diff options
author | Lorry Tar Creator <lorry-tar-importer@lorry> | 2016-05-24 08:28:08 +0000 |
---|---|---|
committer | Lorry Tar Creator <lorry-tar-importer@lorry> | 2016-05-24 08:28:08 +0000 |
commit | a4e969f4965059196ca948db781e52f7cfebf19e (patch) | |
tree | 6ca352808c8fdc52006a0f33f6ae3c593b23867d /Source/JavaScriptCore/interpreter/CallFrame.h | |
parent | 41386e9cb918eed93b3f13648cbef387e371e451 (diff) | |
download | WebKitGtk-tarball-a4e969f4965059196ca948db781e52f7cfebf19e.tar.gz |
webkitgtk-2.12.3webkitgtk-2.12.3
Diffstat (limited to 'Source/JavaScriptCore/interpreter/CallFrame.h')
-rw-r--r-- | Source/JavaScriptCore/interpreter/CallFrame.h | 258 |
1 files changed, 97 insertions, 161 deletions
diff --git a/Source/JavaScriptCore/interpreter/CallFrame.h b/Source/JavaScriptCore/interpreter/CallFrame.h index 48fbcd779..980b92fb2 100644 --- a/Source/JavaScriptCore/interpreter/CallFrame.h +++ b/Source/JavaScriptCore/interpreter/CallFrame.h @@ -1,7 +1,7 @@ /* * Copyright (C) 1999-2001 Harri Porten (porten@kde.org) * Copyright (C) 2001 Peter Kelly (pmk@post.com) - * Copyright (C) 2003, 2007, 2008, 2011, 2013 Apple Inc. All rights reserved. + * Copyright (C) 2003, 2007, 2008, 2011, 2013-2015 Apple Inc. All rights reserved. * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Library General Public @@ -24,30 +24,55 @@ #define CallFrame_h #include "AbstractPC.h" -#include "VM.h" #include "JSStack.h" #include "MacroAssemblerCodeRef.h" #include "Register.h" #include "StackVisitor.h" +#include "VM.h" +#include "VMEntryRecord.h" namespace JSC { class Arguments; - class JSActivation; class Interpreter; class JSScope; + struct CallSiteIndex { + CallSiteIndex() + : m_bits(UINT_MAX) + { + } + + explicit CallSiteIndex(uint32_t bits) + : m_bits(bits) + { } +#if USE(JSVALUE32_64) + explicit CallSiteIndex(Instruction* instruction) + : m_bits(bitwise_cast<uint32_t>(instruction)) + { } +#endif + + explicit operator bool() const { return m_bits != UINT_MAX; } + + inline uint32_t bits() const { return m_bits; } + + private: + uint32_t m_bits; + }; + // Represents the current state of script execution. // Passed as the first argument to most functions. class ExecState : private Register { public: JSValue calleeAsValue() const { return this[JSStack::Callee].jsValue(); } - JSObject* callee() const { return this[JSStack::Callee].function(); } + JSObject* callee() const { return this[JSStack::Callee].object(); } + SUPPRESS_ASAN JSValue unsafeCallee() const { return this[JSStack::Callee].asanUnsafeJSValue(); } CodeBlock* codeBlock() const { return this[JSStack::CodeBlock].Register::codeBlock(); } - JSScope* scope() const + SUPPRESS_ASAN CodeBlock* unsafeCodeBlock() const { return this[JSStack::CodeBlock].Register::asanUnsafeCodeBlock(); } + JSScope* scope(int scopeRegisterOffset) const { - ASSERT(this[JSStack::ScopeChain].Register::scope()); - return this[JSStack::ScopeChain].Register::scope(); + ASSERT(this[scopeRegisterOffset].Register::scope()); + return this[scopeRegisterOffset].Register::scope(); } // Global object in which execution began. @@ -69,49 +94,33 @@ namespace JSC { // But they're used in many places in legacy code, so they're not going away any time soon. void clearException() { vm().clearException(); } - void clearSupplementaryExceptionInfo() - { - vm().clearExceptionStack(); - } - JSValue exception() const { return vm().exception(); } - bool hadException() const { return !vm().exception().isEmpty(); } + Exception* exception() const { return vm().exception(); } + bool hadException() const { return !!vm().exception(); } + Exception* lastException() const { return vm().lastException(); } + void clearLastException() { vm().clearLastException(); } + + AtomicStringTable* atomicStringTable() const { return vm().atomicStringTable(); } const CommonIdentifiers& propertyNames() const { return *vm().propertyNames; } const MarkedArgumentBuffer& emptyList() const { return *vm().emptyList; } Interpreter* interpreter() { return vm().interpreter; } Heap* heap() { return &vm().heap; } -#ifndef NDEBUG - void dumpCaller(); -#endif - static const HashTable& arrayConstructorTable(VM& vm) { return *vm.arrayConstructorTable; } - static const HashTable& arrayPrototypeTable(VM& vm) { return *vm.arrayPrototypeTable; } - static const HashTable& booleanPrototypeTable(VM& vm) { return *vm.booleanPrototypeTable; } - static const HashTable& dataViewTable(VM& vm) { return *vm.dataViewTable; } - static const HashTable& dateTable(VM& vm) { return *vm.dateTable; } - static const HashTable& dateConstructorTable(VM& vm) { return *vm.dateConstructorTable; } - static const HashTable& errorPrototypeTable(VM& vm) { return *vm.errorPrototypeTable; } - static const HashTable& globalObjectTable(VM& vm) { return *vm.globalObjectTable; } - static const HashTable& jsonTable(VM& vm) { return *vm.jsonTable; } - static const HashTable& numberConstructorTable(VM& vm) { return *vm.numberConstructorTable; } - static const HashTable& numberPrototypeTable(VM& vm) { return *vm.numberPrototypeTable; } - static const HashTable& objectConstructorTable(VM& vm) { return *vm.objectConstructorTable; } - static const HashTable& privateNamePrototypeTable(VM& vm) { return *vm.privateNamePrototypeTable; } - static const HashTable& regExpTable(VM& vm) { return *vm.regExpTable; } - static const HashTable& regExpConstructorTable(VM& vm) { return *vm.regExpConstructorTable; } - static const HashTable& regExpPrototypeTable(VM& vm) { return *vm.regExpPrototypeTable; } - static const HashTable& stringConstructorTable(VM& vm) { return *vm.stringConstructorTable; } -#if ENABLE(PROMISES) - static const HashTable& promisePrototypeTable(VM& vm) { return *vm.promisePrototypeTable; } - static const HashTable& promiseConstructorTable(VM& vm) { return *vm.promiseConstructorTable; } -#endif + static CallFrame* create(Register* callFrameBase) { return static_cast<CallFrame*>(callFrameBase); } Register* registers() { return this; } + const Register* registers() const { return this; } CallFrame& operator=(const Register& r) { *static_cast<Register*>(this) = r; return *this; } - CallFrame* callerFrame() const { return callerFrameAndPC().callerFrame; } + CallFrame* callerFrame() const { return static_cast<CallFrame*>(callerFrameOrVMEntryFrame()); } + void* callerFrameOrVMEntryFrame() const { return callerFrameAndPC().callerFrame; } + SUPPRESS_ASAN void* unsafeCallerFrameOrVMEntryFrame() const { return unsafeCallerFrameAndPC().callerFrame; } + + CallFrame* unsafeCallerFrame(VMEntryFrame*&); + JS_EXPORT_PRIVATE CallFrame* callerFrame(VMEntryFrame*&); + static ptrdiff_t callerFrameOffset() { return OBJECT_OFFSETOF(CallerFrameAndPC, callerFrame); } ReturnAddressPtr returnPC() const { return ReturnAddressPtr(callerFrameAndPC().pc); } @@ -120,51 +129,17 @@ namespace JSC { static ptrdiff_t returnPCOffset() { return OBJECT_OFFSETOF(CallerFrameAndPC, pc); } AbstractPC abstractReturnPC(VM& vm) { return AbstractPC(vm, this); } - class Location { - public: - static inline uint32_t decode(uint32_t bits); - - static inline bool isBytecodeLocation(uint32_t bits); -#if USE(JSVALUE64) - static inline uint32_t encodeAsBytecodeOffset(uint32_t bits); -#else - static inline uint32_t encodeAsBytecodeInstruction(Instruction*); -#endif - - static inline bool isCodeOriginIndex(uint32_t bits); - static inline uint32_t encodeAsCodeOriginIndex(uint32_t bits); - - private: - enum TypeTag { - BytecodeLocationTag = 0, - CodeOriginIndexTag = 1, - }; - - static inline uint32_t encode(TypeTag, uint32_t bits); - - static const uint32_t s_mask = 0x1; -#if USE(JSVALUE64) - static const uint32_t s_shift = 31; - static const uint32_t s_shiftedMask = s_mask << s_shift; -#else - static const uint32_t s_shift = 1; -#endif - }; - - bool hasLocationAsBytecodeOffset() const; - bool hasLocationAsCodeOriginIndex() const; + bool callSiteBitsAreBytecodeOffset() const; + bool callSiteBitsAreCodeOriginIndex() const; - unsigned locationAsRawBits() const; - unsigned locationAsBytecodeOffset() const; - unsigned locationAsCodeOriginIndex() const; - - void setLocationAsRawBits(unsigned); - void setLocationAsBytecodeOffset(unsigned); + unsigned callSiteAsRawBits() const; + unsigned unsafeCallSiteAsRawBits() const; + CallSiteIndex callSiteIndex() const; + CallSiteIndex unsafeCallSiteIndex() const; + private: + unsigned callSiteBitsAsBytecodeOffset() const; + public: -#if ENABLE(DFG_JIT) - unsigned bytecodeOffsetFromCodeOriginIndex(); -#endif - // This will try to get you the bytecode offset, but you should be aware that // this bytecode offset may be bogus in the presence of inlining. This will // also return 0 if the call frame has no notion of bytecode offsets (for @@ -176,51 +151,37 @@ namespace JSC { // CodeOrigin(0) if we're in native code. CodeOrigin codeOrigin(); - Register* frameExtent() + Register* topOfFrame() { - if (isVMEntrySentinel() || !codeBlock()) - return registers() - 1; - return frameExtentInternal(); + if (!codeBlock()) + return registers(); + return topOfFrameInternal(); } - Register* frameExtentInternal(); - -#if USE(JSVALUE32_64) - Instruction* currentVPC() const - { - ASSERT(!isVMEntrySentinel()); - return bitwise_cast<Instruction*>(this[JSStack::ArgumentCount].tag()); - } - void setCurrentVPC(Instruction* vpc) - { - ASSERT(!isVMEntrySentinel()); - this[JSStack::ArgumentCount].tag() = bitwise_cast<int32_t>(vpc); - } -#else - Instruction* currentVPC() const; + Instruction* currentVPC() const; // This only makes sense in the LLInt and baseline. void setCurrentVPC(Instruction* vpc); -#endif void setCallerFrame(CallFrame* frame) { callerFrameAndPC().callerFrame = frame; } - void setScope(JSScope* scope) { static_cast<Register*>(this)[JSStack::ScopeChain] = scope; } - - ALWAYS_INLINE void init(CodeBlock* codeBlock, Instruction* vPC, JSScope* scope, - CallFrame* callerFrame, int argc, JSObject* callee) - { - ASSERT(callerFrame == noCaller() || callerFrame->isVMEntrySentinel() || callerFrame->stack()->containsAddress(this)); - - setCodeBlock(codeBlock); - setScope(scope); - setCallerFrame(callerFrame); - setReturnPC(vPC); // This is either an Instruction* or a pointer into JIT generated code stored as an Instruction*. - setArgumentCountIncludingThis(argc); // original argument count (for the sake of the "arguments" object) - setCallee(callee); + void setScope(int scopeRegisterOffset, JSScope* scope) { static_cast<Register*>(this)[scopeRegisterOffset] = scope; } + + ALWAYS_INLINE void init(CodeBlock* codeBlock, Instruction* vPC, + CallFrame* callerFrame, int argc, JSObject* callee) + { + ASSERT(callerFrame == noCaller() || callerFrame->stack()->containsAddress(this)); + + setCodeBlock(codeBlock); + setCallerFrame(callerFrame); + setReturnPC(vPC); // This is either an Instruction* or a pointer into JIT generated code stored as an Instruction*. + setArgumentCountIncludingThis(argc); // original argument count (for the sake of the "arguments" object) + setCallee(callee); } // Read a register from the codeframe (or constant from the CodeBlock). Register& r(int); + Register& r(VirtualRegister); // Read a register for a non-constant Register& uncheckedR(int); + Register& uncheckedR(VirtualRegister); // Access to arguments as passed. (After capture, arguments may move to a different location.) size_t argumentCount() const { return argumentCountIncludingThis() - 1; } @@ -253,54 +214,36 @@ namespace JSC { this[argumentOffset(argument)] = value; } + JSValue getArgumentUnsafe(size_t argIndex) + { + // User beware! This method does not verify that there is a valid + // argument at the specified argIndex. This is used for debugging + // and verification code only. The caller is expected to know what + // he/she is doing when calling this method. + return this[argumentOffset(argIndex)].jsValue(); + } + static int thisArgumentOffset() { return argumentOffsetIncludingThis(0); } JSValue thisValue() { return this[thisArgumentOffset()].jsValue(); } void setThisValue(JSValue value) { this[thisArgumentOffset()] = value; } + // Under the constructor implemented in C++, thisValue holds the newTarget instead of the automatically constructed value. + // The result of this function is only effective under the "construct" context. + JSValue newTarget() { return thisValue(); } + JSValue argumentAfterCapture(size_t argument); static int offsetFor(size_t argumentCountIncludingThis) { return argumentCountIncludingThis + JSStack::ThisArgument - 1; } - // FIXME: Remove these. - int hostThisRegister() { return thisArgumentOffset(); } - JSValue hostThisValue() { return thisValue(); } - static CallFrame* noCaller() { return 0; } - bool isVMEntrySentinel() const - { - return !!this && codeBlock() == vmEntrySentinelCodeBlock(); - } - - CallFrame* vmEntrySentinelCallerFrame() const - { - ASSERT(isVMEntrySentinel()); - return this[JSStack::ScopeChain].callFrame(); - } - - void initializeVMEntrySentinelFrame(CallFrame* callFrame) - { - setCallerFrame(noCaller()); - setReturnPC(0); - setCodeBlock(vmEntrySentinelCodeBlock()); - static_cast<Register*>(this)[JSStack::ScopeChain] = callFrame; - setCallee(0); - setArgumentCountIncludingThis(0); - } - - CallFrame* callerFrameSkippingVMEntrySentinel() - { - CallFrame* caller = callerFrame(); - if (caller->isVMEntrySentinel()) - return caller->vmEntrySentinelCallerFrame(); - return caller; - } - void setArgumentCountIncludingThis(int count) { static_cast<Register*>(this)[JSStack::ArgumentCount].payload() = count; } - void setCallee(JSObject* callee) { static_cast<Register*>(this)[JSStack::Callee] = Register::withCallee(callee); } + void setCallee(JSObject* callee) { static_cast<Register*>(this)[JSStack::Callee] = callee; } void setCodeBlock(CodeBlock* codeBlock) { static_cast<Register*>(this)[JSStack::CodeBlock] = codeBlock; } void setReturnPC(void* value) { callerFrameAndPC().pc = reinterpret_cast<Instruction*>(value); } + String friendlyFunctionName(); + // CallFrame::iterate() expects a Functor that implements the following method: // StackVisitor::Status operator()(StackVisitor&); @@ -309,8 +252,10 @@ namespace JSC { StackVisitor::visit<Functor>(this, functor); } + void dump(PrintStream&); + JS_EXPORT_PRIVATE const char* describeFrame(); + private: - static const intptr_t s_VMEntrySentinel = 1; #ifndef NDEBUG JSStack* stack(); @@ -318,6 +263,8 @@ namespace JSC { ExecState(); ~ExecState(); + Register* topOfFrameInternal(); + // The following are for internal use in debugging and verification // code only and not meant as an API for general usage: @@ -338,22 +285,11 @@ namespace JSC { return argIndex; } - JSValue getArgumentUnsafe(size_t argIndex) - { - // User beware! This method does not verify that there is a valid - // argument at the specified argIndex. This is used for debugging - // and verification code only. The caller is expected to know what - // he/she is doing when calling this method. - return this[argumentOffset(argIndex)].jsValue(); - } - CallerFrameAndPC& callerFrameAndPC() { return *reinterpret_cast<CallerFrameAndPC*>(this); } const CallerFrameAndPC& callerFrameAndPC() const { return *reinterpret_cast<const CallerFrameAndPC*>(this); } - - static CodeBlock* vmEntrySentinelCodeBlock() { return reinterpret_cast<CodeBlock*>(s_VMEntrySentinel); } + SUPPRESS_ASAN const CallerFrameAndPC& unsafeCallerFrameAndPC() const { return *reinterpret_cast<const CallerFrameAndPC*>(this); } friend class JSStack; - friend class VMInspector; }; } // namespace JSC |