diff options
Diffstat (limited to 'Source/JavaScriptCore/interpreter')
-rw-r--r-- | Source/JavaScriptCore/interpreter/CachedCall.h | 4 | ||||
-rw-r--r-- | Source/JavaScriptCore/interpreter/CallFrame.h | 21 | ||||
-rw-r--r-- | Source/JavaScriptCore/interpreter/Interpreter.cpp | 268 | ||||
-rw-r--r-- | Source/JavaScriptCore/interpreter/Interpreter.h | 2 | ||||
-rw-r--r-- | Source/JavaScriptCore/interpreter/Register.h | 66 | ||||
-rw-r--r-- | Source/JavaScriptCore/interpreter/RegisterFile.cpp | 20 | ||||
-rw-r--r-- | Source/JavaScriptCore/interpreter/RegisterFile.h | 25 |
7 files changed, 182 insertions, 224 deletions
diff --git a/Source/JavaScriptCore/interpreter/CachedCall.h b/Source/JavaScriptCore/interpreter/CachedCall.h index 740001d..04f2210 100644 --- a/Source/JavaScriptCore/interpreter/CachedCall.h +++ b/Source/JavaScriptCore/interpreter/CachedCall.h @@ -38,10 +38,10 @@ namespace JSC { CachedCall(CallFrame* callFrame, JSFunction* function, int argCount) : m_valid(false) , m_interpreter(callFrame->interpreter()) - , m_globalObjectScope(callFrame, function->scope().globalObject()) + , m_globalObjectScope(callFrame->globalData(), function->scope()->globalObject.get()) { ASSERT(!function->isHostFunction()); - m_closure = m_interpreter->prepareForRepeatCall(function->jsExecutable(), callFrame, function, argCount, function->scope().node()); + m_closure = m_interpreter->prepareForRepeatCall(function->jsExecutable(), callFrame, function, argCount, function->scope()); m_valid = !callFrame->hadException(); } diff --git a/Source/JavaScriptCore/interpreter/CallFrame.h b/Source/JavaScriptCore/interpreter/CallFrame.h index 190a7c1..28832e0 100644 --- a/Source/JavaScriptCore/interpreter/CallFrame.h +++ b/Source/JavaScriptCore/interpreter/CallFrame.h @@ -26,13 +26,13 @@ #include "JSGlobalData.h" #include "MacroAssemblerCodeRef.h" #include "RegisterFile.h" -#include "ScopeChain.h" namespace JSC { class Arguments; class JSActivation; class Interpreter; + class ScopeChainNode; // Represents the current state of script execution. // Passed as the first argument to most functions. @@ -51,23 +51,13 @@ namespace JSC { // Global object in which the currently executing code was defined. // Differs from dynamicGlobalObject() during function calls across web browser frames. - JSGlobalObject* lexicalGlobalObject() const - { - return scopeChain()->globalObject; - } + inline JSGlobalObject* lexicalGlobalObject() const; // Differs from lexicalGlobalObject because this will have DOM window shell rather than // the actual DOM window, which can't be "this" for security reasons. - JSObject* globalThisValue() const - { - return scopeChain()->globalThis; - } + inline JSObject* globalThisValue() const; - JSGlobalData& globalData() const - { - ASSERT(scopeChain()->globalData); - return *scopeChain()->globalData; - } + inline JSGlobalData& globalData() const; // Convenience functions for access to global data. // It takes a few memory references to get from a call frame to the global data @@ -75,7 +65,7 @@ namespace JSC { // But they're used in many places in legacy code, so they're not going away any time soon. void clearException() { globalData().exception = JSValue(); } - JSValue exception() const { return globalData().exception.get(); } + JSValue exception() const { return globalData().exception; } bool hadException() const { return globalData().exception; } const CommonIdentifiers& propertyNames() const { return *globalData().propertyNames; } @@ -90,6 +80,7 @@ namespace JSC { static const HashTable* jsonTable(CallFrame* callFrame) { return callFrame->globalData().jsonTable; } static const HashTable* mathTable(CallFrame* callFrame) { return callFrame->globalData().mathTable; } static const HashTable* numberTable(CallFrame* callFrame) { return callFrame->globalData().numberTable; } + static const HashTable* objectConstructorTable(CallFrame* callFrame) { return callFrame->globalData().objectConstructorTable; } static const HashTable* regExpTable(CallFrame* callFrame) { return callFrame->globalData().regExpTable; } static const HashTable* regExpConstructorTable(CallFrame* callFrame) { return callFrame->globalData().regExpConstructorTable; } static const HashTable* stringTable(CallFrame* callFrame) { return callFrame->globalData().stringTable; } diff --git a/Source/JavaScriptCore/interpreter/Interpreter.cpp b/Source/JavaScriptCore/interpreter/Interpreter.cpp index c2612ac..4a6ffb6 100644 --- a/Source/JavaScriptCore/interpreter/Interpreter.cpp +++ b/Source/JavaScriptCore/interpreter/Interpreter.cpp @@ -42,7 +42,6 @@ #include "EvalCodeCache.h" #include "ExceptionHelpers.h" #include "GetterSetter.h" -#include "GlobalEvalFunction.h" #include "JSActivation.h" #include "JSArray.h" #include "JSByteArray.h" @@ -77,11 +76,11 @@ using namespace std; namespace JSC { // Returns the depth of the scope chain within a given call frame. -static int depth(CodeBlock* codeBlock, ScopeChain& sc) +static int depth(CodeBlock* codeBlock, ScopeChainNode* sc) { if (!codeBlock->needsFullScopeChain()) return 0; - return sc.localDepth(); + return sc->localDepth(); } #if ENABLE(INTERPRETER) @@ -107,7 +106,7 @@ NEVER_INLINE bool Interpreter::resolve(CallFrame* callFrame, Instruction* vPC, J PropertySlot slot(o); if (o->getPropertySlot(callFrame, ident, slot)) { JSValue result = slot.getValue(callFrame, ident); - exceptionValue = callFrame->globalData().exception.get(); + exceptionValue = callFrame->globalData().exception; if (exceptionValue) return false; callFrame->uncheckedR(dst) = JSValue(result); @@ -146,7 +145,7 @@ NEVER_INLINE bool Interpreter::resolveSkip(CallFrame* callFrame, Instruction* vP PropertySlot slot(o); if (o->getPropertySlot(callFrame, ident, slot)) { JSValue result = slot.getValue(callFrame, ident); - exceptionValue = callFrame->globalData().exception.get(); + exceptionValue = callFrame->globalData().exception; if (exceptionValue) return false; ASSERT(result); @@ -165,7 +164,7 @@ NEVER_INLINE bool Interpreter::resolveGlobal(CallFrame* callFrame, Instruction* JSGlobalObject* globalObject = codeBlock->globalObject(); ASSERT(globalObject->isGlobalObject()); int property = vPC[2].u.operand; - Structure* structure = vPC[3].u.structure; + Structure* structure = vPC[3].u.structure.get(); int offset = vPC[4].u.operand; if (structure == globalObject->structure()) { @@ -178,16 +177,13 @@ NEVER_INLINE bool Interpreter::resolveGlobal(CallFrame* callFrame, Instruction* if (globalObject->getPropertySlot(callFrame, ident, slot)) { JSValue result = slot.getValue(callFrame, ident); if (slot.isCacheableValue() && !globalObject->structure()->isUncacheableDictionary() && slot.slotBase() == globalObject) { - if (vPC[3].u.structure) - vPC[3].u.structure->deref(); - globalObject->structure()->ref(); - vPC[3] = globalObject->structure(); + vPC[3].u.structure.set(callFrame->globalData(), codeBlock->ownerExecutable(), globalObject->structure()); vPC[4] = slot.cachedOffset(); callFrame->uncheckedR(dst) = JSValue(result); return true; } - exceptionValue = callFrame->globalData().exception.get(); + exceptionValue = callFrame->globalData().exception; if (exceptionValue) return false; callFrame->uncheckedR(dst) = JSValue(result); @@ -205,7 +201,7 @@ NEVER_INLINE bool Interpreter::resolveGlobalDynamic(CallFrame* callFrame, Instru JSGlobalObject* globalObject = codeBlock->globalObject(); ASSERT(globalObject->isGlobalObject()); int property = vPC[2].u.operand; - Structure* structure = vPC[3].u.structure; + Structure* structure = vPC[3].u.structure.get(); int offset = vPC[4].u.operand; int skip = vPC[5].u.operand; @@ -227,7 +223,7 @@ NEVER_INLINE bool Interpreter::resolveGlobalDynamic(CallFrame* callFrame, Instru PropertySlot slot(o); if (o->getPropertySlot(callFrame, ident, slot)) { JSValue result = slot.getValue(callFrame, ident); - exceptionValue = callFrame->globalData().exception.get(); + exceptionValue = callFrame->globalData().exception; if (exceptionValue) return false; ASSERT(result); @@ -256,17 +252,14 @@ NEVER_INLINE bool Interpreter::resolveGlobalDynamic(CallFrame* callFrame, Instru if (globalObject->getPropertySlot(callFrame, ident, slot)) { JSValue result = slot.getValue(callFrame, ident); if (slot.isCacheableValue() && !globalObject->structure()->isUncacheableDictionary() && slot.slotBase() == globalObject) { - if (vPC[3].u.structure) - vPC[3].u.structure->deref(); - globalObject->structure()->ref(); - vPC[3] = globalObject->structure(); + vPC[3].u.structure.set(callFrame->globalData(), codeBlock->ownerExecutable(), globalObject->structure()); vPC[4] = slot.cachedOffset(); ASSERT(result); callFrame->uncheckedR(dst) = JSValue(result); return true; } - exceptionValue = callFrame->globalData().exception.get(); + exceptionValue = callFrame->globalData().exception; if (exceptionValue) return false; ASSERT(result); @@ -314,7 +307,7 @@ NEVER_INLINE bool Interpreter::resolveBaseAndProperty(CallFrame* callFrame, Inst PropertySlot slot(base); if (base->getPropertySlot(callFrame, ident, slot)) { JSValue result = slot.getValue(callFrame, ident); - exceptionValue = callFrame->globalData().exception.get(); + exceptionValue = callFrame->globalData().exception; if (exceptionValue) return false; callFrame->uncheckedR(propDst) = JSValue(result); @@ -410,18 +403,19 @@ NEVER_INLINE JSValue Interpreter::callEval(CallFrame* callFrame, RegisterFile* r ScopeChainNode* scopeChain = callFrame->scopeChain(); JSValue exceptionValue; - RefPtr<EvalExecutable> eval = codeBlock->evalCodeCache().get(callFrame, codeBlock->isStrictMode(), programSource, scopeChain, exceptionValue); + EvalExecutable* eval = codeBlock->evalCodeCache().get(callFrame, codeBlock->ownerExecutable(), codeBlock->isStrictMode(), programSource, scopeChain, exceptionValue); ASSERT(!eval == exceptionValue); if (UNLIKELY(!eval)) return throwError(callFrame, exceptionValue); - return callFrame->globalData().interpreter->execute(eval.get(), callFrame, callFrame->uncheckedR(codeBlock->thisRegister()).jsValue().toThisObject(callFrame), callFrame->registers() - registerFile->start() + registerOffset, scopeChain); + return callFrame->globalData().interpreter->execute(eval, callFrame, callFrame->uncheckedR(codeBlock->thisRegister()).jsValue().toThisObject(callFrame), callFrame->registers() - registerFile->start() + registerOffset, scopeChain); } -Interpreter::Interpreter() +Interpreter::Interpreter(JSGlobalData& globalData) : m_sampleEntryDepth(0) , m_reentryDepth(0) + , m_registerFile(globalData) { #if ENABLE(COMPUTED_GOTO_INTERPRETER) privateExecute(InitializeAndReturn, 0, 0); @@ -564,24 +558,21 @@ NEVER_INLINE bool Interpreter::unwindCallFrame(CallFrame*& callFrame, JSValue ex oldCodeBlock->createActivation(callFrame); scopeChain = callFrame->scopeChain(); } - while (!scopeChain->object->inherits(&JSActivation::info)) + while (!scopeChain->object->inherits(&JSActivation::s_info)) scopeChain = scopeChain->pop(); callFrame->setScopeChain(scopeChain); JSActivation* activation = asActivation(scopeChain->object.get()); - activation->copyRegisters(); + activation->copyRegisters(*scopeChain->globalData); if (JSValue arguments = callFrame->uncheckedR(unmodifiedArgumentsRegister(oldCodeBlock->argumentsRegister())).jsValue()) { if (!oldCodeBlock->isStrictMode()) asArguments(arguments)->setActivation(callFrame->globalData(), activation); } } else if (oldCodeBlock->usesArguments() && !oldCodeBlock->isStrictMode()) { if (JSValue arguments = callFrame->uncheckedR(unmodifiedArgumentsRegister(oldCodeBlock->argumentsRegister())).jsValue()) - asArguments(arguments)->copyRegisters(); + asArguments(arguments)->copyRegisters(callFrame->globalData()); } - if (oldCodeBlock->needsFullScopeChain()) - scopeChain->deref(); - CallFrame* callerFrame = callFrame->callerFrame(); if (callerFrame->hasHostCallFrameFlag()) return false; @@ -623,7 +614,7 @@ static void appendSourceToError(CallFrame* callFrame, ErrorInstance* exception, return; JSGlobalData* globalData = &callFrame->globalData(); - JSValue jsMessage = exception->getDirect(globalData->propertyNames->message); + JSValue jsMessage = exception->getDirect(*globalData, globalData->propertyNames->message); if (!jsMessage || !jsMessage.isString()) return; @@ -645,7 +636,7 @@ static void appendSourceToError(CallFrame* callFrame, ErrorInstance* exception, start++; while (stop < dataLength && (stop - expressionStart < 20) && data[stop] != '\n') stop++; - while (stop > expressionStart && isStrWhiteSpace(data[stop])) + while (stop > expressionStart && isStrWhiteSpace(data[stop - 1])) stop--; message = makeUString(message, " (near '...", codeBlock->source()->getRange(start, stop), "...')"); } @@ -710,11 +701,10 @@ NEVER_INLINE HandlerInfo* Interpreter::throwException(CallFrame*& callFrame, JSV // Unwind the scope chain within the exception handler's call frame. ScopeChainNode* scopeChain = callFrame->scopeChain(); - ScopeChain sc(scopeChain); int scopeDelta = 0; if (!codeBlock->needsFullScopeChain() || codeBlock->codeType() != FunctionCode || callFrame->uncheckedR(codeBlock->activationRegister()).jsValue()) - scopeDelta = depth(codeBlock, sc) - handler->scopeDepth; + scopeDelta = depth(codeBlock, scopeChain) - handler->scopeDepth; ASSERT(scopeDelta >= 0); while (scopeDelta--) scopeChain = scopeChain->pop(); @@ -742,6 +732,8 @@ JSValue Interpreter::execute(ProgramExecutable* program, CallFrame* callFrame, S if (m_reentryDepth >= MaxSmallThreadReentryDepth && m_reentryDepth >= callFrame->globalData().maxReentryDepth) return checkedReturn(throwStackOverflowError(callFrame)); + DynamicGlobalObjectScope globalObjectScope(*scopeChain->globalData, scopeChain->globalObject.get()); + JSObject* error = program->compile(callFrame, scopeChain); if (error) return checkedReturn(throwError(callFrame, error)); @@ -761,11 +753,6 @@ JSValue Interpreter::execute(ProgramExecutable* program, CallFrame* callFrame, S newCallFrame->init(codeBlock, 0, scopeChain, CallFrame::noCaller(), codeBlock->m_numParameters, 0); newCallFrame->uncheckedR(newCallFrame->hostThisRegister()) = JSValue(thisObj); - if (codeBlock->needsFullScopeChain()) - scopeChain->ref(); - - DynamicGlobalObjectScope globalObjectScope(callFrame, scopeChain->globalObject); - Profiler** profiler = Profiler::enabledProfilerReference(); if (*profiler) (*profiler)->willExecute(callFrame, program->sourceURL(), program->lineNo()); @@ -820,6 +807,8 @@ JSValue Interpreter::executeCall(CallFrame* callFrame, JSObject* function, CallT if (callType == CallTypeJS) { ScopeChainNode* callDataScopeChain = callData.js.scopeChain; + DynamicGlobalObjectScope globalObjectScope(*callDataScopeChain->globalData, callDataScopeChain->globalObject.get()); + JSObject* compileError = callData.js.functionExecutable->compileForCall(callFrame, callDataScopeChain); if (UNLIKELY(!!compileError)) { m_registerFile.shrink(oldEnd); @@ -835,8 +824,6 @@ JSValue Interpreter::executeCall(CallFrame* callFrame, JSObject* function, CallT newCallFrame->init(newCodeBlock, 0, callDataScopeChain, callFrame->addHostCallFrameFlag(), argCount, function); - DynamicGlobalObjectScope globalObjectScope(newCallFrame, callDataScopeChain->globalObject); - Profiler** profiler = Profiler::enabledProfilerReference(); if (*profiler) (*profiler)->willExecute(callFrame, function); @@ -867,7 +854,7 @@ JSValue Interpreter::executeCall(CallFrame* callFrame, JSObject* function, CallT newCallFrame = CallFrame::create(newCallFrame->registers() + registerOffset); newCallFrame->init(0, 0, scopeChain, callFrame->addHostCallFrameFlag(), argCount, function); - DynamicGlobalObjectScope globalObjectScope(newCallFrame, scopeChain->globalObject); + DynamicGlobalObjectScope globalObjectScope(*scopeChain->globalData, scopeChain->globalObject.get()); Profiler** profiler = Profiler::enabledProfilerReference(); if (*profiler) @@ -909,6 +896,8 @@ JSObject* Interpreter::executeConstruct(CallFrame* callFrame, JSObject* construc if (constructType == ConstructTypeJS) { ScopeChainNode* constructDataScopeChain = constructData.js.scopeChain; + DynamicGlobalObjectScope globalObjectScope(*constructDataScopeChain->globalData, constructDataScopeChain->globalObject.get()); + JSObject* compileError = constructData.js.functionExecutable->compileForConstruct(callFrame, constructDataScopeChain); if (UNLIKELY(!!compileError)) { m_registerFile.shrink(oldEnd); @@ -924,8 +913,6 @@ JSObject* Interpreter::executeConstruct(CallFrame* callFrame, JSObject* construc newCallFrame->init(newCodeBlock, 0, constructDataScopeChain, callFrame->addHostCallFrameFlag(), argCount, constructor); - DynamicGlobalObjectScope globalObjectScope(newCallFrame, constructDataScopeChain->globalObject); - Profiler** profiler = Profiler::enabledProfilerReference(); if (*profiler) (*profiler)->willExecute(callFrame, constructor); @@ -959,7 +946,7 @@ JSObject* Interpreter::executeConstruct(CallFrame* callFrame, JSObject* construc newCallFrame = CallFrame::create(newCallFrame->registers() + registerOffset); newCallFrame->init(0, 0, scopeChain, callFrame->addHostCallFrameFlag(), argCount, constructor); - DynamicGlobalObjectScope globalObjectScope(newCallFrame, scopeChain->globalObject); + DynamicGlobalObjectScope globalObjectScope(*scopeChain->globalData, scopeChain->globalObject.get()); Profiler** profiler = Profiler::enabledProfilerReference(); if (*profiler) @@ -1001,9 +988,10 @@ CallFrameClosure Interpreter::prepareForRepeatCall(FunctionExecutable* FunctionE } CallFrame* newCallFrame = CallFrame::create(oldEnd); + // We initialise |this| unnecessarily here for the sake of code clarity size_t dst = 0; for (int i = 0; i < argc; ++i) - newCallFrame->uncheckedR(++dst) = jsUndefined(); + newCallFrame->uncheckedR(dst++) = jsUndefined(); JSObject* error = FunctionExecutable->compileForCall(callFrame, scopeChain); if (error) { @@ -1073,18 +1061,18 @@ JSValue Interpreter::execute(EvalExecutable* eval, CallFrame* callFrame, JSObjec { ASSERT(!scopeChain->globalData->exception); + DynamicGlobalObjectScope globalObjectScope(*scopeChain->globalData, scopeChain->globalObject.get()); + if (m_reentryDepth >= MaxSmallThreadReentryDepth && m_reentryDepth >= callFrame->globalData().maxReentryDepth) return checkedReturn(throwStackOverflowError(callFrame)); - DynamicGlobalObjectScope globalObjectScope(callFrame, scopeChain->globalObject); - JSObject* compileError = eval->compile(callFrame, scopeChain); if (UNLIKELY(!!compileError)) return checkedReturn(throwError(callFrame, compileError)); EvalCodeBlock* codeBlock = &eval->generatedBytecode(); JSObject* variableObject; - for (ScopeChainNode* node = scopeChain; ; node = node->next) { + for (ScopeChainNode* node = scopeChain; ; node = node->next.get()) { ASSERT(node); if (node->object->isVariableObject()) { variableObject = static_cast<JSVariableObject*>(node->object.get()); @@ -1133,9 +1121,6 @@ JSValue Interpreter::execute(EvalExecutable* eval, CallFrame* callFrame, JSObjec newCallFrame->init(codeBlock, 0, scopeChain, callFrame->addHostCallFrameFlag(), codeBlock->m_numParameters, 0); newCallFrame->uncheckedR(newCallFrame->hostThisRegister()) = JSValue(thisObj); - if (codeBlock->needsFullScopeChain()) - scopeChain->ref(); - Profiler** profiler = Profiler::enabledProfilerReference(); if (*profiler) (*profiler)->willExecute(callFrame, eval->sourceURL(), eval->lineNo()); @@ -1235,11 +1220,11 @@ NEVER_INLINE void Interpreter::tryCachePutByID(CallFrame* callFrame, CodeBlock* } // Cache miss: record Structure to compare against next time. - Structure* lastStructure = vPC[4].u.structure; + Structure* lastStructure = vPC[4].u.structure.get(); if (structure != lastStructure) { // First miss: record Structure to compare against next time. if (!lastStructure) { - vPC[4] = structure; + vPC[4].u.structure.set(callFrame->globalData(), codeBlock->ownerExecutable(), structure); return; } @@ -1265,24 +1250,23 @@ NEVER_INLINE void Interpreter::tryCachePutByID(CallFrame* callFrame, CodeBlock* // put_by_id_transition checks the prototype chain for setters. normalizePrototypeChain(callFrame, baseCell); - + JSCell* owner = codeBlock->ownerExecutable(); + JSGlobalData& globalData = callFrame->globalData(); vPC[0] = getOpcode(op_put_by_id_transition); - vPC[4] = structure->previousID(); - vPC[5] = structure; - vPC[6] = structure->prototypeChain(callFrame); + vPC[4].u.structure.set(globalData, owner, structure->previousID()); + vPC[5].u.structure.set(globalData, owner, structure); + vPC[6].u.structureChain.set(callFrame->globalData(), codeBlock->ownerExecutable(), structure->prototypeChain(callFrame)); + ASSERT(vPC[6].u.structureChain); vPC[7] = slot.cachedOffset(); - codeBlock->refStructures(vPC); return; } vPC[0] = getOpcode(op_put_by_id_replace); vPC[5] = slot.cachedOffset(); - codeBlock->refStructures(vPC); } -NEVER_INLINE void Interpreter::uncachePutByID(CodeBlock* codeBlock, Instruction* vPC) +NEVER_INLINE void Interpreter::uncachePutByID(CodeBlock*, Instruction* vPC) { - codeBlock->derefStructures(vPC); vPC[0] = getOpcode(op_put_by_id); vPC[4] = 0; } @@ -1324,11 +1308,11 @@ NEVER_INLINE void Interpreter::tryCacheGetByID(CallFrame* callFrame, CodeBlock* } // Cache miss - Structure* lastStructure = vPC[4].u.structure; + Structure* lastStructure = vPC[4].u.structure.get(); if (structure != lastStructure) { // First miss: record Structure to compare against next time. if (!lastStructure) { - vPC[4] = structure; + vPC[4].u.structure.set(callFrame->globalData(), codeBlock->ownerExecutable(), structure); return; } @@ -1354,8 +1338,6 @@ NEVER_INLINE void Interpreter::tryCacheGetByID(CallFrame* callFrame, CodeBlock* vPC[5] = slot.cachedOffset(); break; } - - codeBlock->refStructures(vPC); return; } @@ -1374,7 +1356,7 @@ NEVER_INLINE void Interpreter::tryCacheGetByID(CallFrame* callFrame, CodeBlock* // should not be treated as a dictionary. if (baseObject->structure()->isDictionary()) { baseObject->flattenDictionaryObject(callFrame->globalData()); - offset = baseObject->structure()->get(propertyName); + offset = baseObject->structure()->get(callFrame->globalData(), propertyName); } ASSERT(!baseObject->structure()->isUncacheableDictionary()); @@ -1393,9 +1375,7 @@ NEVER_INLINE void Interpreter::tryCacheGetByID(CallFrame* callFrame, CodeBlock* vPC[6] = offset; break; } - vPC[5] = baseObject->structure(); - - codeBlock->refStructures(vPC); + vPC[5].u.structure.set(callFrame->globalData(), codeBlock->ownerExecutable(), baseObject->structure()); return; } @@ -1421,15 +1401,13 @@ NEVER_INLINE void Interpreter::tryCacheGetByID(CallFrame* callFrame, CodeBlock* vPC[7] = offset; break; } - vPC[4] = structure; - vPC[5] = structure->prototypeChain(callFrame); + vPC[4].u.structure.set(callFrame->globalData(), codeBlock->ownerExecutable(), structure); + vPC[5].u.structureChain.set(callFrame->globalData(), codeBlock->ownerExecutable(), structure->prototypeChain(callFrame)); vPC[6] = count; - codeBlock->refStructures(vPC); } -NEVER_INLINE void Interpreter::uncacheGetByID(CodeBlock* codeBlock, Instruction* vPC) +NEVER_INLINE void Interpreter::uncacheGetByID(CodeBlock*, Instruction* vPC) { - codeBlock->derefStructures(vPC); vPC[0] = getOpcode(op_get_by_id); vPC[4] = 0; } @@ -1477,8 +1455,8 @@ JSValue Interpreter::privateExecute(ExecutionFlag flag, RegisterFile* registerFi #define CHECK_FOR_EXCEPTION() \ do { \ - if (UNLIKELY(globalData->exception.get() != JSValue())) { \ - exceptionValue = globalData->exception.get(); \ + if (UNLIKELY(globalData->exception != JSValue())) { \ + exceptionValue = globalData->exception; \ goto vm_throw; \ } \ } while (0) @@ -1559,8 +1537,12 @@ JSValue Interpreter::privateExecute(ExecutionFlag flag, RegisterFile* registerFi register dst. */ int dst = vPC[1].u.operand; - int regExp = vPC[2].u.operand; - callFrame->uncheckedR(dst) = JSValue(new (globalData) RegExpObject(callFrame->lexicalGlobalObject(), callFrame->scopeChain()->globalObject->regExpStructure(), codeBlock->regexp(regExp))); + RegExp* regExp = codeBlock->regexp(vPC[2].u.operand); + if (!regExp->isValid()) { + exceptionValue = createSyntaxError(callFrame, "Invalid flags supplied to RegExp constructor."); + goto vm_throw; + } + callFrame->uncheckedR(dst) = JSValue(new (globalData) RegExpObject(callFrame->lexicalGlobalObject(), callFrame->scopeChain()->globalObject->regExpStructure(), regExp)); vPC += OPCODE_LENGTH(op_new_regexp); NEXT_INSTRUCTION(); @@ -2366,7 +2348,7 @@ JSValue Interpreter::privateExecute(ExecutionFlag flag, RegisterFile* registerFi ASSERT(scope->isGlobalObject()); int index = vPC[2].u.operand; - callFrame->uncheckedR(dst) = scope->registerAt(index); + callFrame->uncheckedR(dst) = scope->registerAt(index).get(); vPC += OPCODE_LENGTH(op_get_global_var); NEXT_INSTRUCTION(); } @@ -2380,7 +2362,7 @@ JSValue Interpreter::privateExecute(ExecutionFlag flag, RegisterFile* registerFi int index = vPC[1].u.operand; int value = vPC[2].u.operand; - scope->registerAt(index) = JSValue(callFrame->r(value).jsValue()); + scope->registerAt(index).set(*globalData, scope, callFrame->r(value).jsValue()); vPC += OPCODE_LENGTH(op_put_global_var); NEXT_INSTRUCTION(); } @@ -2411,7 +2393,7 @@ JSValue Interpreter::privateExecute(ExecutionFlag flag, RegisterFile* registerFi } ASSERT((*iter)->isVariableObject()); JSVariableObject* scope = static_cast<JSVariableObject*>(iter->get()); - callFrame->uncheckedR(dst) = scope->registerAt(index); + callFrame->uncheckedR(dst) = scope->registerAt(index).get(); ASSERT(callFrame->r(dst).jsValue()); vPC += OPCODE_LENGTH(op_get_scoped_var); NEXT_INSTRUCTION(); @@ -2443,19 +2425,21 @@ JSValue Interpreter::privateExecute(ExecutionFlag flag, RegisterFile* registerFi ASSERT((*iter)->isVariableObject()); JSVariableObject* scope = static_cast<JSVariableObject*>(iter->get()); ASSERT(callFrame->r(value).jsValue()); - scope->registerAt(index) = JSValue(callFrame->r(value).jsValue()); + scope->registerAt(index).set(*globalData, scope, callFrame->r(value).jsValue()); vPC += OPCODE_LENGTH(op_put_scoped_var); NEXT_INSTRUCTION(); } DEFINE_OPCODE(op_resolve_base) { - /* resolve_base dst(r) property(id) + /* resolve_base dst(r) property(id) isStrict(bool) Searches the scope chain for an object containing identifier property, and if one is found, writes it to - register dst. If none is found, the outermost scope (which - will be the global object) is stored in register dst. + register dst. If none is found and isStrict is false, the + outermost scope (which will be the global object) is + stored in register dst. */ resolveBase(callFrame, vPC); + CHECK_FOR_EXCEPTION(); vPC += OPCODE_LENGTH(op_resolve_base); NEXT_INSTRUCTION(); @@ -2476,6 +2460,8 @@ JSValue Interpreter::privateExecute(ExecutionFlag flag, RegisterFile* registerFi exceptionValue = createErrorForInvalidGlobalAssignment(callFrame, ident.ustring()); goto vm_throw; } + + vPC += OPCODE_LENGTH(op_ensure_property_exists); NEXT_INSTRUCTION(); } DEFINE_OPCODE(op_resolve_with_base) { @@ -2530,7 +2516,7 @@ JSValue Interpreter::privateExecute(ExecutionFlag flag, RegisterFile* registerFi if (LIKELY(baseValue.isCell())) { JSCell* baseCell = baseValue.asCell(); - Structure* structure = vPC[4].u.structure; + Structure* structure = vPC[4].u.structure.get(); if (LIKELY(baseCell->structure() == structure)) { ASSERT(baseCell->isObject()); @@ -2561,12 +2547,12 @@ JSValue Interpreter::privateExecute(ExecutionFlag flag, RegisterFile* registerFi if (LIKELY(baseValue.isCell())) { JSCell* baseCell = baseValue.asCell(); - Structure* structure = vPC[4].u.structure; + Structure* structure = vPC[4].u.structure.get(); if (LIKELY(baseCell->structure() == structure)) { ASSERT(structure->prototypeForLookup(callFrame).isObject()); JSObject* protoObject = asObject(structure->prototypeForLookup(callFrame)); - Structure* prototypeStructure = vPC[5].u.structure; + Structure* prototypeStructure = vPC[5].u.structure.get(); if (LIKELY(protoObject->structure() == prototypeStructure)) { int dst = vPC[1].u.operand; @@ -2600,12 +2586,12 @@ JSValue Interpreter::privateExecute(ExecutionFlag flag, RegisterFile* registerFi if (LIKELY(baseValue.isCell())) { JSCell* baseCell = baseValue.asCell(); - Structure* structure = vPC[4].u.structure; + Structure* structure = vPC[4].u.structure.get(); if (LIKELY(baseCell->structure() == structure)) { ASSERT(structure->prototypeForLookup(callFrame).isObject()); JSObject* protoObject = asObject(structure->prototypeForLookup(callFrame)); - Structure* prototypeStructure = vPC[5].u.structure; + Structure* prototypeStructure = vPC[5].u.structure.get(); if (LIKELY(protoObject->structure() == prototypeStructure)) { int dst = vPC[1].u.operand; @@ -2645,12 +2631,12 @@ JSValue Interpreter::privateExecute(ExecutionFlag flag, RegisterFile* registerFi if (LIKELY(baseValue.isCell())) { JSCell* baseCell = baseValue.asCell(); - Structure* structure = vPC[4].u.structure; + Structure* structure = vPC[4].u.structure.get(); if (LIKELY(baseCell->structure() == structure)) { ASSERT(structure->prototypeForLookup(callFrame).isObject()); JSObject* protoObject = asObject(structure->prototypeForLookup(callFrame)); - Structure* prototypeStructure = vPC[5].u.structure; + Structure* prototypeStructure = vPC[5].u.structure.get(); if (LIKELY(protoObject->structure() == prototypeStructure)) { int dst = vPC[1].u.operand; @@ -2714,6 +2700,9 @@ JSValue Interpreter::privateExecute(ExecutionFlag flag, RegisterFile* registerFi vPC += OPCODE_LENGTH(op_get_by_id_proto_list); NEXT_INSTRUCTION(); } +#if USE(GCC_COMPUTED_GOTO_WORKAROUND) + goto *(&&skip_get_by_id_chain); +#endif DEFINE_OPCODE(op_get_by_id_chain) { /* op_get_by_id_chain dst(r) base(r) property(id) structure(sID) structureChain(chain) count(n) offset(n) @@ -2726,12 +2715,12 @@ JSValue Interpreter::privateExecute(ExecutionFlag flag, RegisterFile* registerFi if (LIKELY(baseValue.isCell())) { JSCell* baseCell = baseValue.asCell(); - Structure* structure = vPC[4].u.structure; + Structure* structure = vPC[4].u.structure.get(); if (LIKELY(baseCell->structure() == structure)) { - RefPtr<Structure>* it = vPC[5].u.structureChain->head(); + WriteBarrier<Structure>* it = vPC[5].u.structureChain->head(); size_t count = vPC[6].u.operand; - RefPtr<Structure>* end = it + count; + WriteBarrier<Structure>* end = it + count; while (true) { JSObject* baseObject = asObject(baseCell->structure()->prototypeForLookup(callFrame)); @@ -2761,6 +2750,7 @@ JSValue Interpreter::privateExecute(ExecutionFlag flag, RegisterFile* registerFi NEXT_INSTRUCTION(); } #if USE(GCC_COMPUTED_GOTO_WORKAROUND) + skip_get_by_id_chain: goto *(&&skip_id_getter_self); #endif DEFINE_OPCODE(op_get_by_id_getter_self) { @@ -2775,7 +2765,7 @@ JSValue Interpreter::privateExecute(ExecutionFlag flag, RegisterFile* registerFi if (LIKELY(baseValue.isCell())) { JSCell* baseCell = baseValue.asCell(); - Structure* structure = vPC[4].u.structure; + Structure* structure = vPC[4].u.structure.get(); if (LIKELY(baseCell->structure() == structure)) { ASSERT(baseCell->isObject()); @@ -2818,7 +2808,7 @@ JSValue Interpreter::privateExecute(ExecutionFlag flag, RegisterFile* registerFi if (LIKELY(baseValue.isCell())) { JSCell* baseCell = baseValue.asCell(); - Structure* structure = vPC[4].u.structure; + Structure* structure = vPC[4].u.structure.get(); if (LIKELY(baseCell->structure() == structure)) { ASSERT(baseCell->isObject()); @@ -2875,12 +2865,12 @@ skip_id_custom_self: if (LIKELY(baseValue.isCell())) { JSCell* baseCell = baseValue.asCell(); - Structure* structure = vPC[4].u.structure; + Structure* structure = vPC[4].u.structure.get(); if (LIKELY(baseCell->structure() == structure)) { - RefPtr<Structure>* it = vPC[5].u.structureChain->head(); + WriteBarrier<Structure>* it = vPC[5].u.structureChain->head(); size_t count = vPC[6].u.operand; - RefPtr<Structure>* end = it + count; + WriteBarrier<Structure>* end = it + count; while (true) { JSObject* baseObject = asObject(baseCell->structure()->prototypeForLookup(callFrame)); @@ -2930,12 +2920,12 @@ skip_id_custom_self: if (LIKELY(baseValue.isCell())) { JSCell* baseCell = baseValue.asCell(); - Structure* structure = vPC[4].u.structure; + Structure* structure = vPC[4].u.structure.get(); if (LIKELY(baseCell->structure() == structure)) { - RefPtr<Structure>* it = vPC[5].u.structureChain->head(); + WriteBarrier<Structure>* it = vPC[5].u.structureChain->head(); size_t count = vPC[6].u.operand; - RefPtr<Structure>* end = it + count; + WriteBarrier<Structure>* end = it + count; while (true) { JSObject* baseObject = asObject(baseCell->structure()->prototypeForLookup(callFrame)); @@ -2966,6 +2956,7 @@ skip_id_custom_self: } #if USE(GCC_COMPUTED_GOTO_WORKAROUND) skip_id_custom_chain: + goto *(&&skip_get_array_length); #endif DEFINE_OPCODE(op_get_array_length) { /* op_get_array_length dst(r) base(r) property(id) nop(sID) nop(n) nop(n) nop(n) @@ -2987,6 +2978,10 @@ skip_id_custom_self: uncacheGetByID(codeBlock, vPC); NEXT_INSTRUCTION(); } +#if USE(GCC_COMPUTED_GOTO_WORKAROUND) + skip_get_array_length: + goto *(&&skip_get_string_length); +#endif DEFINE_OPCODE(op_get_string_length) { /* op_get_string_length dst(r) base(r) property(id) nop(sID) nop(n) nop(n) nop(n) @@ -3007,6 +3002,10 @@ skip_id_custom_self: uncacheGetByID(codeBlock, vPC); NEXT_INSTRUCTION(); } +#if USE(GCC_COMPUTED_GOTO_WORKAROUND) + skip_get_string_length: + goto *(&&skip_put_by_id); +#endif DEFINE_OPCODE(op_put_by_id) { /* put_by_id base(r) property(id) value(r) nop(n) nop(n) nop(n) nop(n) direct(b) @@ -3040,6 +3039,9 @@ skip_id_custom_self: vPC += OPCODE_LENGTH(op_put_by_id); NEXT_INSTRUCTION(); } +#if USE(GCC_COMPUTED_GOTO_WORKAROUND) + skip_put_by_id: +#endif DEFINE_OPCODE(op_put_by_id_transition) { /* op_put_by_id_transition base(r) property(id) value(r) oldStructure(sID) newStructure(sID) structureChain(chain) offset(n) direct(b) @@ -3056,8 +3058,8 @@ skip_id_custom_self: if (LIKELY(baseValue.isCell())) { JSCell* baseCell = baseValue.asCell(); - Structure* oldStructure = vPC[4].u.structure; - Structure* newStructure = vPC[5].u.structure; + Structure* oldStructure = vPC[4].u.structure.get(); + Structure* newStructure = vPC[5].u.structure.get(); if (LIKELY(baseCell->structure() == oldStructure)) { ASSERT(baseCell->isObject()); @@ -3065,7 +3067,7 @@ skip_id_custom_self: int direct = vPC[8].u.operand; if (!direct) { - RefPtr<Structure>* it = vPC[6].u.structureChain->head(); + WriteBarrier<Structure>* it = vPC[6].u.structureChain->head(); JSValue proto = baseObject->structure()->prototypeForLookup(callFrame); while (!proto.isNull()) { @@ -3077,11 +3079,11 @@ skip_id_custom_self: proto = asObject(proto)->structure()->prototypeForLookup(callFrame); } } - baseObject->transitionTo(newStructure); + baseObject->transitionTo(*globalData, newStructure); int value = vPC[3].u.operand; unsigned offset = vPC[7].u.operand; - ASSERT(baseObject->offsetForLocation(baseObject->getDirectLocation(codeBlock->identifier(vPC[2].u.operand))) == offset); + ASSERT(baseObject->offsetForLocation(baseObject->getDirectLocation(*globalData, codeBlock->identifier(vPC[2].u.operand))) == offset); baseObject->putDirectOffset(callFrame->globalData(), offset, callFrame->r(value).jsValue()); vPC += OPCODE_LENGTH(op_put_by_id_transition); @@ -3108,7 +3110,7 @@ skip_id_custom_self: if (LIKELY(baseValue.isCell())) { JSCell* baseCell = baseValue.asCell(); - Structure* structure = vPC[4].u.structure; + Structure* structure = vPC[4].u.structure.get(); if (LIKELY(baseCell->structure() == structure)) { ASSERT(baseCell->isObject()); @@ -3116,7 +3118,7 @@ skip_id_custom_self: int value = vPC[3].u.operand; unsigned offset = vPC[5].u.operand; - ASSERT(baseObject->offsetForLocation(baseObject->getDirectLocation(codeBlock->identifier(vPC[2].u.operand))) == offset); + ASSERT(baseObject->offsetForLocation(baseObject->getDirectLocation(*globalData, codeBlock->identifier(vPC[2].u.operand))) == offset); baseObject->putDirectOffset(callFrame->globalData(), offset, callFrame->r(value).jsValue()); vPC += OPCODE_LENGTH(op_put_by_id_replace); @@ -3539,10 +3541,9 @@ skip_id_custom_self: to ptr, using pointer equality. */ int src = vPC[1].u.operand; - JSValue ptr = JSValue(vPC[2].u.jsCell); int target = vPC[3].u.operand; JSValue srcValue = callFrame->r(src).jsValue(); - if (srcValue != ptr) { + if (srcValue != vPC[2].u.jsCell.get()) { vPC += target; NEXT_INSTRUCTION(); } @@ -3803,7 +3804,7 @@ skip_id_custom_self: */ if (!function->name().isNull()) { JSStaticScopeObject* functionScopeObject = new (callFrame) JSStaticScopeObject(callFrame, function->name(), func, ReadOnly | DontDelete); - func->scope().push(functionScopeObject); + func->setScope(*globalData, func->scope()->push(functionScopeObject)); } callFrame->uncheckedR(dst) = JSValue(func); @@ -3833,11 +3834,11 @@ skip_id_custom_self: Register* newCallFrame = callFrame->registers() + registerOffset; Register* argv = newCallFrame - RegisterFile::CallFrameHeaderSize - argCount; JSValue thisValue = argv[0].jsValue(); - JSGlobalObject* globalObject = callFrame->scopeChain()->globalObject; + JSGlobalObject* globalObject = callFrame->scopeChain()->globalObject.get(); if (thisValue == globalObject && funcVal == globalObject->evalFunction()) { JSValue result = callEval(callFrame, registerFile, argv, argCount, registerOffset); - if ((exceptionValue = globalData->exception.get())) + if ((exceptionValue = globalData->exception)) goto vm_throw; functionReturnValue = result; @@ -3959,7 +3960,7 @@ skip_id_custom_self: exceptionValue = createInvalidParamError(callFrame, "Function.prototype.apply", arguments); goto vm_throw; } - if (asObject(arguments)->classInfo() == &Arguments::info) { + if (asObject(arguments)->classInfo() == &Arguments::s_info) { Arguments* args = asArguments(arguments); argCount = args->numProvidedArguments(callFrame); argCount = min<uint32_t>(argCount, Arguments::MaxArguments); @@ -3981,7 +3982,7 @@ skip_id_custom_self: goto vm_throw; } array->copyToRegisters(callFrame, callFrame->registers() + argsOffset, argCount); - } else if (asObject(arguments)->inherits(&JSArray::info)) { + } else if (asObject(arguments)->inherits(&JSArray::s_info)) { JSObject* argObject = asObject(arguments); argCount = argObject->get(callFrame, callFrame->propertyNames().length).toUInt32(callFrame); argCount = min<uint32_t>(argCount, Arguments::MaxArguments); @@ -4101,7 +4102,7 @@ skip_id_custom_self: ASSERT(codeBlock->needsFullScopeChain()); JSValue activationValue = callFrame->r(activation).jsValue(); if (activationValue) { - asActivation(activationValue)->copyRegisters(); + asActivation(activationValue)->copyRegisters(*globalData); if (JSValue argumentsValue = callFrame->r(unmodifiedArgumentsRegister(arguments)).jsValue()) { if (!codeBlock->isStrictMode()) @@ -4109,7 +4110,7 @@ skip_id_custom_self: } } else if (JSValue argumentsValue = callFrame->r(unmodifiedArgumentsRegister(arguments)).jsValue()) { if (!codeBlock->isStrictMode()) - asArguments(argumentsValue)->copyRegisters(); + asArguments(argumentsValue)->copyRegisters(*globalData); } vPC += OPCODE_LENGTH(op_tear_off_activation); @@ -4131,7 +4132,7 @@ skip_id_custom_self: ASSERT(!codeBlock->needsFullScopeChain() && codeBlock->ownerExecutable()->usesArguments()); if (JSValue arguments = callFrame->r(unmodifiedArgumentsRegister(src1)).jsValue()) - asArguments(arguments)->copyRegisters(); + asArguments(arguments)->copyRegisters(*globalData); vPC += OPCODE_LENGTH(op_tear_off_arguments); NEXT_INSTRUCTION(); @@ -4148,9 +4149,6 @@ skip_id_custom_self: int result = vPC[1].u.operand; - if (callFrame->codeBlock()->needsFullScopeChain() && callFrame->r(codeBlock->activationRegister()).jsValue()) - callFrame->scopeChain()->deref(); - JSValue returnValue = callFrame->r(result).jsValue(); vPC = callFrame->returnVPC(); @@ -4189,9 +4187,6 @@ skip_id_custom_self: int result = vPC[1].u.operand; - if (codeBlock->needsFullScopeChain() && callFrame->r(codeBlock->activationRegister()).jsValue()) - callFrame->scopeChain()->deref(); - JSValue returnValue = callFrame->r(result).jsValue(); if (UNLIKELY(!returnValue.isObject())) @@ -4236,7 +4231,7 @@ skip_id_custom_self: if (!callFrame->r(activationReg).jsValue()) { JSActivation* activation = new (globalData) JSActivation(callFrame, static_cast<FunctionExecutable*>(codeBlock->ownerExecutable())); callFrame->r(activationReg) = JSValue(activation); - callFrame->setScopeChain(callFrame->scopeChain()->copy()->push(activation)); + callFrame->setScopeChain(callFrame->scopeChain()->push(activation)); } vPC += OPCODE_LENGTH(op_create_activation); NEXT_INSTRUCTION(); @@ -4273,10 +4268,10 @@ skip_id_custom_self: Structure* structure; JSValue proto = callFrame->r(protoRegister).jsValue(); if (proto.isObject()) - structure = asObject(proto)->inheritorID(); + structure = asObject(proto)->inheritorID(callFrame->globalData()); else - structure = constructor->scope().node()->globalObject->emptyObjectStructure(); - callFrame->uncheckedR(thisRegister) = JSValue(new (&callFrame->globalData()) JSObject(structure)); + structure = constructor->scope()->globalObject->emptyObjectStructure(); + callFrame->uncheckedR(thisRegister) = constructEmptyObject(callFrame, structure); vPC += OPCODE_LENGTH(op_create_this); NEXT_INSTRUCTION(); @@ -4641,11 +4636,6 @@ skip_id_custom_self: program. Return control to the calling native code. */ - if (codeBlock->needsFullScopeChain()) { - ScopeChainNode* scopeChain = callFrame->scopeChain(); - ASSERT(scopeChain->refCount > 1); - scopeChain->deref(); - } int result = vPC[1].u.operand; return callFrame->r(result).jsValue(); } @@ -4775,9 +4765,13 @@ skip_id_custom_self: // cannot fathom if we don't assign to the exceptionValue before branching) exceptionValue = createInterruptedExecutionException(globalData); } + JSGlobalObject* globalObject = callFrame->lexicalGlobalObject(); handler = throwException(callFrame, exceptionValue, vPC - codeBlock->instructions().begin()); - if (!handler) - return throwError(callFrame, exceptionValue); + if (!handler) { + // Can't use the callframe at this point as the scopechain, etc have + // been released. + return throwError(globalObject->globalExec(), exceptionValue); + } codeBlock = callFrame->codeBlock(); vPC = codeBlock->instructions().begin() + handler->target; @@ -4814,7 +4808,7 @@ JSValue Interpreter::retrieveArguments(CallFrame* callFrame, JSFunction* functio } Arguments* arguments = new (functionCallFrame) Arguments(functionCallFrame); - arguments->copyRegisters(); + arguments->copyRegisters(functionCallFrame->globalData()); return arguments; } diff --git a/Source/JavaScriptCore/interpreter/Interpreter.h b/Source/JavaScriptCore/interpreter/Interpreter.h index 753d90e..8f29f60 100644 --- a/Source/JavaScriptCore/interpreter/Interpreter.h +++ b/Source/JavaScriptCore/interpreter/Interpreter.h @@ -69,7 +69,7 @@ namespace JSC { friend class JIT; friend class CachedCall; public: - Interpreter(); + Interpreter(JSGlobalData&); RegisterFile& registerFile() { return m_registerFile; } diff --git a/Source/JavaScriptCore/interpreter/Register.h b/Source/JavaScriptCore/interpreter/Register.h index 3944642..fb02c12 100644 --- a/Source/JavaScriptCore/interpreter/Register.h +++ b/Source/JavaScriptCore/interpreter/Register.h @@ -54,11 +54,10 @@ namespace JSC { Register(const JSValue&); Register& operator=(const JSValue&); JSValue jsValue() const; + EncodedJSValue encodedJSValue() const; - Register& operator=(JSActivation*); Register& operator=(CallFrame*); Register& operator=(CodeBlock*); - Register& operator=(JSPropertyNameIterator*); Register& operator=(ScopeChainNode*); Register& operator=(Instruction*); @@ -73,29 +72,17 @@ namespace JSC { static Register withInt(int32_t i) { - Register r; - r.u.i = i; + Register r = jsNumber(i); return r; } - static Register withCallee(JSObject* callee) - { - Register r; - r.u.function = callee; - return r; - } + static inline Register withCallee(JSObject* callee); private: union { - int32_t i; EncodedJSValue value; - - JSActivation* activation; CallFrame* callFrame; CodeBlock* codeBlock; - JSObject* function; - JSPropertyNameIterator* propertyNameIterator; - ScopeChainNode* scopeChain; Instruction* vPC; } u; }; @@ -129,14 +116,13 @@ namespace JSC { return JSValue::decode(u.value); } - // Interpreter functions - - ALWAYS_INLINE Register& Register::operator=(JSActivation* activation) + ALWAYS_INLINE EncodedJSValue Register::encodedJSValue() const { - u.activation = activation; - return *this; + return u.value; } + // Interpreter functions + ALWAYS_INLINE Register& Register::operator=(CallFrame* callFrame) { u.callFrame = callFrame; @@ -155,28 +141,11 @@ namespace JSC { return *this; } - ALWAYS_INLINE Register& Register::operator=(ScopeChainNode* scopeChain) - { - u.scopeChain = scopeChain; - return *this; - } - - ALWAYS_INLINE Register& Register::operator=(JSPropertyNameIterator* propertyNameIterator) - { - u.propertyNameIterator = propertyNameIterator; - return *this; - } - ALWAYS_INLINE int32_t Register::i() const { - return u.i; + return jsValue().asInt32(); } - - ALWAYS_INLINE JSActivation* Register::activation() const - { - return u.activation; - } - + ALWAYS_INLINE CallFrame* Register::callFrame() const { return u.callFrame; @@ -186,22 +155,7 @@ namespace JSC { { return u.codeBlock; } - - ALWAYS_INLINE JSObject* Register::function() const - { - return u.function; - } - - ALWAYS_INLINE JSPropertyNameIterator* Register::propertyNameIterator() const - { - return u.propertyNameIterator; - } - - ALWAYS_INLINE ScopeChainNode* Register::scopeChain() const - { - return u.scopeChain; - } - + ALWAYS_INLINE Instruction* Register::vPC() const { return u.vPC; diff --git a/Source/JavaScriptCore/interpreter/RegisterFile.cpp b/Source/JavaScriptCore/interpreter/RegisterFile.cpp index 4c37676..e3b34bb 100644 --- a/Source/JavaScriptCore/interpreter/RegisterFile.cpp +++ b/Source/JavaScriptCore/interpreter/RegisterFile.cpp @@ -29,6 +29,9 @@ #include "config.h" #include "RegisterFile.h" +#include "ConservativeRoots.h" +#include "Interpreter.h" +#include "JSGlobalData.h" #include "JSGlobalObject.h" namespace JSC { @@ -49,6 +52,16 @@ RegisterFile::~RegisterFile() m_reservation.deallocate(); } +void RegisterFile::gatherConservativeRoots(ConservativeRoots& conservativeRoots) +{ + for (Register* it = start(); it != end(); ++it) { + JSValue v = it->jsValue(); + if (!v.isCell()) + continue; + conservativeRoots.add(v.asCell()); + } +} + void RegisterFile::releaseExcessCapacity() { m_reservation.decommit(m_start, reinterpret_cast<intptr_t>(m_commitEnd) - reinterpret_cast<intptr_t>(m_start)); @@ -59,12 +72,7 @@ void RegisterFile::releaseExcessCapacity() void RegisterFile::setGlobalObject(JSGlobalObject* globalObject) { - m_globalObject = globalObject; -} - -bool RegisterFile::clearGlobalObject(JSGlobalObject* globalObject) -{ - return m_globalObject.clear(globalObject); + m_globalObject.set(globalObject->globalData(), globalObject, &m_globalObjectOwner, this); } JSGlobalObject* RegisterFile::globalObject() diff --git a/Source/JavaScriptCore/interpreter/RegisterFile.h b/Source/JavaScriptCore/interpreter/RegisterFile.h index e9c6df1..f59c13a 100644 --- a/Source/JavaScriptCore/interpreter/RegisterFile.h +++ b/Source/JavaScriptCore/interpreter/RegisterFile.h @@ -32,7 +32,7 @@ #include "Heap.h" #include "ExecutableAllocator.h" #include "Register.h" -#include "WeakGCPtr.h" +#include "Weak.h" #include <stdio.h> #include <wtf/Noncopyable.h> #include <wtf/PageReservation.h> @@ -91,7 +91,6 @@ namespace JSC { class RegisterFile { WTF_MAKE_NONCOPYABLE(RegisterFile); - friend class JIT; public: enum CallFrameHeaderEntry { CallFrameHeaderSize = 6, @@ -112,15 +111,16 @@ namespace JSC { // 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, size_t maxGlobals = defaultMaxGlobals); + RegisterFile(JSGlobalData&, size_t capacity = defaultCapacity, size_t maxGlobals = defaultMaxGlobals); ~RegisterFile(); + + void gatherConservativeRoots(ConservativeRoots&); Register* start() const { return m_start; } Register* end() const { return m_end; } size_t size() const { return m_end - m_start; } void setGlobalObject(JSGlobalObject*); - bool clearGlobalObject(JSGlobalObject*); JSGlobalObject* globalObject(); bool grow(Register* newEnd); @@ -135,6 +135,11 @@ namespace JSC { static size_t committedByteCount(); static void initializeThreading(); + Register* const * addressOfEnd() const + { + return &m_end; + } + private: void releaseExcessCapacity(); void addToCommittedByteCount(long); @@ -147,19 +152,25 @@ namespace JSC { Register* m_commitEnd; PageReservation m_reservation; - WeakGCPtr<JSGlobalObject> m_globalObject; // The global object whose vars are currently stored in the register file. + Weak<JSGlobalObject> m_globalObject; // The global object whose vars are currently stored in the register file. + class GlobalObjectOwner : public WeakHandleOwner { + virtual void finalize(Handle<Unknown>, void* context) + { + static_cast<RegisterFile*>(context)->setNumGlobals(0); + } + } m_globalObjectOwner; }; - inline RegisterFile::RegisterFile(size_t capacity, size_t maxGlobals) + inline RegisterFile::RegisterFile(JSGlobalData& globalData, size_t capacity, size_t maxGlobals) : m_numGlobals(0) , m_maxGlobals(maxGlobals) , m_start(0) , m_end(0) , m_max(0) + , m_globalObject(globalData, 0, &m_globalObjectOwner, this) { ASSERT(maxGlobals && isPageAligned(maxGlobals)); ASSERT(capacity && isPageAligned(capacity)); - size_t bufferLength = (capacity + maxGlobals) * sizeof(Register); m_reservation = PageReservation::reserve(roundUpAllocationSize(bufferLength, commitSize), OSAllocator::JSVMStackPages); void* base = m_reservation.base(); |