From 8995b83bcbfbb68245f779b64e5517627c6cc6ea Mon Sep 17 00:00:00 2001 From: Simon Hausmann Date: Wed, 17 Oct 2012 16:21:14 +0200 Subject: Imported WebKit commit cf4f8fc6f19b0629f51860cb2d4b25e139d07e00 (http://svn.webkit.org/repository/webkit/trunk@131592) New snapshot that includes the build fixes for Mac OS X 10.6 and earlier as well as the previously cherry-picked changes --- Source/JavaScriptCore/interpreter/CallFrame.cpp | 4 +- Source/JavaScriptCore/interpreter/CallFrame.h | 65 ++++++----- .../JavaScriptCore/interpreter/CallFrameClosure.h | 6 +- Source/JavaScriptCore/interpreter/Interpreter.cpp | 127 ++++++++++++--------- Source/JavaScriptCore/interpreter/Interpreter.h | 16 +-- Source/JavaScriptCore/interpreter/JSStack.cpp | 107 +++++++++++++++++ Source/JavaScriptCore/interpreter/JSStack.h | 124 ++++++++++++++++++++ Source/JavaScriptCore/interpreter/RegisterFile.cpp | 107 ----------------- Source/JavaScriptCore/interpreter/RegisterFile.h | 124 -------------------- Source/JavaScriptCore/interpreter/VMInspector.cpp | 32 +++--- 10 files changed, 368 insertions(+), 344 deletions(-) create mode 100644 Source/JavaScriptCore/interpreter/JSStack.cpp create mode 100644 Source/JavaScriptCore/interpreter/JSStack.h delete mode 100644 Source/JavaScriptCore/interpreter/RegisterFile.cpp delete mode 100644 Source/JavaScriptCore/interpreter/RegisterFile.h (limited to 'Source/JavaScriptCore/interpreter') diff --git a/Source/JavaScriptCore/interpreter/CallFrame.cpp b/Source/JavaScriptCore/interpreter/CallFrame.cpp index 63bc93aeb..6dcf354b3 100644 --- a/Source/JavaScriptCore/interpreter/CallFrame.cpp +++ b/Source/JavaScriptCore/interpreter/CallFrame.cpp @@ -43,9 +43,9 @@ void CallFrame::dumpCaller() dataLog("Callpoint => %s:%d\n", urlString.utf8().data(), signedLineNumber); } -RegisterFile* CallFrame::registerFile() +JSStack* CallFrame::stack() { - return &interpreter()->registerFile(); + return &interpreter()->stack(); } #endif diff --git a/Source/JavaScriptCore/interpreter/CallFrame.h b/Source/JavaScriptCore/interpreter/CallFrame.h index 4758e5bd0..7aa49a9b0 100644 --- a/Source/JavaScriptCore/interpreter/CallFrame.h +++ b/Source/JavaScriptCore/interpreter/CallFrame.h @@ -25,8 +25,8 @@ #include "AbstractPC.h" #include "JSGlobalData.h" +#include "JSStack.h" #include "MacroAssemblerCodeRef.h" -#include "RegisterFile.h" namespace JSC { @@ -39,13 +39,13 @@ namespace JSC { // Passed as the first argument to most functions. class ExecState : private Register { public: - JSValue calleeAsValue() const { return this[RegisterFile::Callee].jsValue(); } - JSObject* callee() const { return this[RegisterFile::Callee].function(); } - CodeBlock* codeBlock() const { return this[RegisterFile::CodeBlock].Register::codeBlock(); } + JSValue calleeAsValue() const { return this[JSStack::Callee].jsValue(); } + JSObject* callee() const { return this[JSStack::Callee].function(); } + CodeBlock* codeBlock() const { return this[JSStack::CodeBlock].Register::codeBlock(); } JSScope* scope() const { - ASSERT(this[RegisterFile::ScopeChain].Register::scope()); - return this[RegisterFile::ScopeChain].Register::scope(); + ASSERT(this[JSStack::ScopeChain].Register::scope()); + return this[JSStack::ScopeChain].Register::scope(); } // Global object in which execution began. @@ -102,11 +102,11 @@ namespace JSC { CallFrame& operator=(const Register& r) { *static_cast(this) = r; return *this; } - CallFrame* callerFrame() const { return this[RegisterFile::CallerFrame].callFrame(); } + CallFrame* callerFrame() const { return this[JSStack::CallerFrame].callFrame(); } #if ENABLE(JIT) || ENABLE(LLINT) - ReturnAddressPtr returnPC() const { return ReturnAddressPtr(this[RegisterFile::ReturnPC].vPC()); } - bool hasReturnPC() const { return !!this[RegisterFile::ReturnPC].vPC(); } - void clearReturnPC() { registers()[RegisterFile::ReturnPC] = static_cast(0); } + ReturnAddressPtr returnPC() const { return ReturnAddressPtr(this[JSStack::ReturnPC].vPC()); } + bool hasReturnPC() const { return !!this[JSStack::ReturnPC].vPC(); } + void clearReturnPC() { registers()[JSStack::ReturnPC] = static_cast(0); } #endif AbstractPC abstractReturnPC(JSGlobalData& globalData) { return AbstractPC(globalData, this); } #if USE(JSVALUE32_64) @@ -116,13 +116,13 @@ namespace JSC { unsigned bytecodeOffsetForNonDFGCode() const { ASSERT(codeBlock()); - return this[RegisterFile::ArgumentCount].tag(); + return this[JSStack::ArgumentCount].tag(); } void setBytecodeOffsetForNonDFGCode(unsigned offset) { ASSERT(codeBlock()); - this[RegisterFile::ArgumentCount].tag() = static_cast(offset); + this[JSStack::ArgumentCount].tag() = static_cast(offset); } #endif @@ -136,8 +136,8 @@ namespace JSC { Register* frameExtentInternal(); #if ENABLE(DFG_JIT) - InlineCallFrame* inlineCallFrame() const { return this[RegisterFile::ReturnPC].asInlineCallFrame(); } - unsigned codeOriginIndexForDFG() const { return this[RegisterFile::ArgumentCount].tag(); } + InlineCallFrame* inlineCallFrame() const { return this[JSStack::ReturnPC].asInlineCallFrame(); } + unsigned codeOriginIndexForDFG() const { return this[JSStack::ArgumentCount].tag(); } #else // This will never be called if !ENABLE(DFG_JIT) since all calls should be guarded by // isInlineCallFrame(). But to make it easier to write code without having a bunch of @@ -151,25 +151,25 @@ namespace JSC { #if USE(JSVALUE32_64) Instruction* currentVPC() const { - return bitwise_cast(this[RegisterFile::ArgumentCount].tag()); + return bitwise_cast(this[JSStack::ArgumentCount].tag()); } void setCurrentVPC(Instruction* vpc) { - this[RegisterFile::ArgumentCount].tag() = bitwise_cast(vpc); + this[JSStack::ArgumentCount].tag() = bitwise_cast(vpc); } #else Instruction* currentVPC() const; void setCurrentVPC(Instruction* vpc); #endif - void setCallerFrame(CallFrame* callerFrame) { static_cast(this)[RegisterFile::CallerFrame] = callerFrame; } - void setScope(JSScope* scope) { static_cast(this)[RegisterFile::ScopeChain] = scope; } + void setCallerFrame(CallFrame* callerFrame) { static_cast(this)[JSStack::CallerFrame] = callerFrame; } + void setScope(JSScope* scope) { static_cast(this)[JSStack::ScopeChain] = scope; } ALWAYS_INLINE void init(CodeBlock* codeBlock, Instruction* vPC, JSScope* scope, CallFrame* callerFrame, int argc, JSObject* callee) { ASSERT(callerFrame); // Use noCaller() rather than 0 for the outer host call frame caller. - ASSERT(callerFrame == noCaller() || callerFrame->removeHostCallFrameFlag()->registerFile()->end() >= this); + ASSERT(callerFrame == noCaller() || callerFrame->removeHostCallFrameFlag()->stack()->end() >= this); setCodeBlock(codeBlock); setScope(scope); @@ -186,10 +186,19 @@ namespace JSC { // Access to arguments as passed. (After capture, arguments may move to a different location.) size_t argumentCount() const { return argumentCountIncludingThis() - 1; } - size_t argumentCountIncludingThis() const { return this[RegisterFile::ArgumentCount].payload(); } + size_t argumentCountIncludingThis() const { return this[JSStack::ArgumentCount].payload(); } static int argumentOffset(int argument) { return s_firstArgumentOffset - argument; } static int argumentOffsetIncludingThis(int argument) { return s_thisArgumentOffset - argument; } + // In the following (argument() and setArgument()), the 'argument' + // parameter is the index of the arguments of the target function of + // this frame. The index starts at 0 for the first arg, 1 for the + // second, etc. + // + // The arguments (in this case) do not include the 'this' value. + // arguments(0) will not fetch the 'this' value. To get/set 'this', + // use thisValue() and setThisValue() below. + JSValue argument(size_t argument) { if (argument >= argumentCount()) @@ -207,7 +216,7 @@ namespace JSC { JSValue argumentAfterCapture(size_t argument); - static int offsetFor(size_t argumentCountIncludingThis) { return argumentCountIncludingThis + RegisterFile::CallFrameHeaderSize; } + static int offsetFor(size_t argumentCountIncludingThis) { return argumentCountIncludingThis + JSStack::CallFrameHeaderSize; } // FIXME: Remove these. int hostThisRegister() { return thisArgumentOffset(); } @@ -219,15 +228,15 @@ namespace JSC { CallFrame* addHostCallFrameFlag() const { return reinterpret_cast(reinterpret_cast(this) | HostCallFrameFlag); } CallFrame* removeHostCallFrameFlag() { return reinterpret_cast(reinterpret_cast(this) & ~HostCallFrameFlag); } - void setArgumentCountIncludingThis(int count) { static_cast(this)[RegisterFile::ArgumentCount].payload() = count; } - void setCallee(JSObject* callee) { static_cast(this)[RegisterFile::Callee] = Register::withCallee(callee); } - void setCodeBlock(CodeBlock* codeBlock) { static_cast(this)[RegisterFile::CodeBlock] = codeBlock; } - void setReturnPC(void* value) { static_cast(this)[RegisterFile::ReturnPC] = (Instruction*)value; } + void setArgumentCountIncludingThis(int count) { static_cast(this)[JSStack::ArgumentCount].payload() = count; } + void setCallee(JSObject* callee) { static_cast(this)[JSStack::Callee] = Register::withCallee(callee); } + void setCodeBlock(CodeBlock* codeBlock) { static_cast(this)[JSStack::CodeBlock] = codeBlock; } + void setReturnPC(void* value) { static_cast(this)[JSStack::ReturnPC] = (Instruction*)value; } #if ENABLE(DFG_JIT) bool isInlineCallFrame(); - void setInlineCallFrame(InlineCallFrame* inlineCallFrame) { static_cast(this)[RegisterFile::ReturnPC] = inlineCallFrame; } + void setInlineCallFrame(InlineCallFrame* inlineCallFrame) { static_cast(this)[JSStack::ReturnPC] = inlineCallFrame; } // Call this to get the semantically correct JS CallFrame* for the // currently executing function. @@ -260,11 +269,11 @@ namespace JSC { private: static const intptr_t HostCallFrameFlag = 1; - static const int s_thisArgumentOffset = -1 - RegisterFile::CallFrameHeaderSize; + static const int s_thisArgumentOffset = -1 - JSStack::CallFrameHeaderSize; static const int s_firstArgumentOffset = s_thisArgumentOffset - 1; #ifndef NDEBUG - RegisterFile* registerFile(); + JSStack* stack(); #endif #if ENABLE(DFG_JIT) bool isInlineCallFrameSlow(); diff --git a/Source/JavaScriptCore/interpreter/CallFrameClosure.h b/Source/JavaScriptCore/interpreter/CallFrameClosure.h index 125193258..157d1b3b9 100644 --- a/Source/JavaScriptCore/interpreter/CallFrameClosure.h +++ b/Source/JavaScriptCore/interpreter/CallFrameClosure.h @@ -52,7 +52,11 @@ struct CallFrameClosure { void resetCallFrame() { newCallFrame->setScope(scope); - for (int i = argumentCountIncludingThis; i < parameterCountIncludingThis; ++i) + // setArgument() takes an arg index that starts from 0 for the first + // argument after the 'this' value. Since both argumentCountIncludingThis + // and parameterCountIncludingThis includes the 'this' value, we need to + // subtract 1 from them to make i a valid argument index for setArgument(). + for (int i = argumentCountIncludingThis-1; i < parameterCountIncludingThis-1; ++i) newCallFrame->setArgument(i, jsUndefined()); } }; diff --git a/Source/JavaScriptCore/interpreter/Interpreter.cpp b/Source/JavaScriptCore/interpreter/Interpreter.cpp index 3107a5dab..00b283393 100644 --- a/Source/JavaScriptCore/interpreter/Interpreter.cpp +++ b/Source/JavaScriptCore/interpreter/Interpreter.cpp @@ -88,10 +88,10 @@ static int depth(CodeBlock* codeBlock, JSScope* sc) return sc->localDepth(); } -ALWAYS_INLINE CallFrame* Interpreter::slideRegisterWindowForCall(CodeBlock* newCodeBlock, RegisterFile* registerFile, CallFrame* callFrame, size_t registerOffset, int argumentCountIncludingThis) +ALWAYS_INLINE CallFrame* Interpreter::slideRegisterWindowForCall(CodeBlock* newCodeBlock, JSStack* stack, CallFrame* callFrame, size_t registerOffset, int argumentCountIncludingThis) { // This ensures enough space for the worst case scenario of zero arguments passed by the caller. - if (!registerFile->grow(callFrame->registers() + registerOffset + newCodeBlock->numParameters() + newCodeBlock->m_numCalleeRegisters)) + if (!stack->grow(callFrame->registers() + registerOffset + newCodeBlock->numParameters() + newCodeBlock->m_numCalleeRegisters)) return 0; if (argumentCountIncludingThis >= newCodeBlock->numParameters()) { @@ -163,15 +163,15 @@ JSValue eval(CallFrame* callFrame) JSValue thisValue = callerFrame->thisValue(); ASSERT(isValidThisObject(thisValue, callFrame)); Interpreter* interpreter = callFrame->globalData().interpreter; - return interpreter->execute(eval, callFrame, thisValue, callerScopeChain, callFrame->registers() - interpreter->registerFile().begin() + 1 + RegisterFile::CallFrameHeaderSize); + return interpreter->execute(eval, callFrame, thisValue, callerScopeChain, callFrame->registers() - interpreter->stack().begin() + 1 + JSStack::CallFrameHeaderSize); } -CallFrame* loadVarargs(CallFrame* callFrame, RegisterFile* registerFile, JSValue thisValue, JSValue arguments, int firstFreeRegister) +CallFrame* loadVarargs(CallFrame* callFrame, JSStack* stack, JSValue thisValue, JSValue arguments, int firstFreeRegister) { if (!arguments) { // f.apply(x, arguments), with arguments unmodified. unsigned argumentCountIncludingThis = callFrame->argumentCountIncludingThis(); - CallFrame* newCallFrame = CallFrame::create(callFrame->registers() + firstFreeRegister + argumentCountIncludingThis + RegisterFile::CallFrameHeaderSize); - if (argumentCountIncludingThis > Arguments::MaxArguments + 1 || !registerFile->grow(newCallFrame->registers())) { + CallFrame* newCallFrame = CallFrame::create(callFrame->registers() + firstFreeRegister + argumentCountIncludingThis + JSStack::CallFrameHeaderSize); + if (argumentCountIncludingThis > Arguments::MaxArguments + 1 || !stack->grow(newCallFrame->registers())) { callFrame->globalData().exception = createStackOverflowError(callFrame); return 0; } @@ -184,8 +184,8 @@ CallFrame* loadVarargs(CallFrame* callFrame, RegisterFile* registerFile, JSValue } if (arguments.isUndefinedOrNull()) { - CallFrame* newCallFrame = CallFrame::create(callFrame->registers() + firstFreeRegister + 1 + RegisterFile::CallFrameHeaderSize); - if (!registerFile->grow(newCallFrame->registers())) { + CallFrame* newCallFrame = CallFrame::create(callFrame->registers() + firstFreeRegister + 1 + JSStack::CallFrameHeaderSize); + if (!stack->grow(newCallFrame->registers())) { callFrame->globalData().exception = createStackOverflowError(callFrame); return 0; } @@ -203,7 +203,7 @@ CallFrame* loadVarargs(CallFrame* callFrame, RegisterFile* registerFile, JSValue Arguments* argsObject = asArguments(arguments); unsigned argCount = argsObject->length(callFrame); CallFrame* newCallFrame = CallFrame::create(callFrame->registers() + firstFreeRegister + CallFrame::offsetFor(argCount + 1)); - if (argCount > Arguments::MaxArguments || !registerFile->grow(newCallFrame->registers())) { + if (argCount > Arguments::MaxArguments || !stack->grow(newCallFrame->registers())) { callFrame->globalData().exception = createStackOverflowError(callFrame); return 0; } @@ -217,7 +217,7 @@ CallFrame* loadVarargs(CallFrame* callFrame, RegisterFile* registerFile, JSValue JSArray* array = asArray(arguments); unsigned argCount = array->length(); CallFrame* newCallFrame = CallFrame::create(callFrame->registers() + firstFreeRegister + CallFrame::offsetFor(argCount + 1)); - if (argCount > Arguments::MaxArguments || !registerFile->grow(newCallFrame->registers())) { + if (argCount > Arguments::MaxArguments || !stack->grow(newCallFrame->registers())) { callFrame->globalData().exception = createStackOverflowError(callFrame); return 0; } @@ -230,7 +230,7 @@ CallFrame* loadVarargs(CallFrame* callFrame, RegisterFile* registerFile, JSValue JSObject* argObject = asObject(arguments); unsigned argCount = argObject->get(callFrame, callFrame->propertyNames().length).toUInt32(callFrame); CallFrame* newCallFrame = CallFrame::create(callFrame->registers() + firstFreeRegister + CallFrame::offsetFor(argCount + 1)); - if (argCount > Arguments::MaxArguments || !registerFile->grow(newCallFrame->registers())) { + if (argCount > Arguments::MaxArguments || !stack->grow(newCallFrame->registers())) { callFrame->globalData().exception = createStackOverflowError(callFrame); return 0; } @@ -301,8 +301,8 @@ void Interpreter::dumpRegisters(CallFrame* callFrame) const Register* it; const Register* end; - it = callFrame->registers() - RegisterFile::CallFrameHeaderSize - callFrame->argumentCountIncludingThis(); - end = callFrame->registers() - RegisterFile::CallFrameHeaderSize; + it = callFrame->registers() - JSStack::CallFrameHeaderSize - callFrame->argumentCountIncludingThis(); + end = callFrame->registers() - JSStack::CallFrameHeaderSize; while (it < end) { JSValue v = it->jsValue(); int registerNumber = it - callFrame->registers(); @@ -710,7 +710,7 @@ NEVER_INLINE HandlerInfo* Interpreter::throwException(CallFrame*& callFrame, JSV Register* callerHighWaterMark = callerFrame->registers() + codeBlock->m_numCalleeRegisters; highWaterMark = max(highWaterMark, callerHighWaterMark); } - m_registerFile.shrink(highWaterMark); + m_stack.shrink(highWaterMark); // Unwind the scope chain within the exception handler's call frame. JSScope* scope = callFrame->scope(); @@ -738,8 +738,25 @@ static inline JSObject* checkedReturn(JSObject* returnValue) return returnValue; } +class SamplingScope { +public: + SamplingScope(Interpreter* interpreter) + : m_interpreter(interpreter) + { + interpreter->startSampling(); + } + ~SamplingScope() + { + m_interpreter->stopSampling(); + } +private: + Interpreter* m_interpreter; +}; + JSValue Interpreter::execute(ProgramExecutable* program, CallFrame* callFrame, JSObject* thisObj) { + SamplingScope samplingScope(this); + JSScope* scope = callFrame->scope(); ASSERT(isValidThisObject(thisObj, callFrame)); ASSERT(!scope->globalData()->exception); @@ -863,13 +880,13 @@ failedJSONP: CodeBlock* codeBlock = &program->generatedBytecode(); // Reserve stack space for this invocation: - Register* oldEnd = m_registerFile.end(); - Register* newEnd = oldEnd + codeBlock->numParameters() + RegisterFile::CallFrameHeaderSize + codeBlock->m_numCalleeRegisters; - if (!m_registerFile.grow(newEnd)) + Register* oldEnd = m_stack.end(); + Register* newEnd = oldEnd + codeBlock->numParameters() + JSStack::CallFrameHeaderSize + codeBlock->m_numCalleeRegisters; + if (!m_stack.grow(newEnd)) return checkedReturn(throwStackOverflowError(callFrame)); // Push the call frame for this invocation: - CallFrame* newCallFrame = CallFrame::create(oldEnd + codeBlock->numParameters() + RegisterFile::CallFrameHeaderSize); + CallFrame* newCallFrame = CallFrame::create(oldEnd + codeBlock->numParameters() + JSStack::CallFrameHeaderSize); ASSERT(codeBlock->numParameters() == 1); // 1 parameter for 'this'. newCallFrame->init(codeBlock, 0, scope, CallFrame::noCaller(), codeBlock->numParameters(), 0); newCallFrame->setThisValue(thisObj); @@ -883,11 +900,11 @@ failedJSONP: { SamplingTool::CallRecord callRecord(m_sampler.get()); - m_reentryDepth++; + m_reentryDepth++; #if ENABLE(LLINT_C_LOOP) result = LLInt::CLoop::execute(newCallFrame, llint_program_prologue); #elif ENABLE(JIT) - result = program->generatedJITCode().execute(&m_registerFile, newCallFrame, scope->globalData()); + result = program->generatedJITCode().execute(&m_stack, newCallFrame, scope->globalData()); #endif // ENABLE(JIT) m_reentryDepth--; @@ -896,7 +913,7 @@ failedJSONP: if (Profiler* profiler = callFrame->globalData().enabledProfiler()) profiler->didExecute(callFrame, program->sourceURL(), program->lineNo()); - m_registerFile.shrink(oldEnd); + m_stack.shrink(oldEnd); return checkedReturn(result); } @@ -912,13 +929,13 @@ JSValue Interpreter::executeCall(CallFrame* callFrame, JSObject* function, CallT if (m_reentryDepth >= MaxSmallThreadReentryDepth && m_reentryDepth >= callFrame->globalData().maxReentryDepth) return checkedReturn(throwStackOverflowError(callFrame)); - Register* oldEnd = m_registerFile.end(); + Register* oldEnd = m_stack.end(); ASSERT(callFrame->frameExtent() <= oldEnd || callFrame == callFrame->scope()->globalObject()->globalExec()); int argCount = 1 + args.size(); // implicit "this" parameter - size_t registerOffset = argCount + RegisterFile::CallFrameHeaderSize; + size_t registerOffset = argCount + JSStack::CallFrameHeaderSize; CallFrame* newCallFrame = CallFrame::create(oldEnd + registerOffset); - if (!m_registerFile.grow(newCallFrame->registers())) + if (!m_stack.grow(newCallFrame->registers())) return checkedReturn(throwStackOverflowError(callFrame)); newCallFrame->setThisValue(thisValue); @@ -932,14 +949,14 @@ JSValue Interpreter::executeCall(CallFrame* callFrame, JSObject* function, CallT JSObject* compileError = callData.js.functionExecutable->compileForCall(callFrame, callDataScope); if (UNLIKELY(!!compileError)) { - m_registerFile.shrink(oldEnd); + m_stack.shrink(oldEnd); return checkedReturn(throwError(callFrame, compileError)); } CodeBlock* newCodeBlock = &callData.js.functionExecutable->generatedBytecodeForCall(); - newCallFrame = slideRegisterWindowForCall(newCodeBlock, &m_registerFile, newCallFrame, 0, argCount); + newCallFrame = slideRegisterWindowForCall(newCodeBlock, &m_stack, newCallFrame, 0, argCount); if (UNLIKELY(!newCallFrame)) { - m_registerFile.shrink(oldEnd); + m_stack.shrink(oldEnd); return checkedReturn(throwStackOverflowError(callFrame)); } @@ -958,7 +975,7 @@ JSValue Interpreter::executeCall(CallFrame* callFrame, JSObject* function, CallT #if ENABLE(LLINT_C_LOOP) result = LLInt::CLoop::execute(newCallFrame, llint_function_for_call_prologue); #elif ENABLE(JIT) - result = callData.js.functionExecutable->generatedJITCodeForCall().execute(&m_registerFile, newCallFrame, callDataScope->globalData()); + result = callData.js.functionExecutable->generatedJITCodeForCall().execute(&m_stack, newCallFrame, callDataScope->globalData()); #endif // ENABLE(JIT) m_reentryDepth--; @@ -967,7 +984,7 @@ JSValue Interpreter::executeCall(CallFrame* callFrame, JSObject* function, CallT if (Profiler* profiler = callFrame->globalData().enabledProfiler()) profiler->didExecute(callFrame, function); - m_registerFile.shrink(oldEnd); + m_stack.shrink(oldEnd); return checkedReturn(result); } @@ -991,7 +1008,7 @@ JSValue Interpreter::executeCall(CallFrame* callFrame, JSObject* function, CallT if (Profiler* profiler = callFrame->globalData().enabledProfiler()) profiler->didExecute(callFrame, function); - m_registerFile.shrink(oldEnd); + m_stack.shrink(oldEnd); return checkedReturn(result); } @@ -1007,11 +1024,11 @@ JSObject* Interpreter::executeConstruct(CallFrame* callFrame, JSObject* construc if (m_reentryDepth >= MaxSmallThreadReentryDepth && m_reentryDepth >= callFrame->globalData().maxReentryDepth) return checkedReturn(throwStackOverflowError(callFrame)); - Register* oldEnd = m_registerFile.end(); + Register* oldEnd = m_stack.end(); int argCount = 1 + args.size(); // implicit "this" parameter - size_t registerOffset = argCount + RegisterFile::CallFrameHeaderSize; + size_t registerOffset = argCount + JSStack::CallFrameHeaderSize; - if (!m_registerFile.grow(oldEnd + registerOffset)) + if (!m_stack.grow(oldEnd + registerOffset)) return checkedReturn(throwStackOverflowError(callFrame)); CallFrame* newCallFrame = CallFrame::create(oldEnd + registerOffset); @@ -1026,14 +1043,14 @@ JSObject* Interpreter::executeConstruct(CallFrame* callFrame, JSObject* construc JSObject* compileError = constructData.js.functionExecutable->compileForConstruct(callFrame, constructDataScope); if (UNLIKELY(!!compileError)) { - m_registerFile.shrink(oldEnd); + m_stack.shrink(oldEnd); return checkedReturn(throwError(callFrame, compileError)); } CodeBlock* newCodeBlock = &constructData.js.functionExecutable->generatedBytecodeForConstruct(); - newCallFrame = slideRegisterWindowForCall(newCodeBlock, &m_registerFile, newCallFrame, 0, argCount); + newCallFrame = slideRegisterWindowForCall(newCodeBlock, &m_stack, newCallFrame, 0, argCount); if (UNLIKELY(!newCallFrame)) { - m_registerFile.shrink(oldEnd); + m_stack.shrink(oldEnd); return checkedReturn(throwStackOverflowError(callFrame)); } @@ -1052,7 +1069,7 @@ JSObject* Interpreter::executeConstruct(CallFrame* callFrame, JSObject* construc #if ENABLE(LLINT_C_LOOP) result = LLInt::CLoop::execute(newCallFrame, llint_function_for_construct_prologue); #elif ENABLE(JIT) - result = constructData.js.functionExecutable->generatedJITCodeForConstruct().execute(&m_registerFile, newCallFrame, constructDataScope->globalData()); + result = constructData.js.functionExecutable->generatedJITCodeForConstruct().execute(&m_stack, newCallFrame, constructDataScope->globalData()); #endif // ENABLE(JIT) m_reentryDepth--; } @@ -1060,7 +1077,7 @@ JSObject* Interpreter::executeConstruct(CallFrame* callFrame, JSObject* construc if (Profiler* profiler = callFrame->globalData().enabledProfiler()) profiler->didExecute(callFrame, constructor); - m_registerFile.shrink(oldEnd); + m_stack.shrink(oldEnd); if (callFrame->hadException()) return 0; ASSERT(result.isObject()); @@ -1087,7 +1104,7 @@ JSObject* Interpreter::executeConstruct(CallFrame* callFrame, JSObject* construc if (Profiler* profiler = callFrame->globalData().enabledProfiler()) profiler->didExecute(callFrame, constructor); - m_registerFile.shrink(oldEnd); + m_stack.shrink(oldEnd); if (callFrame->hadException()) return 0; ASSERT(result.isObject()); @@ -1106,11 +1123,11 @@ CallFrameClosure Interpreter::prepareForRepeatCall(FunctionExecutable* functionE return CallFrameClosure(); } - Register* oldEnd = m_registerFile.end(); - size_t registerOffset = argumentCountIncludingThis + RegisterFile::CallFrameHeaderSize; + Register* oldEnd = m_stack.end(); + size_t registerOffset = argumentCountIncludingThis + JSStack::CallFrameHeaderSize; CallFrame* newCallFrame = CallFrame::create(oldEnd + registerOffset); - if (!m_registerFile.grow(newCallFrame->registers())) { + if (!m_stack.grow(newCallFrame->registers())) { throwStackOverflowError(callFrame); return CallFrameClosure(); } @@ -1118,15 +1135,15 @@ CallFrameClosure Interpreter::prepareForRepeatCall(FunctionExecutable* functionE JSObject* error = functionExecutable->compileForCall(callFrame, scope); if (error) { throwError(callFrame, error); - m_registerFile.shrink(oldEnd); + m_stack.shrink(oldEnd); return CallFrameClosure(); } CodeBlock* codeBlock = &functionExecutable->generatedBytecodeForCall(); - newCallFrame = slideRegisterWindowForCall(codeBlock, &m_registerFile, newCallFrame, 0, argumentCountIncludingThis); + newCallFrame = slideRegisterWindowForCall(codeBlock, &m_stack, newCallFrame, 0, argumentCountIncludingThis); if (UNLIKELY(!newCallFrame)) { throwStackOverflowError(callFrame); - m_registerFile.shrink(oldEnd); + m_stack.shrink(oldEnd); return CallFrameClosure(); } newCallFrame->init(codeBlock, 0, scope, callFrame->addHostCallFrameFlag(), argumentCountIncludingThis, function); @@ -1137,6 +1154,8 @@ CallFrameClosure Interpreter::prepareForRepeatCall(FunctionExecutable* functionE JSValue Interpreter::execute(CallFrameClosure& closure) { + SamplingScope samplingScope(this); + ASSERT(!closure.oldCallFrame->globalData().isCollectorBusy()); if (closure.oldCallFrame->globalData().isCollectorBusy()) return jsNull(); @@ -1154,7 +1173,7 @@ JSValue Interpreter::execute(CallFrameClosure& closure) #if ENABLE(LLINT_C_LOOP) result = LLInt::CLoop::execute(closure.newCallFrame, llint_function_for_call_prologue); #elif ENABLE(JIT) - result = closure.functionExecutable->generatedJITCodeForCall().execute(&m_registerFile, closure.newCallFrame, closure.globalData); + result = closure.functionExecutable->generatedJITCodeForCall().execute(&m_stack, closure.newCallFrame, closure.globalData); #endif // ENABLE(JIT) m_reentryDepth--; } @@ -1167,11 +1186,13 @@ JSValue Interpreter::execute(CallFrameClosure& closure) void Interpreter::endRepeatCall(CallFrameClosure& closure) { closure.globalData->topCallFrame = closure.oldCallFrame; - m_registerFile.shrink(closure.oldEnd); + m_stack.shrink(closure.oldEnd); } JSValue Interpreter::execute(EvalExecutable* eval, CallFrame* callFrame, JSValue thisValue, JSScope* scope, int globalRegisterOffset) { + SamplingScope samplingScope(this); + ASSERT(isValidThisObject(thisValue, callFrame)); ASSERT(!scope->globalData()->exception); ASSERT(!callFrame->globalData().isCollectorBusy()); @@ -1222,12 +1243,12 @@ JSValue Interpreter::execute(EvalExecutable* eval, CallFrame* callFrame, JSValue } } - Register* oldEnd = m_registerFile.end(); - Register* newEnd = m_registerFile.begin() + globalRegisterOffset + codeBlock->m_numCalleeRegisters; - if (!m_registerFile.grow(newEnd)) + Register* oldEnd = m_stack.end(); + Register* newEnd = m_stack.begin() + globalRegisterOffset + codeBlock->m_numCalleeRegisters; + if (!m_stack.grow(newEnd)) return checkedReturn(throwStackOverflowError(callFrame)); - CallFrame* newCallFrame = CallFrame::create(m_registerFile.begin() + globalRegisterOffset); + CallFrame* newCallFrame = CallFrame::create(m_stack.begin() + globalRegisterOffset); ASSERT(codeBlock->numParameters() == 1); // 1 parameter for 'this'. newCallFrame->init(codeBlock, 0, scope, callFrame->addHostCallFrameFlag(), codeBlock->numParameters(), 0); @@ -1247,7 +1268,7 @@ JSValue Interpreter::execute(EvalExecutable* eval, CallFrame* callFrame, JSValue #if ENABLE(LLINT_C_LOOP) result = LLInt::CLoop::execute(newCallFrame, llint_eval_prologue); #elif ENABLE(JIT) - result = eval->generatedJITCode().execute(&m_registerFile, newCallFrame, scope->globalData()); + result = eval->generatedJITCode().execute(&m_stack, newCallFrame, scope->globalData()); #endif // ENABLE(JIT) m_reentryDepth--; } @@ -1255,7 +1276,7 @@ JSValue Interpreter::execute(EvalExecutable* eval, CallFrame* callFrame, JSValue if (Profiler* profiler = callFrame->globalData().enabledProfiler()) profiler->didExecute(callFrame, eval->sourceURL(), eval->lineNo()); - m_registerFile.shrink(oldEnd); + m_stack.shrink(oldEnd); return checkedReturn(result); } diff --git a/Source/JavaScriptCore/interpreter/Interpreter.h b/Source/JavaScriptCore/interpreter/Interpreter.h index f27ae8206..11c6f078a 100644 --- a/Source/JavaScriptCore/interpreter/Interpreter.h +++ b/Source/JavaScriptCore/interpreter/Interpreter.h @@ -35,9 +35,9 @@ #include "JSFunction.h" #include "JSValue.h" #include "JSObject.h" +#include "JSStack.h" #include "LLIntData.h" #include "Opcode.h" -#include "RegisterFile.h" #include #include @@ -189,7 +189,7 @@ namespace JSC { void initialize(bool canUseJIT); - RegisterFile& registerFile() { return m_registerFile; } + JSStack& stack() { return m_stack; } Opcode getOpcode(OpcodeID id) { @@ -249,14 +249,10 @@ namespace JSC { NEVER_INLINE bool unwindCallFrame(CallFrame*&, JSValue, unsigned& bytecodeOffset, CodeBlock*&); - static ALWAYS_INLINE CallFrame* slideRegisterWindowForCall(CodeBlock*, RegisterFile*, CallFrame*, size_t registerOffset, int argc); + static ALWAYS_INLINE CallFrame* slideRegisterWindowForCall(CodeBlock*, JSStack*, CallFrame*, size_t registerOffset, int argc); static CallFrame* findFunctionCallFrameFromVMCode(CallFrame*, JSFunction*); -#if !ENABLE(LLINT_C_LOOP) - JSValue privateExecute(ExecutionFlag, RegisterFile*, CallFrame*); -#endif - void dumpRegisters(CallFrame*); bool isCallBytecode(Opcode opcode) { return opcode == getOpcode(op_call) || opcode == getOpcode(op_construct) || opcode == getOpcode(op_call_eval); } @@ -267,7 +263,7 @@ namespace JSC { int m_reentryDepth; - RegisterFile m_registerFile; + JSStack m_stack; #if ENABLE(COMPUTED_GOTO_OPCODES) && ENABLE(LLINT) Opcode* m_opcodeTable; // Maps OpcodeID => Opcode for compiling @@ -287,11 +283,11 @@ namespace JSC { inline JSValue Interpreter::execute(EvalExecutable* eval, CallFrame* callFrame, JSValue thisValue, JSScope* scope) { - return execute(eval, callFrame, thisValue, scope, m_registerFile.size() + 1 + RegisterFile::CallFrameHeaderSize); + return execute(eval, callFrame, thisValue, scope, m_stack.size() + 1 + JSStack::CallFrameHeaderSize); } JSValue eval(CallFrame*); - CallFrame* loadVarargs(CallFrame*, RegisterFile*, JSValue thisValue, JSValue arguments, int firstFreeRegister); + CallFrame* loadVarargs(CallFrame*, JSStack*, JSValue thisValue, JSValue arguments, int firstFreeRegister); } // namespace JSC diff --git a/Source/JavaScriptCore/interpreter/JSStack.cpp b/Source/JavaScriptCore/interpreter/JSStack.cpp new file mode 100644 index 000000000..5dd708a48 --- /dev/null +++ b/Source/JavaScriptCore/interpreter/JSStack.cpp @@ -0,0 +1,107 @@ +/* + * Copyright (C) 2008 Apple Inc. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of Apple Computer, Inc. ("Apple") nor the names of + * its contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY APPLE AND ITS CONTRIBUTORS "AS IS" AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL APPLE OR ITS CONTRIBUTORS BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include "config.h" +#include "JSStack.h" + +#include "ConservativeRoots.h" +#include "Interpreter.h" + +namespace JSC { + +static size_t committedBytesCount = 0; + +static Mutex& stackStatisticsMutex() +{ + DEFINE_STATIC_LOCAL(Mutex, staticMutex, ()); + return staticMutex; +} + +JSStack::~JSStack() +{ + void* base = m_reservation.base(); + m_reservation.decommit(base, reinterpret_cast(m_commitEnd) - reinterpret_cast(base)); + addToCommittedByteCount(-(reinterpret_cast(m_commitEnd) - reinterpret_cast(base))); + m_reservation.deallocate(); +} + +bool JSStack::growSlowCase(Register* newEnd) +{ + if (newEnd <= m_commitEnd) { + m_end = newEnd; + return true; + } + + long delta = roundUpAllocationSize(reinterpret_cast(newEnd) - reinterpret_cast(m_commitEnd), commitSize); + if (reinterpret_cast(m_commitEnd) + delta > static_cast(m_reservation.base()) + m_reservation.size()) + return false; + + m_reservation.commit(m_commitEnd, delta); + addToCommittedByteCount(delta); + m_commitEnd = reinterpret_cast_ptr(reinterpret_cast(m_commitEnd) + delta); + m_end = newEnd; + return true; +} + +void JSStack::gatherConservativeRoots(ConservativeRoots& conservativeRoots) +{ + conservativeRoots.add(begin(), end()); +} + +void JSStack::gatherConservativeRoots(ConservativeRoots& conservativeRoots, JITStubRoutineSet& jitStubRoutines, DFGCodeBlocks& dfgCodeBlocks) +{ + conservativeRoots.add(begin(), end(), jitStubRoutines, dfgCodeBlocks); +} + +void JSStack::releaseExcessCapacity() +{ + ptrdiff_t delta = reinterpret_cast(m_commitEnd) - reinterpret_cast(m_reservation.base()); + m_reservation.decommit(m_reservation.base(), delta); + addToCommittedByteCount(-delta); + m_commitEnd = static_cast(m_reservation.base()); +} + +void JSStack::initializeThreading() +{ + stackStatisticsMutex(); +} + +size_t JSStack::committedByteCount() +{ + MutexLocker locker(stackStatisticsMutex()); + return committedBytesCount; +} + +void JSStack::addToCommittedByteCount(long byteCount) +{ + MutexLocker locker(stackStatisticsMutex()); + ASSERT(static_cast(committedBytesCount) + byteCount > -1); + committedBytesCount += byteCount; +} + +} // namespace JSC diff --git a/Source/JavaScriptCore/interpreter/JSStack.h b/Source/JavaScriptCore/interpreter/JSStack.h new file mode 100644 index 000000000..86fa40be7 --- /dev/null +++ b/Source/JavaScriptCore/interpreter/JSStack.h @@ -0,0 +1,124 @@ +/* + * Copyright (C) 2008, 2009 Apple Inc. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of Apple Computer, Inc. ("Apple") nor the names of + * its contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY APPLE AND ITS CONTRIBUTORS "AS IS" AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL APPLE OR ITS CONTRIBUTORS BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef JSStack_h +#define JSStack_h + +#include "ExecutableAllocator.h" +#include "Register.h" +#include +#include +#include + +namespace JSC { + + class ConservativeRoots; + class DFGCodeBlocks; + class JITStubRoutineSet; + class LLIntOffsetsExtractor; + + class JSStack { + WTF_MAKE_NONCOPYABLE(JSStack); + public: + enum CallFrameHeaderEntry { + CallFrameHeaderSize = 6, + + ArgumentCount = -6, + CallerFrame = -5, + Callee = -4, + ScopeChain = -3, + ReturnPC = -2, // This is either an Instruction* or a pointer into JIT generated code stored as an Instruction*. + CodeBlock = -1, + }; + + static const size_t defaultCapacity = 512 * 1024; + static const size_t commitSize = 16 * 1024; + // Allow 8k of excess registers before we start trying to reap the stack + static const ptrdiff_t maxExcessCapacity = 8 * 1024; + + JSStack(size_t capacity = defaultCapacity); + ~JSStack(); + + void gatherConservativeRoots(ConservativeRoots&); + void gatherConservativeRoots(ConservativeRoots&, JITStubRoutineSet&, DFGCodeBlocks&); + + Register* begin() const { return static_cast(m_reservation.base()); } + Register* end() const { return m_end; } + size_t size() const { return end() - begin(); } + + bool grow(Register*); + void shrink(Register*); + + static size_t committedByteCount(); + static void initializeThreading(); + + Register* const * addressOfEnd() const + { + return &m_end; + } + + private: + friend class LLIntOffsetsExtractor; + + bool growSlowCase(Register*); + void releaseExcessCapacity(); + void addToCommittedByteCount(long); + Register* m_end; + Register* m_commitEnd; + PageReservation m_reservation; + }; + + inline JSStack::JSStack(size_t capacity) + : m_end(0) + { + ASSERT(capacity && isPageAligned(capacity)); + + m_reservation = PageReservation::reserve(roundUpAllocationSize(capacity * sizeof(Register), commitSize), OSAllocator::JSVMStackPages); + m_end = static_cast(m_reservation.base()); + m_commitEnd = static_cast(m_reservation.base()); + } + + inline void JSStack::shrink(Register* newEnd) + { + if (newEnd >= m_end) + return; + m_end = newEnd; + if (m_end == m_reservation.base() && (m_commitEnd - begin()) >= maxExcessCapacity) + releaseExcessCapacity(); + } + + inline bool JSStack::grow(Register* newEnd) + { + if (newEnd <= m_end) + return true; + return growSlowCase(newEnd); + } + +} // namespace JSC + +#endif // JSStack_h diff --git a/Source/JavaScriptCore/interpreter/RegisterFile.cpp b/Source/JavaScriptCore/interpreter/RegisterFile.cpp deleted file mode 100644 index dacb53872..000000000 --- a/Source/JavaScriptCore/interpreter/RegisterFile.cpp +++ /dev/null @@ -1,107 +0,0 @@ -/* - * Copyright (C) 2008 Apple Inc. All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. Neither the name of Apple Computer, Inc. ("Apple") nor the names of - * its contributors may be used to endorse or promote products derived - * from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY APPLE AND ITS CONTRIBUTORS "AS IS" AND ANY - * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED - * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL APPLE OR ITS CONTRIBUTORS BE LIABLE FOR ANY - * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES - * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; - * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND - * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF - * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -#include "config.h" -#include "RegisterFile.h" - -#include "ConservativeRoots.h" -#include "Interpreter.h" - -namespace JSC { - -static size_t committedBytesCount = 0; - -static Mutex& registerFileStatisticsMutex() -{ - DEFINE_STATIC_LOCAL(Mutex, staticMutex, ()); - return staticMutex; -} - -RegisterFile::~RegisterFile() -{ - void* base = m_reservation.base(); - m_reservation.decommit(base, reinterpret_cast(m_commitEnd) - reinterpret_cast(base)); - addToCommittedByteCount(-(reinterpret_cast(m_commitEnd) - reinterpret_cast(base))); - m_reservation.deallocate(); -} - -bool RegisterFile::growSlowCase(Register* newEnd) -{ - if (newEnd <= m_commitEnd) { - m_end = newEnd; - return true; - } - - long delta = roundUpAllocationSize(reinterpret_cast(newEnd) - reinterpret_cast(m_commitEnd), commitSize); - if (reinterpret_cast(m_commitEnd) + delta > static_cast(m_reservation.base()) + m_reservation.size()) - return false; - - m_reservation.commit(m_commitEnd, delta); - addToCommittedByteCount(delta); - m_commitEnd = reinterpret_cast_ptr(reinterpret_cast(m_commitEnd) + delta); - m_end = newEnd; - return true; -} - -void RegisterFile::gatherConservativeRoots(ConservativeRoots& conservativeRoots) -{ - conservativeRoots.add(begin(), end()); -} - -void RegisterFile::gatherConservativeRoots(ConservativeRoots& conservativeRoots, JITStubRoutineSet& jitStubRoutines, DFGCodeBlocks& dfgCodeBlocks) -{ - conservativeRoots.add(begin(), end(), jitStubRoutines, dfgCodeBlocks); -} - -void RegisterFile::releaseExcessCapacity() -{ - ptrdiff_t delta = reinterpret_cast(m_commitEnd) - reinterpret_cast(m_reservation.base()); - m_reservation.decommit(m_reservation.base(), delta); - addToCommittedByteCount(-delta); - m_commitEnd = static_cast(m_reservation.base()); -} - -void RegisterFile::initializeThreading() -{ - registerFileStatisticsMutex(); -} - -size_t RegisterFile::committedByteCount() -{ - MutexLocker locker(registerFileStatisticsMutex()); - return committedBytesCount; -} - -void RegisterFile::addToCommittedByteCount(long byteCount) -{ - MutexLocker locker(registerFileStatisticsMutex()); - ASSERT(static_cast(committedBytesCount) + byteCount > -1); - committedBytesCount += byteCount; -} - -} // namespace JSC diff --git a/Source/JavaScriptCore/interpreter/RegisterFile.h b/Source/JavaScriptCore/interpreter/RegisterFile.h deleted file mode 100644 index 8fff8208c..000000000 --- a/Source/JavaScriptCore/interpreter/RegisterFile.h +++ /dev/null @@ -1,124 +0,0 @@ -/* - * Copyright (C) 2008, 2009 Apple Inc. All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. Neither the name of Apple Computer, Inc. ("Apple") nor the names of - * its contributors may be used to endorse or promote products derived - * from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY APPLE AND ITS CONTRIBUTORS "AS IS" AND ANY - * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED - * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL APPLE OR ITS CONTRIBUTORS BE LIABLE FOR ANY - * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES - * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; - * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND - * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF - * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -#ifndef RegisterFile_h -#define RegisterFile_h - -#include "ExecutableAllocator.h" -#include "Register.h" -#include -#include -#include - -namespace JSC { - - class ConservativeRoots; - class DFGCodeBlocks; - class JITStubRoutineSet; - class LLIntOffsetsExtractor; - - class RegisterFile { - WTF_MAKE_NONCOPYABLE(RegisterFile); - public: - enum CallFrameHeaderEntry { - CallFrameHeaderSize = 6, - - ArgumentCount = -6, - CallerFrame = -5, - Callee = -4, - ScopeChain = -3, - ReturnPC = -2, // This is either an Instruction* or a pointer into JIT generated code stored as an Instruction*. - CodeBlock = -1, - }; - - static const size_t defaultCapacity = 512 * 1024; - static const size_t commitSize = 16 * 1024; - // Allow 8k of excess registers before we start trying to reap the registerfile - static const ptrdiff_t maxExcessCapacity = 8 * 1024; - - RegisterFile(size_t capacity = defaultCapacity); - ~RegisterFile(); - - void gatherConservativeRoots(ConservativeRoots&); - void gatherConservativeRoots(ConservativeRoots&, JITStubRoutineSet&, DFGCodeBlocks&); - - Register* begin() const { return static_cast(m_reservation.base()); } - Register* end() const { return m_end; } - size_t size() const { return end() - begin(); } - - bool grow(Register*); - void shrink(Register*); - - static size_t committedByteCount(); - static void initializeThreading(); - - Register* const * addressOfEnd() const - { - return &m_end; - } - - private: - friend class LLIntOffsetsExtractor; - - bool growSlowCase(Register*); - void releaseExcessCapacity(); - void addToCommittedByteCount(long); - Register* m_end; - Register* m_commitEnd; - PageReservation m_reservation; - }; - - inline RegisterFile::RegisterFile(size_t capacity) - : m_end(0) - { - ASSERT(capacity && isPageAligned(capacity)); - - m_reservation = PageReservation::reserve(roundUpAllocationSize(capacity * sizeof(Register), commitSize), OSAllocator::JSVMStackPages); - m_end = static_cast(m_reservation.base()); - m_commitEnd = static_cast(m_reservation.base()); - } - - inline void RegisterFile::shrink(Register* newEnd) - { - if (newEnd >= m_end) - return; - m_end = newEnd; - if (m_end == m_reservation.base() && (m_commitEnd - begin()) >= maxExcessCapacity) - releaseExcessCapacity(); - } - - inline bool RegisterFile::grow(Register* newEnd) - { - if (newEnd <= m_end) - return true; - return growSlowCase(newEnd); - } - -} // namespace JSC - -#endif // RegisterFile_h diff --git a/Source/JavaScriptCore/interpreter/VMInspector.cpp b/Source/JavaScriptCore/interpreter/VMInspector.cpp index 34bf61535..566d4e8e0 100644 --- a/Source/JavaScriptCore/interpreter/VMInspector.cpp +++ b/Source/JavaScriptCore/interpreter/VMInspector.cpp @@ -69,25 +69,19 @@ void VMInspector::dumpFrame(CallFrame* frame, const char* prefix, printf("%s ", prefix); printf("frame [%d] %p { cb %p:%s, retPC %p:%s, scope %p:%s, callee %p:%s, callerFrame %p:%s, argc %d, vPC %p }", - frameCount, frame, - - CAST(frame[RegisterFile::CodeBlock].payload()), - getTypeName(frame[RegisterFile::CodeBlock].jsValue()), - - CAST(frame[RegisterFile::ReturnPC].payload()), - getTypeName(frame[RegisterFile::ReturnPC].jsValue()), - - CAST(frame[RegisterFile::ScopeChain].payload()), - getTypeName(frame[RegisterFile::ScopeChain].jsValue()), - - CAST(frame[RegisterFile::Callee].payload()), - getTypeName(frame[RegisterFile::Callee].jsValue()), - - CAST(frame[RegisterFile::CallerFrame].payload()), - getTypeName(frame[RegisterFile::CallerFrame].jsValue()), - - frame[RegisterFile::ArgumentCount].payload(), - vPC); + frameCount, frame, + CAST(frame[JSStack::CodeBlock].payload()), + getTypeName(frame[JSStack::CodeBlock].jsValue()), + CAST(frame[JSStack::ReturnPC].payload()), + getTypeName(frame[JSStack::ReturnPC].jsValue()), + CAST(frame[JSStack::ScopeChain].payload()), + getTypeName(frame[JSStack::ScopeChain].jsValue()), + CAST(frame[JSStack::Callee].payload()), + getTypeName(frame[JSStack::Callee].jsValue()), + CAST(frame[JSStack::CallerFrame].callFrame()), + getTypeName(frame[JSStack::CallerFrame].jsValue()), + frame[JSStack::ArgumentCount].payload(), + vPC); if (funcName || file || (line >= 0)) { printf(" @"); -- cgit v1.2.1