diff options
author | Lorry Tar Creator <lorry-tar-importer@lorry> | 2016-04-10 09:28:39 +0000 |
---|---|---|
committer | Lorry Tar Creator <lorry-tar-importer@lorry> | 2016-04-10 09:28:39 +0000 |
commit | 32761a6cee1d0dee366b885b7b9c777e67885688 (patch) | |
tree | d6bec92bebfb216f4126356e55518842c2f476a1 /Source/JavaScriptCore/interpreter/CallFrame.h | |
parent | a4e969f4965059196ca948db781e52f7cfebf19e (diff) | |
download | WebKitGtk-tarball-32761a6cee1d0dee366b885b7b9c777e67885688.tar.gz |
webkitgtk-2.4.11webkitgtk-2.4.11
Diffstat (limited to 'Source/JavaScriptCore/interpreter/CallFrame.h')
-rw-r--r-- | Source/JavaScriptCore/interpreter/CallFrame.h | 258 |
1 files changed, 161 insertions, 97 deletions
diff --git a/Source/JavaScriptCore/interpreter/CallFrame.h b/Source/JavaScriptCore/interpreter/CallFrame.h index 980b92fb2..48fbcd779 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-2015 Apple Inc. All rights reserved. + * Copyright (C) 2003, 2007, 2008, 2011, 2013 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,55 +24,30 @@ #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].object(); } - SUPPRESS_ASAN JSValue unsafeCallee() const { return this[JSStack::Callee].asanUnsafeJSValue(); } + JSObject* callee() const { return this[JSStack::Callee].function(); } CodeBlock* codeBlock() const { return this[JSStack::CodeBlock].Register::codeBlock(); } - SUPPRESS_ASAN CodeBlock* unsafeCodeBlock() const { return this[JSStack::CodeBlock].Register::asanUnsafeCodeBlock(); } - JSScope* scope(int scopeRegisterOffset) const + JSScope* scope() const { - ASSERT(this[scopeRegisterOffset].Register::scope()); - return this[scopeRegisterOffset].Register::scope(); + ASSERT(this[JSStack::ScopeChain].Register::scope()); + return this[JSStack::ScopeChain].Register::scope(); } // Global object in which execution began. @@ -94,33 +69,49 @@ 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(); + } - Exception* exception() const { return vm().exception(); } - bool hadException() const { return !!vm().exception(); } - - Exception* lastException() const { return vm().lastException(); } - void clearLastException() { vm().clearLastException(); } + JSValue exception() const { return vm().exception(); } + bool hadException() const { return !vm().exception().isEmpty(); } - 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 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*&); - + CallFrame* callerFrame() const { return callerFrameAndPC().callerFrame; } static ptrdiff_t callerFrameOffset() { return OBJECT_OFFSETOF(CallerFrameAndPC, callerFrame); } ReturnAddressPtr returnPC() const { return ReturnAddressPtr(callerFrameAndPC().pc); } @@ -129,17 +120,51 @@ namespace JSC { static ptrdiff_t returnPCOffset() { return OBJECT_OFFSETOF(CallerFrameAndPC, pc); } AbstractPC abstractReturnPC(VM& vm) { return AbstractPC(vm, this); } - bool callSiteBitsAreBytecodeOffset() const; - bool callSiteBitsAreCodeOriginIndex() const; + class Location { + public: + static inline uint32_t decode(uint32_t bits); - unsigned callSiteAsRawBits() const; - unsigned unsafeCallSiteAsRawBits() const; - CallSiteIndex callSiteIndex() const; - CallSiteIndex unsafeCallSiteIndex() const; - private: - unsigned callSiteBitsAsBytecodeOffset() const; - public: + 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; + + unsigned locationAsRawBits() const; + unsigned locationAsBytecodeOffset() const; + unsigned locationAsCodeOriginIndex() const; + + void setLocationAsRawBits(unsigned); + void setLocationAsBytecodeOffset(unsigned); + +#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 @@ -151,37 +176,51 @@ namespace JSC { // CodeOrigin(0) if we're in native code. CodeOrigin codeOrigin(); - Register* topOfFrame() + Register* frameExtent() { - if (!codeBlock()) - return registers(); - return topOfFrameInternal(); + if (isVMEntrySentinel() || !codeBlock()) + return registers() - 1; + return frameExtentInternal(); } - Instruction* currentVPC() const; // This only makes sense in the LLInt and baseline. + 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; void setCurrentVPC(Instruction* vpc); +#endif void setCallerFrame(CallFrame* frame) { callerFrameAndPC().callerFrame = frame; } - 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); + 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); } // 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; } @@ -214,36 +253,54 @@ 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] = callee; } + void setCallee(JSObject* callee) { static_cast<Register*>(this)[JSStack::Callee] = Register::withCallee(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&); @@ -252,10 +309,8 @@ 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(); @@ -263,8 +318,6 @@ 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: @@ -285,11 +338,22 @@ 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); } - SUPPRESS_ASAN const CallerFrameAndPC& unsafeCallerFrameAndPC() const { return *reinterpret_cast<const CallerFrameAndPC*>(this); } + + static CodeBlock* vmEntrySentinelCodeBlock() { return reinterpret_cast<CodeBlock*>(s_VMEntrySentinel); } friend class JSStack; + friend class VMInspector; }; } // namespace JSC |