summaryrefslogtreecommitdiffstats
path: root/Source/JavaScriptCore/interpreter
diff options
context:
space:
mode:
Diffstat (limited to 'Source/JavaScriptCore/interpreter')
-rw-r--r--Source/JavaScriptCore/interpreter/CachedCall.h4
-rw-r--r--Source/JavaScriptCore/interpreter/CallFrame.h21
-rw-r--r--Source/JavaScriptCore/interpreter/Interpreter.cpp268
-rw-r--r--Source/JavaScriptCore/interpreter/Interpreter.h2
-rw-r--r--Source/JavaScriptCore/interpreter/Register.h66
-rw-r--r--Source/JavaScriptCore/interpreter/RegisterFile.cpp20
-rw-r--r--Source/JavaScriptCore/interpreter/RegisterFile.h25
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();