summaryrefslogtreecommitdiffstats
path: root/JavaScriptCore/interpreter
diff options
context:
space:
mode:
Diffstat (limited to 'JavaScriptCore/interpreter')
-rw-r--r--JavaScriptCore/interpreter/CachedCall.h70
-rw-r--r--JavaScriptCore/interpreter/CallFrame.cpp18
-rw-r--r--JavaScriptCore/interpreter/CallFrame.h42
-rw-r--r--JavaScriptCore/interpreter/CallFrameClosure.h60
-rw-r--r--JavaScriptCore/interpreter/Interpreter.cpp3108
-rw-r--r--JavaScriptCore/interpreter/Interpreter.h64
-rw-r--r--JavaScriptCore/interpreter/Register.h101
-rw-r--r--JavaScriptCore/interpreter/RegisterFile.cpp11
-rw-r--r--JavaScriptCore/interpreter/RegisterFile.h28
9 files changed, 900 insertions, 2602 deletions
diff --git a/JavaScriptCore/interpreter/CachedCall.h b/JavaScriptCore/interpreter/CachedCall.h
new file mode 100644
index 0000000..f48f4f4
--- /dev/null
+++ b/JavaScriptCore/interpreter/CachedCall.h
@@ -0,0 +1,70 @@
+/*
+ * Copyright (C) 2009 Apple Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
+ * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef CachedCall_h
+#define CachedCall_h
+
+#include "CallFrameClosure.h"
+#include "JSFunction.h"
+#include "JSGlobalObject.h"
+#include "Interpreter.h"
+
+namespace JSC {
+ class CachedCall : Noncopyable {
+ public:
+ CachedCall(CallFrame* callFrame, JSFunction* function, int argCount, JSValue* exception)
+ : m_valid(false)
+ , m_interpreter(callFrame->interpreter())
+ , m_exception(exception)
+ , m_globalObjectScope(callFrame, callFrame->globalData().dynamicGlobalObject ? callFrame->globalData().dynamicGlobalObject : function->scope().node()->globalObject())
+ {
+ m_closure = m_interpreter->prepareForRepeatCall(function->body(), callFrame, function, argCount, function->scope().node(), exception);
+ m_valid = !*exception;
+ }
+
+ JSValue call()
+ {
+ ASSERT(m_valid);
+ return m_interpreter->execute(m_closure, m_exception);
+ }
+ void setThis(JSValue v) { m_closure.setArgument(0, v); }
+ void setArgument(int n, JSValue v) { m_closure.setArgument(n + 1, v); }
+ CallFrame* newCallFrame() { return m_closure.newCallFrame; }
+ ~CachedCall()
+ {
+ if (m_valid)
+ m_interpreter->endRepeatCall(m_closure);
+ }
+
+ private:
+ bool m_valid;
+ Interpreter* m_interpreter;
+ JSValue* m_exception;
+ DynamicGlobalObjectScope m_globalObjectScope;
+ CallFrameClosure m_closure;
+ };
+}
+
+#endif
diff --git a/JavaScriptCore/interpreter/CallFrame.cpp b/JavaScriptCore/interpreter/CallFrame.cpp
index 1c74280..9724875 100644
--- a/JavaScriptCore/interpreter/CallFrame.cpp
+++ b/JavaScriptCore/interpreter/CallFrame.cpp
@@ -27,12 +27,26 @@
#include "CallFrame.h"
#include "CodeBlock.h"
+#include "Interpreter.h"
namespace JSC {
-JSValuePtr CallFrame::thisValue()
+JSValue CallFrame::thisValue()
{
- return this[codeBlock()->thisRegister()].jsValue(this);
+ return this[codeBlock()->thisRegister()].jsValue();
}
+#ifndef NDEBUG
+void CallFrame::dumpCaller()
+{
+ int signedLineNumber;
+ intptr_t sourceID;
+ UString urlString;
+ JSValue function;
+
+ interpreter()->retrieveLastCaller(this, signedLineNumber, sourceID, urlString, function);
+ printf("Callpoint => %s:%d\n", urlString.ascii(), signedLineNumber);
+}
+#endif
+
}
diff --git a/JavaScriptCore/interpreter/CallFrame.h b/JavaScriptCore/interpreter/CallFrame.h
index 10d0b99..a61e143 100644
--- a/JavaScriptCore/interpreter/CallFrame.h
+++ b/JavaScriptCore/interpreter/CallFrame.h
@@ -40,8 +40,9 @@ namespace JSC {
JSFunction* callee() const { return this[RegisterFile::Callee].function(); }
CodeBlock* codeBlock() const { return this[RegisterFile::CodeBlock].Register::codeBlock(); }
ScopeChainNode* scopeChain() const { return this[RegisterFile::ScopeChain].Register::scopeChain(); }
+ int argumentCount() const { return this[RegisterFile::ArgumentCount].i(); }
- JSValuePtr thisValue();
+ JSValue thisValue();
// Global object in which execution began.
JSGlobalObject* dynamicGlobalObject();
@@ -73,17 +74,19 @@ namespace JSC {
// pointer, so these are inefficient, and should be used sparingly in new code.
// But they're used in many places in legacy code, so they're not going away any time soon.
- void setException(JSValuePtr exception) { globalData().exception = exception; }
- void clearException() { globalData().exception = noValue(); }
- JSValuePtr exception() const { return globalData().exception; }
- JSValuePtr* exceptionSlot() { return &globalData().exception; }
+ void setException(JSValue exception) { globalData().exception = exception; }
+ void clearException() { globalData().exception = JSValue(); }
+ JSValue exception() const { return globalData().exception; }
+ JSValue* exceptionSlot() { return &globalData().exception; }
bool hadException() const { return globalData().exception; }
const CommonIdentifiers& propertyNames() const { return *globalData().propertyNames; }
- const ArgList& emptyList() const { return *globalData().emptyList; }
+ const MarkedArgumentBuffer& emptyList() const { return *globalData().emptyList; }
Interpreter* interpreter() { return globalData().interpreter; }
Heap* heap() { return &globalData().heap; }
-
+#ifndef NDEBUG
+ void dumpCaller();
+#endif
static const HashTable* arrayTable(CallFrame* callFrame) { return callFrame->globalData().arrayTable; }
static const HashTable* dateTable(CallFrame* callFrame) { return callFrame->globalData().dateTable; }
static const HashTable* mathTable(CallFrame* callFrame) { return callFrame->globalData().mathTable; }
@@ -92,29 +95,17 @@ namespace JSC {
static const HashTable* regExpConstructorTable(CallFrame* callFrame) { return callFrame->globalData().regExpConstructorTable; }
static const HashTable* stringTable(CallFrame* callFrame) { return callFrame->globalData().stringTable; }
- private:
- friend class Arguments;
- friend class JSActivation;
- friend class JSGlobalObject;
- friend class Interpreter;
- friend class JITStubs;
-
static CallFrame* create(Register* callFrameBase) { return static_cast<CallFrame*>(callFrameBase); }
Register* registers() { return this; }
CallFrame& operator=(const Register& r) { *static_cast<Register*>(this) = r; return *this; }
- int argumentCount() const { return this[RegisterFile::ArgumentCount].i(); }
CallFrame* callerFrame() const { return this[RegisterFile::CallerFrame].callFrame(); }
Arguments* optionalCalleeArguments() const { return this[RegisterFile::OptionalCalleeArguments].arguments(); }
Instruction* returnPC() const { return this[RegisterFile::ReturnPC].vPC(); }
- int returnValueRegister() const { return this[RegisterFile::ReturnValueRegister].i(); }
- void setArgumentCount(int count) { this[RegisterFile::ArgumentCount] = count; }
- void setCallee(JSFunction* callee) { this[RegisterFile::Callee] = callee; }
void setCalleeArguments(Arguments* arguments) { this[RegisterFile::OptionalCalleeArguments] = arguments; }
void setCallerFrame(CallFrame* callerFrame) { this[RegisterFile::CallerFrame] = callerFrame; }
- void setCodeBlock(CodeBlock* codeBlock) { this[RegisterFile::CodeBlock] = codeBlock; }
void setScopeChain(ScopeChainNode* scopeChain) { this[RegisterFile::ScopeChain] = scopeChain; }
ALWAYS_INLINE void init(CodeBlock* codeBlock, Instruction* vPC, ScopeChainNode* scopeChain,
@@ -132,6 +123,19 @@ namespace JSC {
setCalleeArguments(0);
}
+ private:
+ friend class Arguments;
+ friend class JSActivation;
+ friend class JSGlobalObject;
+ friend class Interpreter;
+ friend struct CallFrameClosure;
+
+ int returnValueRegister() const { return this[RegisterFile::ReturnValueRegister].i(); }
+
+ void setArgumentCount(int count) { this[RegisterFile::ArgumentCount] = count; }
+ void setCallee(JSFunction* callee) { this[RegisterFile::Callee] = callee; }
+ void setCodeBlock(CodeBlock* codeBlock) { this[RegisterFile::CodeBlock] = codeBlock; }
+
static const intptr_t HostCallFrameFlag = 1;
static CallFrame* noCaller() { return reinterpret_cast<CallFrame*>(HostCallFrameFlag); }
diff --git a/JavaScriptCore/interpreter/CallFrameClosure.h b/JavaScriptCore/interpreter/CallFrameClosure.h
new file mode 100644
index 0000000..0e14ced
--- /dev/null
+++ b/JavaScriptCore/interpreter/CallFrameClosure.h
@@ -0,0 +1,60 @@
+/*
+ * Copyright (C) 2009 Apple Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
+ * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef CallFrameClosure_h
+#define CallFrameClosure_h
+
+namespace JSC {
+
+struct CallFrameClosure {
+ CallFrame* oldCallFrame;
+ CallFrame* newCallFrame;
+ JSFunction* function;
+ FunctionBodyNode* functionBody;
+ JSGlobalData* globalData;
+ Register* oldEnd;
+ ScopeChainNode* scopeChain;
+ int expectedParams;
+ int providedParams;
+
+ void setArgument(int arg, JSValue value)
+ {
+ if (arg < expectedParams)
+ newCallFrame[arg - RegisterFile::CallFrameHeaderSize - expectedParams] = value;
+ else
+ newCallFrame[arg - RegisterFile::CallFrameHeaderSize - expectedParams - providedParams] = value;
+ }
+ void resetCallFrame()
+ {
+ newCallFrame->setScopeChain(scopeChain);
+ newCallFrame->setCalleeArguments(0);
+ for (int i = providedParams; i < expectedParams; ++i)
+ newCallFrame[i - RegisterFile::CallFrameHeaderSize - expectedParams] = jsUndefined();
+ }
+};
+
+}
+
+#endif
diff --git a/JavaScriptCore/interpreter/Interpreter.cpp b/JavaScriptCore/interpreter/Interpreter.cpp
index 8178d15..d980962 100644
--- a/JavaScriptCore/interpreter/Interpreter.cpp
+++ b/JavaScriptCore/interpreter/Interpreter.cpp
@@ -32,11 +32,14 @@
#include "Arguments.h"
#include "BatchedTransitionOptimizer.h"
+#include "CallFrame.h"
+#include "CallFrameClosure.h"
#include "CodeBlock.h"
+#include "Collector.h"
+#include "Debugger.h"
#include "DebuggerCallFrame.h"
#include "EvalCodeCache.h"
#include "ExceptionHelpers.h"
-#include "CallFrame.h"
#include "GlobalEvalFunction.h"
#include "JSActivation.h"
#include "JSArray.h"
@@ -44,19 +47,19 @@
#include "JSFunction.h"
#include "JSNotAnObject.h"
#include "JSPropertyNameIterator.h"
+#include "LiteralParser.h"
#include "JSStaticScopeObject.h"
#include "JSString.h"
#include "ObjectPrototype.h"
+#include "Operations.h"
#include "Parser.h"
#include "Profiler.h"
#include "RegExpObject.h"
#include "RegExpPrototype.h"
#include "Register.h"
-#include "Collector.h"
-#include "Debugger.h"
-#include "Operations.h"
#include "SamplingTool.h"
#include <stdio.h>
+#include <wtf/Threading.h>
#if ENABLE(JIT)
#include "JIT.h"
@@ -88,7 +91,8 @@ static int depth(CodeBlock* codeBlock, ScopeChain& sc)
return sc.localDepth();
}
-NEVER_INLINE bool Interpreter::resolve(CallFrame* callFrame, Instruction* vPC, JSValuePtr& exceptionValue)
+#if USE(INTERPRETER)
+NEVER_INLINE bool Interpreter::resolve(CallFrame* callFrame, Instruction* vPC, JSValue& exceptionValue)
{
int dst = (vPC + 1)->u.operand;
int property = (vPC + 2)->u.operand;
@@ -104,11 +108,11 @@ NEVER_INLINE bool Interpreter::resolve(CallFrame* callFrame, Instruction* vPC, J
JSObject* o = *iter;
PropertySlot slot(o);
if (o->getPropertySlot(callFrame, ident, slot)) {
- JSValuePtr result = slot.getValue(callFrame, ident);
+ JSValue result = slot.getValue(callFrame, ident);
exceptionValue = callFrame->globalData().exception;
if (exceptionValue)
return false;
- callFrame[dst] = JSValuePtr(result);
+ callFrame[dst] = JSValue(result);
return true;
}
} while (++iter != end);
@@ -116,7 +120,7 @@ NEVER_INLINE bool Interpreter::resolve(CallFrame* callFrame, Instruction* vPC, J
return false;
}
-NEVER_INLINE bool Interpreter::resolveSkip(CallFrame* callFrame, Instruction* vPC, JSValuePtr& exceptionValue)
+NEVER_INLINE bool Interpreter::resolveSkip(CallFrame* callFrame, Instruction* vPC, JSValue& exceptionValue)
{
CodeBlock* codeBlock = callFrame->codeBlock();
@@ -137,11 +141,11 @@ NEVER_INLINE bool Interpreter::resolveSkip(CallFrame* callFrame, Instruction* vP
JSObject* o = *iter;
PropertySlot slot(o);
if (o->getPropertySlot(callFrame, ident, slot)) {
- JSValuePtr result = slot.getValue(callFrame, ident);
+ JSValue result = slot.getValue(callFrame, ident);
exceptionValue = callFrame->globalData().exception;
if (exceptionValue)
return false;
- callFrame[dst] = JSValuePtr(result);
+ callFrame[dst] = JSValue(result);
return true;
}
} while (++iter != end);
@@ -149,7 +153,7 @@ NEVER_INLINE bool Interpreter::resolveSkip(CallFrame* callFrame, Instruction* vP
return false;
}
-NEVER_INLINE bool Interpreter::resolveGlobal(CallFrame* callFrame, Instruction* vPC, JSValuePtr& exceptionValue)
+NEVER_INLINE bool Interpreter::resolveGlobal(CallFrame* callFrame, Instruction* vPC, JSValue& exceptionValue)
{
int dst = (vPC + 1)->u.operand;
JSGlobalObject* globalObject = static_cast<JSGlobalObject*>((vPC + 2)->u.jsCell);
@@ -159,7 +163,7 @@ NEVER_INLINE bool Interpreter::resolveGlobal(CallFrame* callFrame, Instruction*
int offset = (vPC + 5)->u.operand;
if (structure == globalObject->structure()) {
- callFrame[dst] = JSValuePtr(globalObject->getDirectOffset(offset));
+ callFrame[dst] = JSValue(globalObject->getDirectOffset(offset));
return true;
}
@@ -167,21 +171,21 @@ NEVER_INLINE bool Interpreter::resolveGlobal(CallFrame* callFrame, Instruction*
Identifier& ident = codeBlock->identifier(property);
PropertySlot slot(globalObject);
if (globalObject->getPropertySlot(callFrame, ident, slot)) {
- JSValuePtr result = slot.getValue(callFrame, ident);
- if (slot.isCacheable() && !globalObject->structure()->isDictionary()) {
+ JSValue result = slot.getValue(callFrame, ident);
+ if (slot.isCacheable() && !globalObject->structure()->isDictionary() && slot.slotBase() == globalObject) {
if (vPC[4].u.structure)
vPC[4].u.structure->deref();
globalObject->structure()->ref();
vPC[4] = globalObject->structure();
vPC[5] = slot.cachedOffset();
- callFrame[dst] = JSValuePtr(result);
+ callFrame[dst] = JSValue(result);
return true;
}
exceptionValue = callFrame->globalData().exception;
if (exceptionValue)
return false;
- callFrame[dst] = JSValuePtr(result);
+ callFrame[dst] = JSValue(result);
return true;
}
@@ -193,10 +197,10 @@ NEVER_INLINE void Interpreter::resolveBase(CallFrame* callFrame, Instruction* vP
{
int dst = (vPC + 1)->u.operand;
int property = (vPC + 2)->u.operand;
- callFrame[dst] = JSValuePtr(JSC::resolveBase(callFrame, callFrame->codeBlock()->identifier(property), callFrame->scopeChain()));
+ callFrame[dst] = JSValue(JSC::resolveBase(callFrame, callFrame->codeBlock()->identifier(property), callFrame->scopeChain()));
}
-NEVER_INLINE bool Interpreter::resolveBaseAndProperty(CallFrame* callFrame, Instruction* vPC, JSValuePtr& exceptionValue)
+NEVER_INLINE bool Interpreter::resolveBaseAndProperty(CallFrame* callFrame, Instruction* vPC, JSValue& exceptionValue)
{
int baseDst = (vPC + 1)->u.operand;
int propDst = (vPC + 2)->u.operand;
@@ -217,12 +221,12 @@ NEVER_INLINE bool Interpreter::resolveBaseAndProperty(CallFrame* callFrame, Inst
base = *iter;
PropertySlot slot(base);
if (base->getPropertySlot(callFrame, ident, slot)) {
- JSValuePtr result = slot.getValue(callFrame, ident);
+ JSValue result = slot.getValue(callFrame, ident);
exceptionValue = callFrame->globalData().exception;
if (exceptionValue)
return false;
- callFrame[propDst] = JSValuePtr(result);
- callFrame[baseDst] = JSValuePtr(base);
+ callFrame[propDst] = JSValue(result);
+ callFrame[baseDst] = JSValue(base);
return true;
}
++iter;
@@ -232,7 +236,7 @@ NEVER_INLINE bool Interpreter::resolveBaseAndProperty(CallFrame* callFrame, Inst
return false;
}
-NEVER_INLINE bool Interpreter::resolveBaseAndFunc(CallFrame* callFrame, Instruction* vPC, JSValuePtr& exceptionValue)
+NEVER_INLINE bool Interpreter::resolveBaseAndFunc(CallFrame* callFrame, Instruction* vPC, JSValue& exceptionValue)
{
int baseDst = (vPC + 1)->u.operand;
int funcDst = (vPC + 2)->u.operand;
@@ -261,13 +265,13 @@ NEVER_INLINE bool Interpreter::resolveBaseAndFunc(CallFrame* callFrame, Instruct
// that in host objects you always get a valid object for this.
// We also handle wrapper substitution for the global object at the same time.
JSObject* thisObj = base->toThisObject(callFrame);
- JSValuePtr result = slot.getValue(callFrame, ident);
+ JSValue result = slot.getValue(callFrame, ident);
exceptionValue = callFrame->globalData().exception;
if (exceptionValue)
return false;
- callFrame[baseDst] = JSValuePtr(thisObj);
- callFrame[funcDst] = JSValuePtr(result);
+ callFrame[baseDst] = JSValue(thisObj);
+ callFrame[funcDst] = JSValue(result);
return true;
}
++iter;
@@ -277,6 +281,8 @@ NEVER_INLINE bool Interpreter::resolveBaseAndFunc(CallFrame* callFrame, Instruct
return false;
}
+#endif // USE(INTERPRETER)
+
ALWAYS_INLINE CallFrame* Interpreter::slideRegisterWindowForCall(CodeBlock* newCodeBlock, RegisterFile* registerFile, CallFrame* callFrame, size_t registerOffset, int argc)
{
Register* r = callFrame->registers();
@@ -314,31 +320,46 @@ ALWAYS_INLINE CallFrame* Interpreter::slideRegisterWindowForCall(CodeBlock* newC
return CallFrame::create(r);
}
-static NEVER_INLINE bool isNotObject(CallFrame* callFrame, bool forInstanceOf, CodeBlock* codeBlock, const Instruction* vPC, JSValuePtr value, JSValuePtr& exceptionData)
+#if USE(INTERPRETER)
+static NEVER_INLINE bool isInvalidParamForIn(CallFrame* callFrame, CodeBlock* codeBlock, const Instruction* vPC, JSValue value, JSValue& exceptionData)
{
if (value.isObject())
return false;
- exceptionData = createInvalidParamError(callFrame, forInstanceOf ? "instanceof" : "in" , value, vPC - codeBlock->instructions().begin(), codeBlock);
+ exceptionData = createInvalidParamError(callFrame, "in" , value, vPC - codeBlock->instructions().begin(), codeBlock);
return true;
}
-NEVER_INLINE JSValuePtr Interpreter::callEval(CallFrame* callFrame, RegisterFile* registerFile, Register* argv, int argc, int registerOffset, JSValuePtr& exceptionValue)
+static NEVER_INLINE bool isInvalidParamForInstanceOf(CallFrame* callFrame, CodeBlock* codeBlock, const Instruction* vPC, JSValue value, JSValue& exceptionData)
+{
+ if (value.isObject() && asObject(value)->structure()->typeInfo().implementsHasInstance())
+ return false;
+ exceptionData = createInvalidParamError(callFrame, "instanceof" , value, vPC - codeBlock->instructions().begin(), codeBlock);
+ return true;
+}
+#endif
+
+NEVER_INLINE JSValue Interpreter::callEval(CallFrame* callFrame, RegisterFile* registerFile, Register* argv, int argc, int registerOffset, JSValue& exceptionValue)
{
if (argc < 2)
return jsUndefined();
- JSValuePtr program = argv[1].jsValue(callFrame);
+ JSValue program = argv[1].jsValue();
if (!program.isString())
return program;
UString programSource = asString(program)->value();
+ LiteralParser preparser(callFrame, programSource);
+ if (JSValue parsedObject = preparser.tryLiteralParse())
+ return parsedObject;
+
+
ScopeChainNode* scopeChain = callFrame->scopeChain();
CodeBlock* codeBlock = callFrame->codeBlock();
RefPtr<EvalNode> evalNode = codeBlock->evalCodeCache().get(callFrame, programSource, scopeChain, exceptionValue);
- JSValuePtr result = jsUndefined();
+ JSValue result = jsUndefined();
if (evalNode)
result = callFrame->globalData().interpreter->execute(evalNode.get(), callFrame, callFrame->thisValue().toThisObject(callFrame), callFrame->registers() - registerFile->start() + registerOffset, scopeChain, &exceptionValue);
@@ -449,7 +470,7 @@ bool Interpreter::isOpcode(Opcode opcode)
#endif
}
-NEVER_INLINE bool Interpreter::unwindCallFrame(CallFrame*& callFrame, JSValuePtr exceptionValue, unsigned& bytecodeOffset, CodeBlock*& codeBlock)
+NEVER_INLINE bool Interpreter::unwindCallFrame(CallFrame*& callFrame, JSValue exceptionValue, unsigned& bytecodeOffset, CodeBlock*& codeBlock)
{
CodeBlock* oldCodeBlock = codeBlock;
ScopeChainNode* scopeChain = callFrame->scopeChain();
@@ -492,7 +513,7 @@ NEVER_INLINE bool Interpreter::unwindCallFrame(CallFrame*& callFrame, JSValuePtr
return true;
}
-NEVER_INLINE HandlerInfo* Interpreter::throwException(CallFrame*& callFrame, JSValuePtr& exceptionValue, unsigned bytecodeOffset, bool explicitThrow)
+NEVER_INLINE HandlerInfo* Interpreter::throwException(CallFrame*& callFrame, JSValue& exceptionValue, unsigned bytecodeOffset, bool explicitThrow)
{
// Set up the exception object
@@ -546,13 +567,13 @@ NEVER_INLINE HandlerInfo* Interpreter::throwException(CallFrame*& callFrame, JSV
if (Profiler* profiler = *Profiler::enabledProfilerReference()) {
#if !ENABLE(JIT)
if (isCallBytecode(codeBlock->instructions()[bytecodeOffset].u.opcode))
- profiler->didExecute(callFrame, callFrame[codeBlock->instructions()[bytecodeOffset + 2].u.operand].jsValue(callFrame));
+ profiler->didExecute(callFrame, callFrame[codeBlock->instructions()[bytecodeOffset + 2].u.operand].jsValue());
else if (codeBlock->instructions()[bytecodeOffset + 8].u.opcode == getOpcode(op_construct))
- profiler->didExecute(callFrame, callFrame[codeBlock->instructions()[bytecodeOffset + 10].u.operand].jsValue(callFrame));
+ profiler->didExecute(callFrame, callFrame[codeBlock->instructions()[bytecodeOffset + 10].u.operand].jsValue());
#else
int functionRegisterIndex;
if (codeBlock->functionRegisterForBytecodeOffset(bytecodeOffset, functionRegisterIndex))
- profiler->didExecute(callFrame, callFrame[functionRegisterIndex].jsValue(callFrame));
+ profiler->didExecute(callFrame, callFrame[functionRegisterIndex].jsValue());
#endif
}
@@ -577,13 +598,15 @@ NEVER_INLINE HandlerInfo* Interpreter::throwException(CallFrame*& callFrame, JSV
return handler;
}
-JSValuePtr Interpreter::execute(ProgramNode* programNode, CallFrame* callFrame, ScopeChainNode* scopeChain, JSObject* thisObj, JSValuePtr* exception)
+JSValue Interpreter::execute(ProgramNode* programNode, CallFrame* callFrame, ScopeChainNode* scopeChain, JSObject* thisObj, JSValue* exception)
{
ASSERT(!scopeChain->globalData->exception);
- if (m_reentryDepth >= MaxReentryDepth) {
- *exception = createStackOverflowError(callFrame);
- return jsNull();
+ if (m_reentryDepth >= MaxSecondaryThreadReentryDepth) {
+ if (!isMainThread() || m_reentryDepth >= MaxMainThreadReentryDepth) {
+ *exception = createStackOverflowError(callFrame);
+ return jsNull();
+ }
}
CodeBlock* codeBlock = &programNode->bytecode(scopeChain);
@@ -602,7 +625,7 @@ JSValuePtr Interpreter::execute(ProgramNode* programNode, CallFrame* callFrame,
globalObject->copyGlobalsTo(m_registerFile);
CallFrame* newCallFrame = CallFrame::create(oldEnd + codeBlock->m_numParameters + RegisterFile::CallFrameHeaderSize);
- newCallFrame[codeBlock->thisRegister()] = JSValuePtr(thisObj);
+ newCallFrame[codeBlock->thisRegister()] = JSValue(thisObj);
newCallFrame->init(codeBlock, 0, scopeChain, CallFrame::noCaller(), 0, 0, 0);
if (codeBlock->needsFullScopeChain())
@@ -612,15 +635,13 @@ JSValuePtr Interpreter::execute(ProgramNode* programNode, CallFrame* callFrame,
if (*profiler)
(*profiler)->willExecute(newCallFrame, programNode->sourceURL(), programNode->lineNo());
- JSValuePtr result;
+ JSValue result;
{
SamplingTool::CallRecord callRecord(m_sampler);
m_reentryDepth++;
#if ENABLE(JIT)
- if (!codeBlock->jitCode())
- JIT::compile(scopeChain->globalData, codeBlock);
- result = codeBlock->jitCode().execute(&m_registerFile, newCallFrame, scopeChain->globalData, exception);
+ result = programNode->jitCode(scopeChain).execute(&m_registerFile, newCallFrame, scopeChain->globalData, exception);
#else
result = privateExecute(Normal, &m_registerFile, newCallFrame, exception);
#endif
@@ -638,13 +659,15 @@ JSValuePtr Interpreter::execute(ProgramNode* programNode, CallFrame* callFrame,
return result;
}
-JSValuePtr Interpreter::execute(FunctionBodyNode* functionBodyNode, CallFrame* callFrame, JSFunction* function, JSObject* thisObj, const ArgList& args, ScopeChainNode* scopeChain, JSValuePtr* exception)
+JSValue Interpreter::execute(FunctionBodyNode* functionBodyNode, CallFrame* callFrame, JSFunction* function, JSObject* thisObj, const ArgList& args, ScopeChainNode* scopeChain, JSValue* exception)
{
ASSERT(!scopeChain->globalData->exception);
- if (m_reentryDepth >= MaxReentryDepth) {
- *exception = createStackOverflowError(callFrame);
- return jsNull();
+ if (m_reentryDepth >= MaxSecondaryThreadReentryDepth) {
+ if (!isMainThread() || m_reentryDepth >= MaxMainThreadReentryDepth) {
+ *exception = createStackOverflowError(callFrame);
+ return jsNull();
+ }
}
Register* oldEnd = m_registerFile.end();
@@ -659,7 +682,7 @@ JSValuePtr Interpreter::execute(FunctionBodyNode* functionBodyNode, CallFrame* c
CallFrame* newCallFrame = CallFrame::create(oldEnd);
size_t dst = 0;
- newCallFrame[0] = JSValuePtr(thisObj);
+ newCallFrame[0] = JSValue(thisObj);
ArgList::const_iterator end = args.end();
for (ArgList::const_iterator it = args.begin(); it != end; ++it)
newCallFrame[++dst] = *it;
@@ -678,15 +701,13 @@ JSValuePtr Interpreter::execute(FunctionBodyNode* functionBodyNode, CallFrame* c
if (*profiler)
(*profiler)->willExecute(callFrame, function);
- JSValuePtr result;
+ JSValue result;
{
SamplingTool::CallRecord callRecord(m_sampler);
m_reentryDepth++;
#if ENABLE(JIT)
- if (!codeBlock->jitCode())
- JIT::compile(scopeChain->globalData, codeBlock);
- result = codeBlock->jitCode().execute(&m_registerFile, newCallFrame, scopeChain->globalData, exception);
+ result = functionBodyNode->jitCode(scopeChain).execute(&m_registerFile, newCallFrame, scopeChain->globalData, exception);
#else
result = privateExecute(Normal, &m_registerFile, newCallFrame, exception);
#endif
@@ -700,18 +721,91 @@ JSValuePtr Interpreter::execute(FunctionBodyNode* functionBodyNode, CallFrame* c
return result;
}
-JSValuePtr Interpreter::execute(EvalNode* evalNode, CallFrame* callFrame, JSObject* thisObj, ScopeChainNode* scopeChain, JSValuePtr* exception)
+CallFrameClosure Interpreter::prepareForRepeatCall(FunctionBodyNode* functionBodyNode, CallFrame* callFrame, JSFunction* function, int argCount, ScopeChainNode* scopeChain, JSValue* exception)
+{
+ ASSERT(!scopeChain->globalData->exception);
+
+ if (m_reentryDepth >= MaxSecondaryThreadReentryDepth) {
+ if (!isMainThread() || m_reentryDepth >= MaxMainThreadReentryDepth) {
+ *exception = createStackOverflowError(callFrame);
+ return CallFrameClosure();
+ }
+ }
+
+ Register* oldEnd = m_registerFile.end();
+ int argc = 1 + argCount; // implicit "this" parameter
+
+ if (!m_registerFile.grow(oldEnd + argc)) {
+ *exception = createStackOverflowError(callFrame);
+ return CallFrameClosure();
+ }
+
+ CallFrame* newCallFrame = CallFrame::create(oldEnd);
+ size_t dst = 0;
+ for (int i = 0; i < argc; ++i)
+ newCallFrame[++dst] = jsUndefined();
+
+ CodeBlock* codeBlock = &functionBodyNode->bytecode(scopeChain);
+ newCallFrame = slideRegisterWindowForCall(codeBlock, &m_registerFile, newCallFrame, argc + RegisterFile::CallFrameHeaderSize, argc);
+ if (UNLIKELY(!newCallFrame)) {
+ *exception = createStackOverflowError(callFrame);
+ m_registerFile.shrink(oldEnd);
+ return CallFrameClosure();
+ }
+ // a 0 codeBlock indicates a built-in caller
+ newCallFrame->init(codeBlock, 0, scopeChain, callFrame->addHostCallFrameFlag(), 0, argc, function);
+#if ENABLE(JIT)
+ functionBodyNode->jitCode(scopeChain);
+#endif
+
+ CallFrameClosure result = { callFrame, newCallFrame, function, functionBodyNode, scopeChain->globalData, oldEnd, scopeChain, codeBlock->m_numParameters, argc };
+ return result;
+}
+
+JSValue Interpreter::execute(CallFrameClosure& closure, JSValue* exception)
+{
+ closure.resetCallFrame();
+ Profiler** profiler = Profiler::enabledProfilerReference();
+ if (*profiler)
+ (*profiler)->willExecute(closure.oldCallFrame, closure.function);
+
+ JSValue result;
+ {
+ SamplingTool::CallRecord callRecord(m_sampler);
+
+ m_reentryDepth++;
+#if ENABLE(JIT)
+ result = closure.functionBody->generatedJITCode().execute(&m_registerFile, closure.newCallFrame, closure.globalData, exception);
+#else
+ result = privateExecute(Normal, &m_registerFile, closure.newCallFrame, exception);
+#endif
+ m_reentryDepth--;
+ }
+
+ if (*profiler)
+ (*profiler)->didExecute(closure.oldCallFrame, closure.function);
+ return result;
+}
+
+void Interpreter::endRepeatCall(CallFrameClosure& closure)
+{
+ m_registerFile.shrink(closure.oldEnd);
+}
+
+JSValue Interpreter::execute(EvalNode* evalNode, CallFrame* callFrame, JSObject* thisObj, ScopeChainNode* scopeChain, JSValue* exception)
{
return execute(evalNode, callFrame, thisObj, m_registerFile.size() + evalNode->bytecode(scopeChain).m_numParameters + RegisterFile::CallFrameHeaderSize, scopeChain, exception);
}
-JSValuePtr Interpreter::execute(EvalNode* evalNode, CallFrame* callFrame, JSObject* thisObj, int globalRegisterOffset, ScopeChainNode* scopeChain, JSValuePtr* exception)
+JSValue Interpreter::execute(EvalNode* evalNode, CallFrame* callFrame, JSObject* thisObj, int globalRegisterOffset, ScopeChainNode* scopeChain, JSValue* exception)
{
ASSERT(!scopeChain->globalData->exception);
- if (m_reentryDepth >= MaxReentryDepth) {
- *exception = createStackOverflowError(callFrame);
- return jsNull();
+ if (m_reentryDepth >= MaxSecondaryThreadReentryDepth) {
+ if (!isMainThread() || m_reentryDepth >= MaxMainThreadReentryDepth) {
+ *exception = createStackOverflowError(callFrame);
+ return jsNull();
+ }
}
DynamicGlobalObjectScope globalObjectScope(callFrame, callFrame->globalData().dynamicGlobalObject ? callFrame->globalData().dynamicGlobalObject : scopeChain->globalObject());
@@ -760,7 +854,7 @@ JSValuePtr Interpreter::execute(EvalNode* evalNode, CallFrame* callFrame, JSObje
CallFrame* newCallFrame = CallFrame::create(m_registerFile.start() + globalRegisterOffset);
// a 0 codeBlock indicates a built-in caller
- newCallFrame[codeBlock->thisRegister()] = JSValuePtr(thisObj);
+ newCallFrame[codeBlock->thisRegister()] = JSValue(thisObj);
newCallFrame->init(codeBlock, 0, scopeChain, callFrame->addHostCallFrameFlag(), 0, 0, 0);
if (codeBlock->needsFullScopeChain())
@@ -770,15 +864,13 @@ JSValuePtr Interpreter::execute(EvalNode* evalNode, CallFrame* callFrame, JSObje
if (*profiler)
(*profiler)->willExecute(newCallFrame, evalNode->sourceURL(), evalNode->lineNo());
- JSValuePtr result;
+ JSValue result;
{
SamplingTool::CallRecord callRecord(m_sampler);
m_reentryDepth++;
#if ENABLE(JIT)
- if (!codeBlock->jitCode())
- JIT::compile(scopeChain->globalData, codeBlock);
- result = codeBlock->jitCode().execute(&m_registerFile, newCallFrame, scopeChain->globalData, exception);
+ result = evalNode->jitCode(scopeChain).execute(&m_registerFile, newCallFrame, scopeChain->globalData, exception);
#else
result = privateExecute(Normal, &m_registerFile, newCallFrame, exception);
#endif
@@ -819,30 +911,21 @@ NEVER_INLINE void Interpreter::debug(CallFrame* callFrame, DebugHookID debugHook
return;
}
}
-
+
+#if USE(INTERPRETER)
NEVER_INLINE ScopeChainNode* Interpreter::createExceptionScope(CallFrame* callFrame, const Instruction* vPC)
{
int dst = (++vPC)->u.operand;
CodeBlock* codeBlock = callFrame->codeBlock();
Identifier& property = codeBlock->identifier((++vPC)->u.operand);
- JSValuePtr value = callFrame[(++vPC)->u.operand].jsValue(callFrame);
+ JSValue value = callFrame[(++vPC)->u.operand].jsValue();
JSObject* scope = new (callFrame) JSStaticScopeObject(callFrame, property, value, DontDelete);
- callFrame[dst] = JSValuePtr(scope);
+ callFrame[dst] = JSValue(scope);
return callFrame->scopeChain()->push(scope);
}
-static StructureChain* cachePrototypeChain(CallFrame* callFrame, Structure* structure)
-{
- JSValuePtr prototype = structure->prototypeForLookup(callFrame);
- if (!prototype.isCell())
- return 0;
- RefPtr<StructureChain> chain = StructureChain::create(asObject(prototype)->structure());
- structure->setCachedPrototypeChain(chain.release());
- return structure->cachedPrototypeChain();
-}
-
-NEVER_INLINE void Interpreter::tryCachePutByID(CallFrame* callFrame, CodeBlock* codeBlock, Instruction* vPC, JSValuePtr baseValue, const PutPropertySlot& slot)
+NEVER_INLINE void Interpreter::tryCachePutByID(CallFrame* callFrame, CodeBlock* codeBlock, Instruction* vPC, JSValue baseValue, const PutPropertySlot& slot)
{
// Recursive invocation may already have specialized this instruction.
if (vPC[0].u.opcode != getOpcode(op_put_by_id))
@@ -892,16 +975,7 @@ NEVER_INLINE void Interpreter::tryCachePutByID(CallFrame* callFrame, CodeBlock*
vPC[0] = getOpcode(op_put_by_id_transition);
vPC[4] = structure->previousID();
vPC[5] = structure;
- StructureChain* chain = structure->cachedPrototypeChain();
- if (!chain) {
- chain = cachePrototypeChain(callFrame, structure);
- if (!chain) {
- // This happens if someone has manually inserted null into the prototype chain
- vPC[0] = getOpcode(op_put_by_id_generic);
- return;
- }
- }
- vPC[6] = chain;
+ vPC[6] = structure->prototypeChain(callFrame);
vPC[7] = slot.cachedOffset();
codeBlock->refStructures(vPC);
return;
@@ -919,7 +993,7 @@ NEVER_INLINE void Interpreter::uncachePutByID(CodeBlock* codeBlock, Instruction*
vPC[4] = 0;
}
-NEVER_INLINE void Interpreter::tryCacheGetByID(CallFrame* callFrame, CodeBlock* codeBlock, Instruction* vPC, JSValuePtr baseValue, const Identifier& propertyName, const PropertySlot& slot)
+NEVER_INLINE void Interpreter::tryCacheGetByID(CallFrame* callFrame, CodeBlock* codeBlock, Instruction* vPC, JSValue baseValue, const Identifier& propertyName, const PropertySlot& slot)
{
// Recursive invocation may already have specialized this instruction.
if (vPC[0].u.opcode != getOpcode(op_get_by_id))
@@ -986,11 +1060,8 @@ NEVER_INLINE void Interpreter::tryCacheGetByID(CallFrame* callFrame, CodeBlock*
// Since we're accessing a prototype in a loop, it's a good bet that it
// should not be treated as a dictionary.
- if (baseObject->structure()->isDictionary()) {
- RefPtr<Structure> transition = Structure::fromDictionaryTransition(baseObject->structure());
- baseObject->setStructure(transition.release());
- asCell(baseValue)->structure()->setCachedPrototypeChain(0);
- }
+ if (baseObject->structure()->isDictionary())
+ baseObject->setStructure(Structure::fromDictionaryTransition(baseObject->structure()));
vPC[0] = getOpcode(op_get_by_id_proto);
vPC[5] = baseObject->structure();
@@ -1006,14 +1077,9 @@ NEVER_INLINE void Interpreter::tryCacheGetByID(CallFrame* callFrame, CodeBlock*
return;
}
- StructureChain* chain = structure->cachedPrototypeChain();
- if (!chain)
- chain = cachePrototypeChain(callFrame, structure);
- ASSERT(chain);
-
vPC[0] = getOpcode(op_get_by_id_chain);
vPC[4] = structure;
- vPC[5] = chain;
+ vPC[5] = structure->prototypeChain(callFrame);
vPC[6] = count;
vPC[7] = slot.cachedOffset();
codeBlock->refStructures(vPC);
@@ -1026,7 +1092,9 @@ NEVER_INLINE void Interpreter::uncacheGetByID(CodeBlock* codeBlock, Instruction*
vPC[4] = 0;
}
-JSValuePtr Interpreter::privateExecute(ExecutionFlag flag, RegisterFile* registerFile, CallFrame* callFrame, JSValuePtr* exception)
+#endif // USE(INTERPRETER)
+
+JSValue Interpreter::privateExecute(ExecutionFlag flag, RegisterFile* registerFile, CallFrame* callFrame, JSValue* exception)
{
// One-time initialization of our address tables. We have to put this code
// here because our labels are only in scope inside this function.
@@ -1041,16 +1109,22 @@ JSValuePtr Interpreter::privateExecute(ExecutionFlag flag, RegisterFile* registe
#undef ADD_OPCODE_ID
ASSERT(m_opcodeIDTable.size() == numOpcodeIDs);
#endif // HAVE(COMPUTED_GOTO)
- return noValue();
+ return JSValue();
}
#if ENABLE(JIT)
// Currently with CTI enabled we never interpret functions
ASSERT_NOT_REACHED();
#endif
+#if !USE(INTERPRETER)
+ UNUSED_PARAM(registerFile);
+ UNUSED_PARAM(callFrame);
+ UNUSED_PARAM(exception);
+ return JSValue();
+#else
JSGlobalData* globalData = &callFrame->globalData();
- JSValuePtr exceptionValue = noValue();
+ JSValue exceptionValue;
HandlerInfo* handler = 0;
Instruction* vPC = callFrame->codeBlock()->instructions().begin();
@@ -1059,7 +1133,7 @@ JSValuePtr Interpreter::privateExecute(ExecutionFlag flag, RegisterFile* registe
#define CHECK_FOR_EXCEPTION() \
do { \
- if (UNLIKELY(globalData->exception != noValue())) { \
+ if (UNLIKELY(globalData->exception != JSValue())) { \
exceptionValue = globalData->exception; \
goto vm_throw; \
} \
@@ -1111,7 +1185,7 @@ JSValuePtr Interpreter::privateExecute(ExecutionFlag flag, RegisterFile* registe
constructor, and puts the result in register dst.
*/
int dst = (++vPC)->u.operand;
- callFrame[dst] = JSValuePtr(constructEmptyObject(callFrame));
+ callFrame[dst] = JSValue(constructEmptyObject(callFrame));
++vPC;
NEXT_INSTRUCTION();
@@ -1128,7 +1202,7 @@ JSValuePtr Interpreter::privateExecute(ExecutionFlag flag, RegisterFile* registe
int firstArg = (++vPC)->u.operand;
int argCount = (++vPC)->u.operand;
ArgList args(callFrame->registers() + firstArg, argCount);
- callFrame[dst] = JSValuePtr(constructArray(callFrame, args));
+ callFrame[dst] = JSValue(constructArray(callFrame, args));
++vPC;
NEXT_INSTRUCTION();
@@ -1142,7 +1216,7 @@ JSValuePtr Interpreter::privateExecute(ExecutionFlag flag, RegisterFile* registe
*/
int dst = (++vPC)->u.operand;
int regExp = (++vPC)->u.operand;
- callFrame[dst] = JSValuePtr(new (globalData) RegExpObject(callFrame->scopeChain()->globalObject()->regExpStructure(), callFrame->codeBlock()->regexp(regExp)));
+ callFrame[dst] = JSValue(new (globalData) RegExpObject(callFrame->scopeChain()->globalObject()->regExpStructure(), callFrame->codeBlock()->regexp(regExp)));
++vPC;
NEXT_INSTRUCTION();
@@ -1167,12 +1241,12 @@ JSValuePtr Interpreter::privateExecute(ExecutionFlag flag, RegisterFile* registe
as a boolean in register dst.
*/
int dst = (++vPC)->u.operand;
- JSValuePtr src1 = callFrame[(++vPC)->u.operand].jsValue(callFrame);
- JSValuePtr src2 = callFrame[(++vPC)->u.operand].jsValue(callFrame);
+ JSValue src1 = callFrame[(++vPC)->u.operand].jsValue();
+ JSValue src2 = callFrame[(++vPC)->u.operand].jsValue();
if (JSFastMath::canDoFastBitwiseOperations(src1, src2))
callFrame[dst] = JSFastMath::equal(src1, src2);
else {
- JSValuePtr result = jsBoolean(JSValuePtr::equalSlowCase(callFrame, src1, src2));
+ JSValue result = jsBoolean(JSValue::equalSlowCase(callFrame, src1, src2));
CHECK_FOR_EXCEPTION();
callFrame[dst] = result;
}
@@ -1187,7 +1261,7 @@ JSValuePtr Interpreter::privateExecute(ExecutionFlag flag, RegisterFile* registe
operator, and puts the result as a boolean in register dst.
*/
int dst = (++vPC)->u.operand;
- JSValuePtr src = callFrame[(++vPC)->u.operand].jsValue(callFrame);
+ JSValue src = callFrame[(++vPC)->u.operand].jsValue();
if (src.isUndefinedOrNull()) {
callFrame[dst] = jsBoolean(true);
@@ -1207,12 +1281,12 @@ JSValuePtr Interpreter::privateExecute(ExecutionFlag flag, RegisterFile* registe
result as a boolean in register dst.
*/
int dst = (++vPC)->u.operand;
- JSValuePtr src1 = callFrame[(++vPC)->u.operand].jsValue(callFrame);
- JSValuePtr src2 = callFrame[(++vPC)->u.operand].jsValue(callFrame);
+ JSValue src1 = callFrame[(++vPC)->u.operand].jsValue();
+ JSValue src2 = callFrame[(++vPC)->u.operand].jsValue();
if (JSFastMath::canDoFastBitwiseOperations(src1, src2))
callFrame[dst] = JSFastMath::notEqual(src1, src2);
else {
- JSValuePtr result = jsBoolean(!JSValuePtr::equalSlowCase(callFrame, src1, src2));
+ JSValue result = jsBoolean(!JSValue::equalSlowCase(callFrame, src1, src2));
CHECK_FOR_EXCEPTION();
callFrame[dst] = result;
}
@@ -1227,7 +1301,7 @@ JSValuePtr Interpreter::privateExecute(ExecutionFlag flag, RegisterFile* registe
operator, and puts the result as a boolean in register dst.
*/
int dst = (++vPC)->u.operand;
- JSValuePtr src = callFrame[(++vPC)->u.operand].jsValue(callFrame);
+ JSValue src = callFrame[(++vPC)->u.operand].jsValue();
if (src.isUndefinedOrNull()) {
callFrame[dst] = jsBoolean(false);
@@ -1247,9 +1321,9 @@ JSValuePtr Interpreter::privateExecute(ExecutionFlag flag, RegisterFile* registe
result as a boolean in register dst.
*/
int dst = (++vPC)->u.operand;
- JSValuePtr src1 = callFrame[(++vPC)->u.operand].jsValue(callFrame);
- JSValuePtr src2 = callFrame[(++vPC)->u.operand].jsValue(callFrame);
- callFrame[dst] = jsBoolean(JSValuePtr::strictEqual(src1, src2));
+ JSValue src1 = callFrame[(++vPC)->u.operand].jsValue();
+ JSValue src2 = callFrame[(++vPC)->u.operand].jsValue();
+ callFrame[dst] = jsBoolean(JSValue::strictEqual(src1, src2));
++vPC;
NEXT_INSTRUCTION();
@@ -1262,9 +1336,9 @@ JSValuePtr Interpreter::privateExecute(ExecutionFlag flag, RegisterFile* registe
puts the result as a boolean in register dst.
*/
int dst = (++vPC)->u.operand;
- JSValuePtr src1 = callFrame[(++vPC)->u.operand].jsValue(callFrame);
- JSValuePtr src2 = callFrame[(++vPC)->u.operand].jsValue(callFrame);
- callFrame[dst] = jsBoolean(!JSValuePtr::strictEqual(src1, src2));
+ JSValue src1 = callFrame[(++vPC)->u.operand].jsValue();
+ JSValue src2 = callFrame[(++vPC)->u.operand].jsValue();
+ callFrame[dst] = jsBoolean(!JSValue::strictEqual(src1, src2));
++vPC;
NEXT_INSTRUCTION();
@@ -1277,9 +1351,9 @@ JSValuePtr Interpreter::privateExecute(ExecutionFlag flag, RegisterFile* registe
a boolean in register dst.
*/
int dst = (++vPC)->u.operand;
- JSValuePtr src1 = callFrame[(++vPC)->u.operand].jsValue(callFrame);
- JSValuePtr src2 = callFrame[(++vPC)->u.operand].jsValue(callFrame);
- JSValuePtr result = jsBoolean(jsLess(callFrame, src1, src2));
+ JSValue src1 = callFrame[(++vPC)->u.operand].jsValue();
+ JSValue src2 = callFrame[(++vPC)->u.operand].jsValue();
+ JSValue result = jsBoolean(jsLess(callFrame, src1, src2));
CHECK_FOR_EXCEPTION();
callFrame[dst] = result;
@@ -1294,9 +1368,9 @@ JSValuePtr Interpreter::privateExecute(ExecutionFlag flag, RegisterFile* registe
puts the result as a boolean in register dst.
*/
int dst = (++vPC)->u.operand;
- JSValuePtr src1 = callFrame[(++vPC)->u.operand].jsValue(callFrame);
- JSValuePtr src2 = callFrame[(++vPC)->u.operand].jsValue(callFrame);
- JSValuePtr result = jsBoolean(jsLessEq(callFrame, src1, src2));
+ JSValue src1 = callFrame[(++vPC)->u.operand].jsValue();
+ JSValue src2 = callFrame[(++vPC)->u.operand].jsValue();
+ JSValue result = jsBoolean(jsLessEq(callFrame, src1, src2));
CHECK_FOR_EXCEPTION();
callFrame[dst] = result;
@@ -1310,11 +1384,11 @@ JSValuePtr Interpreter::privateExecute(ExecutionFlag flag, RegisterFile* registe
back in register srcDst.
*/
int srcDst = (++vPC)->u.operand;
- JSValuePtr v = callFrame[srcDst].jsValue(callFrame);
+ JSValue v = callFrame[srcDst].jsValue();
if (JSFastMath::canDoFastAdditiveOperations(v))
- callFrame[srcDst] = JSValuePtr(JSFastMath::incImmediateNumber(v));
+ callFrame[srcDst] = JSValue(JSFastMath::incImmediateNumber(v));
else {
- JSValuePtr result = jsNumber(callFrame, v.toNumber(callFrame) + 1);
+ JSValue result = jsNumber(callFrame, v.toNumber(callFrame) + 1);
CHECK_FOR_EXCEPTION();
callFrame[srcDst] = result;
}
@@ -1329,11 +1403,11 @@ JSValuePtr Interpreter::privateExecute(ExecutionFlag flag, RegisterFile* registe
back in register srcDst.
*/
int srcDst = (++vPC)->u.operand;
- JSValuePtr v = callFrame[srcDst].jsValue(callFrame);
+ JSValue v = callFrame[srcDst].jsValue();
if (JSFastMath::canDoFastAdditiveOperations(v))
- callFrame[srcDst] = JSValuePtr(JSFastMath::decImmediateNumber(v));
+ callFrame[srcDst] = JSValue(JSFastMath::decImmediateNumber(v));
else {
- JSValuePtr result = jsNumber(callFrame, v.toNumber(callFrame) - 1);
+ JSValue result = jsNumber(callFrame, v.toNumber(callFrame) - 1);
CHECK_FOR_EXCEPTION();
callFrame[srcDst] = result;
}
@@ -1350,15 +1424,15 @@ JSValuePtr Interpreter::privateExecute(ExecutionFlag flag, RegisterFile* registe
*/
int dst = (++vPC)->u.operand;
int srcDst = (++vPC)->u.operand;
- JSValuePtr v = callFrame[srcDst].jsValue(callFrame);
+ JSValue v = callFrame[srcDst].jsValue();
if (JSFastMath::canDoFastAdditiveOperations(v)) {
callFrame[dst] = v;
- callFrame[srcDst] = JSValuePtr(JSFastMath::incImmediateNumber(v));
+ callFrame[srcDst] = JSValue(JSFastMath::incImmediateNumber(v));
} else {
- JSValuePtr number = callFrame[srcDst].jsValue(callFrame).toJSNumber(callFrame);
+ JSValue number = callFrame[srcDst].jsValue().toJSNumber(callFrame);
CHECK_FOR_EXCEPTION();
callFrame[dst] = number;
- callFrame[srcDst] = JSValuePtr(jsNumber(callFrame, number.uncheckedGetNumber() + 1));
+ callFrame[srcDst] = JSValue(jsNumber(callFrame, number.uncheckedGetNumber() + 1));
}
++vPC;
@@ -1373,15 +1447,15 @@ JSValuePtr Interpreter::privateExecute(ExecutionFlag flag, RegisterFile* registe
*/
int dst = (++vPC)->u.operand;
int srcDst = (++vPC)->u.operand;
- JSValuePtr v = callFrame[srcDst].jsValue(callFrame);
+ JSValue v = callFrame[srcDst].jsValue();
if (JSFastMath::canDoFastAdditiveOperations(v)) {
callFrame[dst] = v;
- callFrame[srcDst] = JSValuePtr(JSFastMath::decImmediateNumber(v));
+ callFrame[srcDst] = JSValue(JSFastMath::decImmediateNumber(v));
} else {
- JSValuePtr number = callFrame[srcDst].jsValue(callFrame).toJSNumber(callFrame);
+ JSValue number = callFrame[srcDst].jsValue().toJSNumber(callFrame);
CHECK_FOR_EXCEPTION();
callFrame[dst] = number;
- callFrame[srcDst] = JSValuePtr(jsNumber(callFrame, number.uncheckedGetNumber() - 1));
+ callFrame[srcDst] = JSValue(jsNumber(callFrame, number.uncheckedGetNumber() - 1));
}
++vPC;
@@ -1396,12 +1470,12 @@ JSValuePtr Interpreter::privateExecute(ExecutionFlag flag, RegisterFile* registe
int dst = (++vPC)->u.operand;
int src = (++vPC)->u.operand;
- JSValuePtr srcVal = callFrame[src].jsValue(callFrame);
+ JSValue srcVal = callFrame[src].jsValue();
if (LIKELY(srcVal.isNumber()))
callFrame[dst] = callFrame[src];
else {
- JSValuePtr result = srcVal.toJSNumber(callFrame);
+ JSValue result = srcVal.toJSNumber(callFrame);
CHECK_FOR_EXCEPTION();
callFrame[dst] = result;
}
@@ -1416,13 +1490,13 @@ JSValuePtr Interpreter::privateExecute(ExecutionFlag flag, RegisterFile* registe
result in register dst.
*/
int dst = (++vPC)->u.operand;
- JSValuePtr src = callFrame[(++vPC)->u.operand].jsValue(callFrame);
+ JSValue src = callFrame[(++vPC)->u.operand].jsValue();
++vPC;
double v;
if (src.getNumber(v))
- callFrame[dst] = JSValuePtr(jsNumber(callFrame, -v));
+ callFrame[dst] = JSValue(jsNumber(callFrame, -v));
else {
- JSValuePtr result = jsNumber(callFrame, -src.toNumber(callFrame));
+ JSValue result = jsNumber(callFrame, -src.toNumber(callFrame));
CHECK_FOR_EXCEPTION();
callFrame[dst] = result;
}
@@ -1437,12 +1511,12 @@ JSValuePtr Interpreter::privateExecute(ExecutionFlag flag, RegisterFile* registe
numeric add, depending on the types of the operands.)
*/
int dst = (++vPC)->u.operand;
- JSValuePtr src1 = callFrame[(++vPC)->u.operand].jsValue(callFrame);
- JSValuePtr src2 = callFrame[(++vPC)->u.operand].jsValue(callFrame);
+ JSValue src1 = callFrame[(++vPC)->u.operand].jsValue();
+ JSValue src2 = callFrame[(++vPC)->u.operand].jsValue();
if (JSFastMath::canDoFastAdditiveOperations(src1, src2))
- callFrame[dst] = JSValuePtr(JSFastMath::addImmediateNumbers(src1, src2));
+ callFrame[dst] = JSValue(JSFastMath::addImmediateNumbers(src1, src2));
else {
- JSValuePtr result = jsAdd(callFrame, src1, src2);
+ JSValue result = jsAdd(callFrame, src1, src2);
CHECK_FOR_EXCEPTION();
callFrame[dst] = result;
}
@@ -1456,21 +1530,21 @@ JSValuePtr Interpreter::privateExecute(ExecutionFlag flag, RegisterFile* registe
numbers), and puts the product in register dst.
*/
int dst = (++vPC)->u.operand;
- JSValuePtr src1 = callFrame[(++vPC)->u.operand].jsValue(callFrame);
- JSValuePtr src2 = callFrame[(++vPC)->u.operand].jsValue(callFrame);
+ JSValue src1 = callFrame[(++vPC)->u.operand].jsValue();
+ JSValue src2 = callFrame[(++vPC)->u.operand].jsValue();
double left;
double right;
- if (JSValuePtr::areBothInt32Fast(src1, src2)) {
+ if (JSValue::areBothInt32Fast(src1, src2)) {
int32_t left = src1.getInt32Fast();
int32_t right = src2.getInt32Fast();
if ((left | right) >> 15 == 0)
- callFrame[dst] = JSValuePtr(jsNumber(callFrame, left * right));
+ callFrame[dst] = JSValue(jsNumber(callFrame, left * right));
else
- callFrame[dst] = JSValuePtr(jsNumber(callFrame, static_cast<double>(left) * static_cast<double>(right)));
+ callFrame[dst] = JSValue(jsNumber(callFrame, static_cast<double>(left) * static_cast<double>(right)));
} else if (src1.getNumber(left) && src2.getNumber(right))
- callFrame[dst] = JSValuePtr(jsNumber(callFrame, left * right));
+ callFrame[dst] = JSValue(jsNumber(callFrame, left * right));
else {
- JSValuePtr result = jsNumber(callFrame, src1.toNumber(callFrame) * src2.toNumber(callFrame));
+ JSValue result = jsNumber(callFrame, src1.toNumber(callFrame) * src2.toNumber(callFrame));
CHECK_FOR_EXCEPTION();
callFrame[dst] = result;
}
@@ -1486,14 +1560,14 @@ JSValuePtr Interpreter::privateExecute(ExecutionFlag flag, RegisterFile* registe
quotient in register dst.
*/
int dst = (++vPC)->u.operand;
- JSValuePtr dividend = callFrame[(++vPC)->u.operand].jsValue(callFrame);
- JSValuePtr divisor = callFrame[(++vPC)->u.operand].jsValue(callFrame);
+ JSValue dividend = callFrame[(++vPC)->u.operand].jsValue();
+ JSValue divisor = callFrame[(++vPC)->u.operand].jsValue();
double left;
double right;
if (dividend.getNumber(left) && divisor.getNumber(right))
- callFrame[dst] = JSValuePtr(jsNumber(callFrame, left / right));
+ callFrame[dst] = JSValue(jsNumber(callFrame, left / right));
else {
- JSValuePtr result = jsNumber(callFrame, dividend.toNumber(callFrame) / divisor.toNumber(callFrame));
+ JSValue result = jsNumber(callFrame, dividend.toNumber(callFrame) / divisor.toNumber(callFrame));
CHECK_FOR_EXCEPTION();
callFrame[dst] = result;
}
@@ -1511,13 +1585,13 @@ JSValuePtr Interpreter::privateExecute(ExecutionFlag flag, RegisterFile* registe
int dividend = (++vPC)->u.operand;
int divisor = (++vPC)->u.operand;
- JSValuePtr dividendValue = callFrame[dividend].jsValue(callFrame);
- JSValuePtr divisorValue = callFrame[divisor].jsValue(callFrame);
+ JSValue dividendValue = callFrame[dividend].jsValue();
+ JSValue divisorValue = callFrame[divisor].jsValue();
- if (JSValuePtr::areBothInt32Fast(dividendValue, divisorValue) && divisorValue != js0()) {
+ if (JSValue::areBothInt32Fast(dividendValue, divisorValue) && divisorValue != jsNumber(callFrame, 0)) {
// We expect the result of the modulus of a number that was representable as an int32 to also be representable
// as an int32.
- JSValuePtr result = JSValuePtr::makeInt32Fast(dividendValue.getInt32Fast() % divisorValue.getInt32Fast());
+ JSValue result = JSValue::makeInt32Fast(dividendValue.getInt32Fast() % divisorValue.getInt32Fast());
ASSERT(result);
callFrame[dst] = result;
++vPC;
@@ -1525,7 +1599,7 @@ JSValuePtr Interpreter::privateExecute(ExecutionFlag flag, RegisterFile* registe
}
double d = dividendValue.toNumber(callFrame);
- JSValuePtr result = jsNumber(callFrame, fmod(d, divisorValue.toNumber(callFrame)));
+ JSValue result = jsNumber(callFrame, fmod(d, divisorValue.toNumber(callFrame)));
CHECK_FOR_EXCEPTION();
callFrame[dst] = result;
++vPC;
@@ -1539,16 +1613,16 @@ JSValuePtr Interpreter::privateExecute(ExecutionFlag flag, RegisterFile* registe
register dst.
*/
int dst = (++vPC)->u.operand;
- JSValuePtr src1 = callFrame[(++vPC)->u.operand].jsValue(callFrame);
- JSValuePtr src2 = callFrame[(++vPC)->u.operand].jsValue(callFrame);
+ JSValue src1 = callFrame[(++vPC)->u.operand].jsValue();
+ JSValue src2 = callFrame[(++vPC)->u.operand].jsValue();
double left;
double right;
if (JSFastMath::canDoFastAdditiveOperations(src1, src2))
- callFrame[dst] = JSValuePtr(JSFastMath::subImmediateNumbers(src1, src2));
+ callFrame[dst] = JSValue(JSFastMath::subImmediateNumbers(src1, src2));
else if (src1.getNumber(left) && src2.getNumber(right))
- callFrame[dst] = JSValuePtr(jsNumber(callFrame, left - right));
+ callFrame[dst] = JSValue(jsNumber(callFrame, left - right));
else {
- JSValuePtr result = jsNumber(callFrame, src1.toNumber(callFrame) - src2.toNumber(callFrame));
+ JSValue result = jsNumber(callFrame, src1.toNumber(callFrame) - src2.toNumber(callFrame));
CHECK_FOR_EXCEPTION();
callFrame[dst] = result;
}
@@ -1563,16 +1637,16 @@ JSValuePtr Interpreter::privateExecute(ExecutionFlag flag, RegisterFile* registe
in register dst.
*/
int dst = (++vPC)->u.operand;
- JSValuePtr val = callFrame[(++vPC)->u.operand].jsValue(callFrame);
- JSValuePtr shift = callFrame[(++vPC)->u.operand].jsValue(callFrame);
+ JSValue val = callFrame[(++vPC)->u.operand].jsValue();
+ JSValue shift = callFrame[(++vPC)->u.operand].jsValue();
int32_t left;
uint32_t right;
- if (JSValuePtr::areBothInt32Fast(val, shift))
- callFrame[dst] = JSValuePtr(jsNumber(callFrame, val.getInt32Fast() << (shift.getInt32Fast() & 0x1f)));
+ if (JSValue::areBothInt32Fast(val, shift))
+ callFrame[dst] = JSValue(jsNumber(callFrame, val.getInt32Fast() << (shift.getInt32Fast() & 0x1f)));
else if (val.numberToInt32(left) && shift.numberToUInt32(right))
- callFrame[dst] = JSValuePtr(jsNumber(callFrame, left << (right & 0x1f)));
+ callFrame[dst] = JSValue(jsNumber(callFrame, left << (right & 0x1f)));
else {
- JSValuePtr result = jsNumber(callFrame, (val.toInt32(callFrame)) << (shift.toUInt32(callFrame) & 0x1f));
+ JSValue result = jsNumber(callFrame, (val.toInt32(callFrame)) << (shift.toUInt32(callFrame) & 0x1f));
CHECK_FOR_EXCEPTION();
callFrame[dst] = result;
}
@@ -1588,16 +1662,16 @@ JSValuePtr Interpreter::privateExecute(ExecutionFlag flag, RegisterFile* registe
uint32), and puts the result in register dst.
*/
int dst = (++vPC)->u.operand;
- JSValuePtr val = callFrame[(++vPC)->u.operand].jsValue(callFrame);
- JSValuePtr shift = callFrame[(++vPC)->u.operand].jsValue(callFrame);
+ JSValue val = callFrame[(++vPC)->u.operand].jsValue();
+ JSValue shift = callFrame[(++vPC)->u.operand].jsValue();
int32_t left;
uint32_t right;
if (JSFastMath::canDoFastRshift(val, shift))
- callFrame[dst] = JSValuePtr(JSFastMath::rightShiftImmediateNumbers(val, shift));
+ callFrame[dst] = JSValue(JSFastMath::rightShiftImmediateNumbers(val, shift));
else if (val.numberToInt32(left) && shift.numberToUInt32(right))
- callFrame[dst] = JSValuePtr(jsNumber(callFrame, left >> (right & 0x1f)));
+ callFrame[dst] = JSValue(jsNumber(callFrame, left >> (right & 0x1f)));
else {
- JSValuePtr result = jsNumber(callFrame, (val.toInt32(callFrame)) >> (shift.toUInt32(callFrame) & 0x1f));
+ JSValue result = jsNumber(callFrame, (val.toInt32(callFrame)) >> (shift.toUInt32(callFrame) & 0x1f));
CHECK_FOR_EXCEPTION();
callFrame[dst] = result;
}
@@ -1613,12 +1687,12 @@ JSValuePtr Interpreter::privateExecute(ExecutionFlag flag, RegisterFile* registe
uint32), and puts the result in register dst.
*/
int dst = (++vPC)->u.operand;
- JSValuePtr val = callFrame[(++vPC)->u.operand].jsValue(callFrame);
- JSValuePtr shift = callFrame[(++vPC)->u.operand].jsValue(callFrame);
+ JSValue val = callFrame[(++vPC)->u.operand].jsValue();
+ JSValue shift = callFrame[(++vPC)->u.operand].jsValue();
if (JSFastMath::canDoFastUrshift(val, shift))
- callFrame[dst] = JSValuePtr(JSFastMath::rightShiftImmediateNumbers(val, shift));
+ callFrame[dst] = JSValue(JSFastMath::rightShiftImmediateNumbers(val, shift));
else {
- JSValuePtr result = jsNumber(callFrame, (val.toUInt32(callFrame)) >> (shift.toUInt32(callFrame) & 0x1f));
+ JSValue result = jsNumber(callFrame, (val.toUInt32(callFrame)) >> (shift.toUInt32(callFrame) & 0x1f));
CHECK_FOR_EXCEPTION();
callFrame[dst] = result;
}
@@ -1634,16 +1708,16 @@ JSValuePtr Interpreter::privateExecute(ExecutionFlag flag, RegisterFile* registe
in register dst.
*/
int dst = (++vPC)->u.operand;
- JSValuePtr src1 = callFrame[(++vPC)->u.operand].jsValue(callFrame);
- JSValuePtr src2 = callFrame[(++vPC)->u.operand].jsValue(callFrame);
+ JSValue src1 = callFrame[(++vPC)->u.operand].jsValue();
+ JSValue src2 = callFrame[(++vPC)->u.operand].jsValue();
int32_t left;
int32_t right;
if (JSFastMath::canDoFastBitwiseOperations(src1, src2))
- callFrame[dst] = JSValuePtr(JSFastMath::andImmediateNumbers(src1, src2));
+ callFrame[dst] = JSValue(JSFastMath::andImmediateNumbers(src1, src2));
else if (src1.numberToInt32(left) && src2.numberToInt32(right))
- callFrame[dst] = JSValuePtr(jsNumber(callFrame, left & right));
+ callFrame[dst] = JSValue(jsNumber(callFrame, left & right));
else {
- JSValuePtr result = jsNumber(callFrame, src1.toInt32(callFrame) & src2.toInt32(callFrame));
+ JSValue result = jsNumber(callFrame, src1.toInt32(callFrame) & src2.toInt32(callFrame));
CHECK_FOR_EXCEPTION();
callFrame[dst] = result;
}
@@ -1659,16 +1733,16 @@ JSValuePtr Interpreter::privateExecute(ExecutionFlag flag, RegisterFile* registe
in register dst.
*/
int dst = (++vPC)->u.operand;
- JSValuePtr src1 = callFrame[(++vPC)->u.operand].jsValue(callFrame);
- JSValuePtr src2 = callFrame[(++vPC)->u.operand].jsValue(callFrame);
+ JSValue src1 = callFrame[(++vPC)->u.operand].jsValue();
+ JSValue src2 = callFrame[(++vPC)->u.operand].jsValue();
int32_t left;
int32_t right;
if (JSFastMath::canDoFastBitwiseOperations(src1, src2))
- callFrame[dst] = JSValuePtr(JSFastMath::xorImmediateNumbers(src1, src2));
+ callFrame[dst] = JSValue(JSFastMath::xorImmediateNumbers(src1, src2));
else if (src1.numberToInt32(left) && src2.numberToInt32(right))
- callFrame[dst] = JSValuePtr(jsNumber(callFrame, left ^ right));
+ callFrame[dst] = JSValue(jsNumber(callFrame, left ^ right));
else {
- JSValuePtr result = jsNumber(callFrame, src1.toInt32(callFrame) ^ src2.toInt32(callFrame));
+ JSValue result = jsNumber(callFrame, src1.toInt32(callFrame) ^ src2.toInt32(callFrame));
CHECK_FOR_EXCEPTION();
callFrame[dst] = result;
}
@@ -1684,16 +1758,16 @@ JSValuePtr Interpreter::privateExecute(ExecutionFlag flag, RegisterFile* registe
result in register dst.
*/
int dst = (++vPC)->u.operand;
- JSValuePtr src1 = callFrame[(++vPC)->u.operand].jsValue(callFrame);
- JSValuePtr src2 = callFrame[(++vPC)->u.operand].jsValue(callFrame);
+ JSValue src1 = callFrame[(++vPC)->u.operand].jsValue();
+ JSValue src2 = callFrame[(++vPC)->u.operand].jsValue();
int32_t left;
int32_t right;
if (JSFastMath::canDoFastBitwiseOperations(src1, src2))
- callFrame[dst] = JSValuePtr(JSFastMath::orImmediateNumbers(src1, src2));
+ callFrame[dst] = JSValue(JSFastMath::orImmediateNumbers(src1, src2));
else if (src1.numberToInt32(left) && src2.numberToInt32(right))
- callFrame[dst] = JSValuePtr(jsNumber(callFrame, left | right));
+ callFrame[dst] = JSValue(jsNumber(callFrame, left | right));
else {
- JSValuePtr result = jsNumber(callFrame, src1.toInt32(callFrame) | src2.toInt32(callFrame));
+ JSValue result = jsNumber(callFrame, src1.toInt32(callFrame) | src2.toInt32(callFrame));
CHECK_FOR_EXCEPTION();
callFrame[dst] = result;
}
@@ -1708,12 +1782,12 @@ JSValuePtr Interpreter::privateExecute(ExecutionFlag flag, RegisterFile* registe
and puts the result in register dst.
*/
int dst = (++vPC)->u.operand;
- JSValuePtr src = callFrame[(++vPC)->u.operand].jsValue(callFrame);
+ JSValue src = callFrame[(++vPC)->u.operand].jsValue();
int32_t value;
if (src.numberToInt32(value))
- callFrame[dst] = JSValuePtr(jsNumber(callFrame, ~value));
+ callFrame[dst] = JSValue(jsNumber(callFrame, ~value));
else {
- JSValuePtr result = jsNumber(callFrame, ~src.toInt32(callFrame));
+ JSValue result = jsNumber(callFrame, ~src.toInt32(callFrame));
CHECK_FOR_EXCEPTION();
callFrame[dst] = result;
}
@@ -1728,7 +1802,7 @@ JSValuePtr Interpreter::privateExecute(ExecutionFlag flag, RegisterFile* registe
*/
int dst = (++vPC)->u.operand;
int src = (++vPC)->u.operand;
- JSValuePtr result = jsBoolean(!callFrame[src].jsValue(callFrame).toBoolean(callFrame));
+ JSValue result = jsBoolean(!callFrame[src].jsValue().toBoolean(callFrame));
CHECK_FOR_EXCEPTION();
callFrame[dst] = result;
@@ -1753,18 +1827,14 @@ JSValuePtr Interpreter::privateExecute(ExecutionFlag flag, RegisterFile* registe
int base = vPC[3].u.operand;
int baseProto = vPC[4].u.operand;
- JSValuePtr baseVal = callFrame[base].jsValue(callFrame);
+ JSValue baseVal = callFrame[base].jsValue();
- if (isNotObject(callFrame, true, callFrame->codeBlock(), vPC, baseVal, exceptionValue))
+ if (isInvalidParamForInstanceOf(callFrame, callFrame->codeBlock(), vPC, baseVal, exceptionValue))
goto vm_throw;
- JSObject* baseObj = asObject(baseVal);
- if (baseObj->structure()->typeInfo().implementsHasInstance()) {
- bool result = baseObj->hasInstance(callFrame, callFrame[value].jsValue(callFrame), callFrame[baseProto].jsValue(callFrame));
- CHECK_FOR_EXCEPTION();
- callFrame[dst] = jsBoolean(result);
- } else
- callFrame[dst] = jsBoolean(false);
+ bool result = asObject(baseVal)->hasInstance(callFrame, callFrame[value].jsValue(), callFrame[baseProto].jsValue());
+ CHECK_FOR_EXCEPTION();
+ callFrame[dst] = jsBoolean(result);
vPC += 5;
NEXT_INSTRUCTION();
@@ -1777,7 +1847,7 @@ JSValuePtr Interpreter::privateExecute(ExecutionFlag flag, RegisterFile* registe
*/
int dst = (++vPC)->u.operand;
int src = (++vPC)->u.operand;
- callFrame[dst] = JSValuePtr(jsTypeStringForValue(callFrame, callFrame[src].jsValue(callFrame)));
+ callFrame[dst] = JSValue(jsTypeStringForValue(callFrame, callFrame[src].jsValue()));
++vPC;
NEXT_INSTRUCTION();
@@ -1791,7 +1861,7 @@ JSValuePtr Interpreter::privateExecute(ExecutionFlag flag, RegisterFile* registe
*/
int dst = (++vPC)->u.operand;
int src = (++vPC)->u.operand;
- JSValuePtr v = callFrame[src].jsValue(callFrame);
+ JSValue v = callFrame[src].jsValue();
callFrame[dst] = jsBoolean(v.isCell() ? v.asCell()->structure()->typeInfo().masqueradesAsUndefined() : v.isUndefined());
++vPC;
@@ -1806,7 +1876,7 @@ JSValuePtr Interpreter::privateExecute(ExecutionFlag flag, RegisterFile* registe
*/
int dst = (++vPC)->u.operand;
int src = (++vPC)->u.operand;
- callFrame[dst] = jsBoolean(callFrame[src].jsValue(callFrame).isBoolean());
+ callFrame[dst] = jsBoolean(callFrame[src].jsValue().isBoolean());
++vPC;
NEXT_INSTRUCTION();
@@ -1820,7 +1890,7 @@ JSValuePtr Interpreter::privateExecute(ExecutionFlag flag, RegisterFile* registe
*/
int dst = (++vPC)->u.operand;
int src = (++vPC)->u.operand;
- callFrame[dst] = jsBoolean(callFrame[src].jsValue(callFrame).isNumber());
+ callFrame[dst] = jsBoolean(callFrame[src].jsValue().isNumber());
++vPC;
NEXT_INSTRUCTION();
@@ -1834,7 +1904,7 @@ JSValuePtr Interpreter::privateExecute(ExecutionFlag flag, RegisterFile* registe
*/
int dst = (++vPC)->u.operand;
int src = (++vPC)->u.operand;
- callFrame[dst] = jsBoolean(callFrame[src].jsValue(callFrame).isString());
+ callFrame[dst] = jsBoolean(callFrame[src].jsValue().isString());
++vPC;
NEXT_INSTRUCTION();
@@ -1848,7 +1918,7 @@ JSValuePtr Interpreter::privateExecute(ExecutionFlag flag, RegisterFile* registe
*/
int dst = (++vPC)->u.operand;
int src = (++vPC)->u.operand;
- callFrame[dst] = jsBoolean(jsIsObjectType(callFrame[src].jsValue(callFrame)));
+ callFrame[dst] = jsBoolean(jsIsObjectType(callFrame[src].jsValue()));
++vPC;
NEXT_INSTRUCTION();
@@ -1862,7 +1932,7 @@ JSValuePtr Interpreter::privateExecute(ExecutionFlag flag, RegisterFile* registe
*/
int dst = (++vPC)->u.operand;
int src = (++vPC)->u.operand;
- callFrame[dst] = jsBoolean(jsIsFunctionType(callFrame[src].jsValue(callFrame)));
+ callFrame[dst] = jsBoolean(jsIsFunctionType(callFrame[src].jsValue()));
++vPC;
NEXT_INSTRUCTION();
@@ -1880,13 +1950,13 @@ JSValuePtr Interpreter::privateExecute(ExecutionFlag flag, RegisterFile* registe
int property = (++vPC)->u.operand;
int base = (++vPC)->u.operand;
- JSValuePtr baseVal = callFrame[base].jsValue(callFrame);
- if (isNotObject(callFrame, false, callFrame->codeBlock(), vPC, baseVal, exceptionValue))
+ JSValue baseVal = callFrame[base].jsValue();
+ if (isInvalidParamForIn(callFrame, callFrame->codeBlock(), vPC, baseVal, exceptionValue))
goto vm_throw;
JSObject* baseObj = asObject(baseVal);
- JSValuePtr propName = callFrame[property].jsValue(callFrame);
+ JSValue propName = callFrame[property].jsValue();
uint32_t i;
if (propName.getUInt32(i))
@@ -1966,7 +2036,7 @@ JSValuePtr Interpreter::privateExecute(ExecutionFlag flag, RegisterFile* registe
int index = (++vPC)->u.operand;
int value = (++vPC)->u.operand;
- scope->registerAt(index) = JSValuePtr(callFrame[value].jsValue(callFrame));
+ scope->registerAt(index) = JSValue(callFrame[value].jsValue());
++vPC;
NEXT_INSTRUCTION();
}
@@ -2014,7 +2084,7 @@ JSValuePtr Interpreter::privateExecute(ExecutionFlag flag, RegisterFile* registe
ASSERT((*iter)->isVariableObject());
JSVariableObject* scope = static_cast<JSVariableObject*>(*iter);
- scope->registerAt(index) = JSValuePtr(callFrame[value].jsValue(callFrame));
+ scope->registerAt(index) = JSValue(callFrame[value].jsValue());
++vPC;
NEXT_INSTRUCTION();
}
@@ -2082,9 +2152,9 @@ JSValuePtr Interpreter::privateExecute(ExecutionFlag flag, RegisterFile* registe
CodeBlock* codeBlock = callFrame->codeBlock();
Identifier& ident = codeBlock->identifier(property);
- JSValuePtr baseValue = callFrame[base].jsValue(callFrame);
+ JSValue baseValue = callFrame[base].jsValue();
PropertySlot slot(baseValue);
- JSValuePtr result = baseValue.get(callFrame, ident, slot);
+ JSValue result = baseValue.get(callFrame, ident, slot);
CHECK_FOR_EXCEPTION();
tryCacheGetByID(callFrame, codeBlock, vPC, baseValue, ident, slot);
@@ -2101,7 +2171,7 @@ JSValuePtr Interpreter::privateExecute(ExecutionFlag flag, RegisterFile* registe
op_get_by_id.
*/
int base = vPC[2].u.operand;
- JSValuePtr baseValue = callFrame[base].jsValue(callFrame);
+ JSValue baseValue = callFrame[base].jsValue();
if (LIKELY(baseValue.isCell())) {
JSCell* baseCell = asCell(baseValue);
@@ -2114,7 +2184,7 @@ JSValuePtr Interpreter::privateExecute(ExecutionFlag flag, RegisterFile* registe
int offset = vPC[5].u.operand;
ASSERT(baseObject->get(callFrame, callFrame->codeBlock()->identifier(vPC[3].u.operand)) == baseObject->getDirectOffset(offset));
- callFrame[dst] = JSValuePtr(baseObject->getDirectOffset(offset));
+ callFrame[dst] = JSValue(baseObject->getDirectOffset(offset));
vPC += 8;
NEXT_INSTRUCTION();
@@ -2132,7 +2202,7 @@ JSValuePtr Interpreter::privateExecute(ExecutionFlag flag, RegisterFile* registe
reverts to op_get_by_id.
*/
int base = vPC[2].u.operand;
- JSValuePtr baseValue = callFrame[base].jsValue(callFrame);
+ JSValue baseValue = callFrame[base].jsValue();
if (LIKELY(baseValue.isCell())) {
JSCell* baseCell = asCell(baseValue);
@@ -2148,7 +2218,7 @@ JSValuePtr Interpreter::privateExecute(ExecutionFlag flag, RegisterFile* registe
int offset = vPC[6].u.operand;
ASSERT(protoObject->get(callFrame, callFrame->codeBlock()->identifier(vPC[3].u.operand)) == protoObject->getDirectOffset(offset));
- callFrame[dst] = JSValuePtr(protoObject->getDirectOffset(offset));
+ callFrame[dst] = JSValue(protoObject->getDirectOffset(offset));
vPC += 8;
NEXT_INSTRUCTION();
@@ -2181,7 +2251,7 @@ JSValuePtr Interpreter::privateExecute(ExecutionFlag flag, RegisterFile* registe
reverts to op_get_by_id.
*/
int base = vPC[2].u.operand;
- JSValuePtr baseValue = callFrame[base].jsValue(callFrame);
+ JSValue baseValue = callFrame[base].jsValue();
if (LIKELY(baseValue.isCell())) {
JSCell* baseCell = asCell(baseValue);
@@ -2203,7 +2273,7 @@ JSValuePtr Interpreter::privateExecute(ExecutionFlag flag, RegisterFile* registe
int offset = vPC[7].u.operand;
ASSERT(baseObject->get(callFrame, callFrame->codeBlock()->identifier(vPC[3].u.operand)) == baseObject->getDirectOffset(offset));
- callFrame[dst] = JSValuePtr(baseObject->getDirectOffset(offset));
+ callFrame[dst] = JSValue(baseObject->getDirectOffset(offset));
vPC += 8;
NEXT_INSTRUCTION();
@@ -2229,9 +2299,9 @@ JSValuePtr Interpreter::privateExecute(ExecutionFlag flag, RegisterFile* registe
int property = vPC[3].u.operand;
Identifier& ident = callFrame->codeBlock()->identifier(property);
- JSValuePtr baseValue = callFrame[base].jsValue(callFrame);
+ JSValue baseValue = callFrame[base].jsValue();
PropertySlot slot(baseValue);
- JSValuePtr result = baseValue.get(callFrame, ident, slot);
+ JSValue result = baseValue.get(callFrame, ident, slot);
CHECK_FOR_EXCEPTION();
callFrame[dst] = result;
@@ -2247,10 +2317,10 @@ JSValuePtr Interpreter::privateExecute(ExecutionFlag flag, RegisterFile* registe
*/
int base = vPC[2].u.operand;
- JSValuePtr baseValue = callFrame[base].jsValue(callFrame);
+ JSValue baseValue = callFrame[base].jsValue();
if (LIKELY(isJSArray(globalData, baseValue))) {
int dst = vPC[1].u.operand;
- callFrame[dst] = JSValuePtr(jsNumber(callFrame, asArray(baseValue)->length()));
+ callFrame[dst] = JSValue(jsNumber(callFrame, asArray(baseValue)->length()));
vPC += 8;
NEXT_INSTRUCTION();
}
@@ -2267,10 +2337,10 @@ JSValuePtr Interpreter::privateExecute(ExecutionFlag flag, RegisterFile* registe
*/
int base = vPC[2].u.operand;
- JSValuePtr baseValue = callFrame[base].jsValue(callFrame);
+ JSValue baseValue = callFrame[base].jsValue();
if (LIKELY(isJSString(globalData, baseValue))) {
int dst = vPC[1].u.operand;
- callFrame[dst] = JSValuePtr(jsNumber(callFrame, asString(baseValue)->value().size()));
+ callFrame[dst] = JSValue(jsNumber(callFrame, asString(baseValue)->value().size()));
vPC += 8;
NEXT_INSTRUCTION();
}
@@ -2293,10 +2363,10 @@ JSValuePtr Interpreter::privateExecute(ExecutionFlag flag, RegisterFile* registe
int value = vPC[3].u.operand;
CodeBlock* codeBlock = callFrame->codeBlock();
- JSValuePtr baseValue = callFrame[base].jsValue(callFrame);
+ JSValue baseValue = callFrame[base].jsValue();
Identifier& ident = codeBlock->identifier(property);
PutPropertySlot slot;
- baseValue.put(callFrame, ident, callFrame[value].jsValue(callFrame), slot);
+ baseValue.put(callFrame, ident, callFrame[value].jsValue(), slot);
CHECK_FOR_EXCEPTION();
tryCachePutByID(callFrame, codeBlock, vPC, baseValue, slot);
@@ -2316,7 +2386,7 @@ JSValuePtr Interpreter::privateExecute(ExecutionFlag flag, RegisterFile* registe
the register file.
*/
int base = vPC[1].u.operand;
- JSValuePtr baseValue = callFrame[base].jsValue(callFrame);
+ JSValue baseValue = callFrame[base].jsValue();
if (LIKELY(baseValue.isCell())) {
JSCell* baseCell = asCell(baseValue);
@@ -2329,7 +2399,7 @@ JSValuePtr Interpreter::privateExecute(ExecutionFlag flag, RegisterFile* registe
RefPtr<Structure>* it = vPC[6].u.structureChain->head();
- JSValuePtr proto = baseObject->structure()->prototypeForLookup(callFrame);
+ JSValue proto = baseObject->structure()->prototypeForLookup(callFrame);
while (!proto.isNull()) {
if (UNLIKELY(asObject(proto)->structure() != (*it).get())) {
uncachePutByID(callFrame->codeBlock(), vPC);
@@ -2344,7 +2414,7 @@ JSValuePtr Interpreter::privateExecute(ExecutionFlag flag, RegisterFile* registe
int value = vPC[3].u.operand;
unsigned offset = vPC[7].u.operand;
ASSERT(baseObject->offsetForLocation(baseObject->getDirectLocation(callFrame->codeBlock()->identifier(vPC[2].u.operand))) == offset);
- baseObject->putDirectOffset(offset, callFrame[value].jsValue(callFrame));
+ baseObject->putDirectOffset(offset, callFrame[value].jsValue());
vPC += 8;
NEXT_INSTRUCTION();
@@ -2366,7 +2436,7 @@ JSValuePtr Interpreter::privateExecute(ExecutionFlag flag, RegisterFile* registe
the register file.
*/
int base = vPC[1].u.operand;
- JSValuePtr baseValue = callFrame[base].jsValue(callFrame);
+ JSValue baseValue = callFrame[base].jsValue();
if (LIKELY(baseValue.isCell())) {
JSCell* baseCell = asCell(baseValue);
@@ -2379,7 +2449,7 @@ JSValuePtr Interpreter::privateExecute(ExecutionFlag flag, RegisterFile* registe
unsigned offset = vPC[5].u.operand;
ASSERT(baseObject->offsetForLocation(baseObject->getDirectLocation(callFrame->codeBlock()->identifier(vPC[2].u.operand))) == offset);
- baseObject->putDirectOffset(offset, callFrame[value].jsValue(callFrame));
+ baseObject->putDirectOffset(offset, callFrame[value].jsValue());
vPC += 8;
NEXT_INSTRUCTION();
@@ -2402,10 +2472,10 @@ JSValuePtr Interpreter::privateExecute(ExecutionFlag flag, RegisterFile* registe
int property = vPC[2].u.operand;
int value = vPC[3].u.operand;
- JSValuePtr baseValue = callFrame[base].jsValue(callFrame);
+ JSValue baseValue = callFrame[base].jsValue();
Identifier& ident = callFrame->codeBlock()->identifier(property);
PutPropertySlot slot;
- baseValue.put(callFrame, ident, callFrame[value].jsValue(callFrame), slot);
+ baseValue.put(callFrame, ident, callFrame[value].jsValue(), slot);
CHECK_FOR_EXCEPTION();
vPC += 8;
@@ -2423,9 +2493,9 @@ JSValuePtr Interpreter::privateExecute(ExecutionFlag flag, RegisterFile* registe
int base = (++vPC)->u.operand;
int property = (++vPC)->u.operand;
- JSObject* baseObj = callFrame[base].jsValue(callFrame).toObject(callFrame);
+ JSObject* baseObj = callFrame[base].jsValue().toObject(callFrame);
Identifier& ident = callFrame->codeBlock()->identifier(property);
- JSValuePtr result = jsBoolean(baseObj->deleteProperty(callFrame, ident));
+ JSValue result = jsBoolean(baseObj->deleteProperty(callFrame, ident));
CHECK_FOR_EXCEPTION();
callFrame[dst] = result;
++vPC;
@@ -2443,10 +2513,10 @@ JSValuePtr Interpreter::privateExecute(ExecutionFlag flag, RegisterFile* registe
int base = (++vPC)->u.operand;
int property = (++vPC)->u.operand;
- JSValuePtr baseValue = callFrame[base].jsValue(callFrame);
- JSValuePtr subscript = callFrame[property].jsValue(callFrame);
+ JSValue baseValue = callFrame[base].jsValue();
+ JSValue subscript = callFrame[property].jsValue();
- JSValuePtr result;
+ JSValue result;
if (LIKELY(subscript.isUInt32Fast())) {
uint32_t i = subscript.getUInt32Fast();
@@ -2487,21 +2557,21 @@ JSValuePtr Interpreter::privateExecute(ExecutionFlag flag, RegisterFile* registe
int property = (++vPC)->u.operand;
int value = (++vPC)->u.operand;
- JSValuePtr baseValue = callFrame[base].jsValue(callFrame);
- JSValuePtr subscript = callFrame[property].jsValue(callFrame);
+ JSValue baseValue = callFrame[base].jsValue();
+ JSValue subscript = callFrame[property].jsValue();
if (LIKELY(subscript.isUInt32Fast())) {
uint32_t i = subscript.getUInt32Fast();
if (isJSArray(globalData, baseValue)) {
JSArray* jsArray = asArray(baseValue);
if (jsArray->canSetIndex(i))
- jsArray->setIndex(i, callFrame[value].jsValue(callFrame));
+ jsArray->setIndex(i, callFrame[value].jsValue());
else
- jsArray->JSArray::put(callFrame, i, callFrame[value].jsValue(callFrame));
+ jsArray->JSArray::put(callFrame, i, callFrame[value].jsValue());
} else if (isJSByteArray(globalData, baseValue) && asByteArray(baseValue)->canAccessIndex(i)) {
JSByteArray* jsByteArray = asByteArray(baseValue);
double dValue = 0;
- JSValuePtr jsValue = callFrame[value].jsValue(callFrame);
+ JSValue jsValue = callFrame[value].jsValue();
if (jsValue.isInt32Fast())
jsByteArray->setIndex(i, jsValue.getInt32Fast());
else if (jsValue.getNumber(dValue))
@@ -2509,12 +2579,12 @@ JSValuePtr Interpreter::privateExecute(ExecutionFlag flag, RegisterFile* registe
else
baseValue.put(callFrame, i, jsValue);
} else
- baseValue.put(callFrame, i, callFrame[value].jsValue(callFrame));
+ baseValue.put(callFrame, i, callFrame[value].jsValue());
} else {
Identifier property(callFrame, subscript.toString(callFrame));
if (!globalData->exception) { // Don't put to an object if toString threw an exception.
PutPropertySlot slot;
- baseValue.put(callFrame, property, callFrame[value].jsValue(callFrame), slot);
+ baseValue.put(callFrame, property, callFrame[value].jsValue(), slot);
}
}
@@ -2534,10 +2604,10 @@ JSValuePtr Interpreter::privateExecute(ExecutionFlag flag, RegisterFile* registe
int base = (++vPC)->u.operand;
int property = (++vPC)->u.operand;
- JSObject* baseObj = callFrame[base].jsValue(callFrame).toObject(callFrame); // may throw
+ JSObject* baseObj = callFrame[base].jsValue().toObject(callFrame); // may throw
- JSValuePtr subscript = callFrame[property].jsValue(callFrame);
- JSValuePtr result;
+ JSValue subscript = callFrame[property].jsValue();
+ JSValue result;
uint32_t i;
if (subscript.getUInt32(i))
result = jsBoolean(baseObj->deleteProperty(callFrame, i));
@@ -2569,7 +2639,7 @@ JSValuePtr Interpreter::privateExecute(ExecutionFlag flag, RegisterFile* registe
unsigned property = (++vPC)->u.operand;
int value = (++vPC)->u.operand;
- callFrame[base].jsValue(callFrame).put(callFrame, property, callFrame[value].jsValue(callFrame));
+ callFrame[base].jsValue().put(callFrame, property, callFrame[value].jsValue());
++vPC;
NEXT_INSTRUCTION();
@@ -2616,7 +2686,7 @@ JSValuePtr Interpreter::privateExecute(ExecutionFlag flag, RegisterFile* registe
*/
int cond = (++vPC)->u.operand;
int target = (++vPC)->u.operand;
- if (callFrame[cond].jsValue(callFrame).toBoolean(callFrame)) {
+ if (callFrame[cond].jsValue().toBoolean(callFrame)) {
vPC += target;
CHECK_FOR_TIMEOUT();
NEXT_INSTRUCTION();
@@ -2633,7 +2703,7 @@ JSValuePtr Interpreter::privateExecute(ExecutionFlag flag, RegisterFile* registe
*/
int cond = (++vPC)->u.operand;
int target = (++vPC)->u.operand;
- if (callFrame[cond].jsValue(callFrame).toBoolean(callFrame)) {
+ if (callFrame[cond].jsValue().toBoolean(callFrame)) {
vPC += target;
NEXT_INSTRUCTION();
}
@@ -2649,7 +2719,7 @@ JSValuePtr Interpreter::privateExecute(ExecutionFlag flag, RegisterFile* registe
*/
int cond = (++vPC)->u.operand;
int target = (++vPC)->u.operand;
- if (!callFrame[cond].jsValue(callFrame).toBoolean(callFrame)) {
+ if (!callFrame[cond].jsValue().toBoolean(callFrame)) {
vPC += target;
NEXT_INSTRUCTION();
}
@@ -2665,7 +2735,7 @@ JSValuePtr Interpreter::privateExecute(ExecutionFlag flag, RegisterFile* registe
*/
int src = (++vPC)->u.operand;
int target = (++vPC)->u.operand;
- JSValuePtr srcValue = callFrame[src].jsValue(callFrame);
+ JSValue srcValue = callFrame[src].jsValue();
if (srcValue.isUndefinedOrNull() || (srcValue.isCell() && srcValue.asCell()->structure()->typeInfo().masqueradesAsUndefined())) {
vPC += target;
@@ -2683,7 +2753,7 @@ JSValuePtr Interpreter::privateExecute(ExecutionFlag flag, RegisterFile* registe
*/
int src = (++vPC)->u.operand;
int target = (++vPC)->u.operand;
- JSValuePtr srcValue = callFrame[src].jsValue(callFrame);
+ JSValue srcValue = callFrame[src].jsValue();
if (!srcValue.isUndefinedOrNull() || (srcValue.isCell() && !srcValue.asCell()->structure()->typeInfo().masqueradesAsUndefined())) {
vPC += target;
@@ -2693,6 +2763,24 @@ JSValuePtr Interpreter::privateExecute(ExecutionFlag flag, RegisterFile* registe
++vPC;
NEXT_INSTRUCTION();
}
+ DEFINE_OPCODE(op_jneq_ptr) {
+ /* jneq_ptr src(r) ptr(jsCell) target(offset)
+
+ Jumps to offset target from the current instruction, if the value r is equal
+ to ptr, using pointer equality.
+ */
+ int src = (++vPC)->u.operand;
+ JSValue ptr = JSValue((++vPC)->u.jsCell);
+ int target = (++vPC)->u.operand;
+ JSValue srcValue = callFrame[src].jsValue();
+ if (srcValue != ptr) {
+ vPC += target;
+ NEXT_INSTRUCTION();
+ }
+
+ ++vPC;
+ NEXT_INSTRUCTION();
+ }
DEFINE_OPCODE(op_loop_if_less) {
/* loop_if_less src1(r) src2(r) target(offset)
@@ -2704,8 +2792,8 @@ JSValuePtr Interpreter::privateExecute(ExecutionFlag flag, RegisterFile* registe
Additionally this loop instruction may terminate JS execution is
the JS timeout is reached.
*/
- JSValuePtr src1 = callFrame[(++vPC)->u.operand].jsValue(callFrame);
- JSValuePtr src2 = callFrame[(++vPC)->u.operand].jsValue(callFrame);
+ JSValue src1 = callFrame[(++vPC)->u.operand].jsValue();
+ JSValue src2 = callFrame[(++vPC)->u.operand].jsValue();
int target = (++vPC)->u.operand;
bool result = jsLess(callFrame, src1, src2);
@@ -2731,8 +2819,8 @@ JSValuePtr Interpreter::privateExecute(ExecutionFlag flag, RegisterFile* registe
Additionally this loop instruction may terminate JS execution is
the JS timeout is reached.
*/
- JSValuePtr src1 = callFrame[(++vPC)->u.operand].jsValue(callFrame);
- JSValuePtr src2 = callFrame[(++vPC)->u.operand].jsValue(callFrame);
+ JSValue src1 = callFrame[(++vPC)->u.operand].jsValue();
+ JSValue src2 = callFrame[(++vPC)->u.operand].jsValue();
int target = (++vPC)->u.operand;
bool result = jsLessEq(callFrame, src1, src2);
@@ -2755,8 +2843,8 @@ JSValuePtr Interpreter::privateExecute(ExecutionFlag flag, RegisterFile* registe
target from the current instruction, if and only if the
result of the comparison is false.
*/
- JSValuePtr src1 = callFrame[(++vPC)->u.operand].jsValue(callFrame);
- JSValuePtr src2 = callFrame[(++vPC)->u.operand].jsValue(callFrame);
+ JSValue src1 = callFrame[(++vPC)->u.operand].jsValue();
+ JSValue src2 = callFrame[(++vPC)->u.operand].jsValue();
int target = (++vPC)->u.operand;
bool result = jsLess(callFrame, src1, src2);
@@ -2770,6 +2858,29 @@ JSValuePtr Interpreter::privateExecute(ExecutionFlag flag, RegisterFile* registe
++vPC;
NEXT_INSTRUCTION();
}
+ DEFINE_OPCODE(op_jnlesseq) {
+ /* jnlesseq src1(r) src2(r) target(offset)
+
+ Checks whether register src1 is less than or equal to
+ register src2, as with the ECMAScript '<=' operator,
+ and then jumps to offset target from the current instruction,
+ if and only if theresult of the comparison is false.
+ */
+ JSValue src1 = callFrame[(++vPC)->u.operand].jsValue();
+ JSValue src2 = callFrame[(++vPC)->u.operand].jsValue();
+ int target = (++vPC)->u.operand;
+
+ bool result = jsLessEq(callFrame, src1, src2);
+ CHECK_FOR_EXCEPTION();
+
+ if (!result) {
+ vPC += target;
+ NEXT_INSTRUCTION();
+ }
+
+ ++vPC;
+ NEXT_INSTRUCTION();
+ }
DEFINE_OPCODE(op_switch_imm) {
/* switch_imm tableIndex(n) defaultOffset(offset) scrutinee(r)
@@ -2781,7 +2892,7 @@ JSValuePtr Interpreter::privateExecute(ExecutionFlag flag, RegisterFile* registe
*/
int tableIndex = (++vPC)->u.operand;
int defaultOffset = (++vPC)->u.operand;
- JSValuePtr scrutinee = callFrame[(++vPC)->u.operand].jsValue(callFrame);
+ JSValue scrutinee = callFrame[(++vPC)->u.operand].jsValue();
if (scrutinee.isInt32Fast())
vPC += callFrame->codeBlock()->immediateSwitchJumpTable(tableIndex).offsetForValue(scrutinee.getInt32Fast(), defaultOffset);
else {
@@ -2805,7 +2916,7 @@ JSValuePtr Interpreter::privateExecute(ExecutionFlag flag, RegisterFile* registe
*/
int tableIndex = (++vPC)->u.operand;
int defaultOffset = (++vPC)->u.operand;
- JSValuePtr scrutinee = callFrame[(++vPC)->u.operand].jsValue(callFrame);
+ JSValue scrutinee = callFrame[(++vPC)->u.operand].jsValue();
if (!scrutinee.isString())
vPC += defaultOffset;
else {
@@ -2828,7 +2939,7 @@ JSValuePtr Interpreter::privateExecute(ExecutionFlag flag, RegisterFile* registe
*/
int tableIndex = (++vPC)->u.operand;
int defaultOffset = (++vPC)->u.operand;
- JSValuePtr scrutinee = callFrame[(++vPC)->u.operand].jsValue(callFrame);
+ JSValue scrutinee = callFrame[(++vPC)->u.operand].jsValue();
if (!scrutinee.isString())
vPC += defaultOffset;
else
@@ -2884,15 +2995,15 @@ JSValuePtr Interpreter::privateExecute(ExecutionFlag flag, RegisterFile* registe
int argCount = vPC[3].u.operand;
int registerOffset = vPC[4].u.operand;
- JSValuePtr funcVal = callFrame[func].jsValue(callFrame);
+ JSValue funcVal = callFrame[func].jsValue();
Register* newCallFrame = callFrame->registers() + registerOffset;
Register* argv = newCallFrame - RegisterFile::CallFrameHeaderSize - argCount;
- JSValuePtr thisValue = argv[0].jsValue(callFrame);
+ JSValue thisValue = argv[0].jsValue();
JSGlobalObject* globalObject = callFrame->scopeChain()->globalObject();
if (thisValue == globalObject && funcVal == globalObject->evalFunction()) {
- JSValuePtr result = callEval(callFrame, registerFile, argv, argCount, registerOffset, exceptionValue);
+ JSValue result = callEval(callFrame, registerFile, argv, argCount, registerOffset, exceptionValue);
if (exceptionValue)
goto vm_throw;
callFrame[dst] = result;
@@ -2921,7 +3032,7 @@ JSValuePtr Interpreter::privateExecute(ExecutionFlag flag, RegisterFile* registe
int argCount = vPC[3].u.operand;
int registerOffset = vPC[4].u.operand;
- JSValuePtr v = callFrame[func].jsValue(callFrame);
+ JSValue v = callFrame[func].jsValue();
CallData callData;
CallType callType = v.getCallData(callData);
@@ -2959,18 +3070,18 @@ JSValuePtr Interpreter::privateExecute(ExecutionFlag flag, RegisterFile* registe
ArgList args(thisRegister + 1, argCount - 1);
// FIXME: All host methods should be calling toThisObject, but this is not presently the case.
- JSValuePtr thisValue = thisRegister->jsValue(callFrame);
+ JSValue thisValue = thisRegister->jsValue();
if (thisValue == jsNull())
thisValue = callFrame->globalThisValue();
- JSValuePtr returnValue;
+ JSValue returnValue;
{
SamplingTool::HostCallRecord callRecord(m_sampler);
returnValue = callData.native.function(newCallFrame, asObject(v), thisValue, args);
}
CHECK_FOR_EXCEPTION();
- callFrame[dst] = JSValuePtr(returnValue);
+ callFrame[dst] = JSValue(returnValue);
vPC += 5;
NEXT_INSTRUCTION();
@@ -2981,6 +3092,160 @@ JSValuePtr Interpreter::privateExecute(ExecutionFlag flag, RegisterFile* registe
exceptionValue = createNotAFunctionError(callFrame, v, vPC - callFrame->codeBlock()->instructions().begin(), callFrame->codeBlock());
goto vm_throw;
}
+ DEFINE_OPCODE(op_load_varargs) {
+ int argCountDst = (++vPC)->u.operand;
+ int argsOffset = (++vPC)->u.operand;
+
+ JSValue arguments = callFrame[argsOffset].jsValue();
+ uint32_t argCount = 0;
+ if (!arguments) {
+ argCount = (uint32_t)(callFrame[RegisterFile::ArgumentCount].u.i) - 1;
+ int32_t sizeDelta = argsOffset + argCount + RegisterFile::CallFrameHeaderSize;
+ Register* newEnd = callFrame->registers() + sizeDelta;
+ if (!registerFile->grow(newEnd) || ((newEnd - callFrame->registers()) != sizeDelta)) {
+ exceptionValue = createStackOverflowError(callFrame);
+ goto vm_throw;
+ }
+ uint32_t expectedParams = asFunction(callFrame[RegisterFile::Callee].jsValue())->body()->parameterCount();
+ uint32_t inplaceArgs = min(argCount, expectedParams);
+ uint32_t i = 0;
+ Register* argStore = callFrame->registers() + argsOffset;
+
+ // First step is to copy the "expected" parameters from their normal location relative to the callframe
+ for (; i < inplaceArgs; i++)
+ argStore[i] = callFrame->registers()[i - RegisterFile::CallFrameHeaderSize - expectedParams];
+ // Then we copy any additional arguments that may be further up the stack ('-1' to account for 'this')
+ for (; i < argCount; i++)
+ argStore[i] = callFrame->registers()[i - RegisterFile::CallFrameHeaderSize - expectedParams - argCount - 1];
+ } else if (!arguments.isUndefinedOrNull()) {
+ if (!arguments.isObject()) {
+ exceptionValue = createInvalidParamError(callFrame, "Function.prototype.apply", arguments, vPC - callFrame->codeBlock()->instructions().begin(), callFrame->codeBlock());
+ goto vm_throw;
+ }
+ if (asObject(arguments)->classInfo() == &Arguments::info) {
+ Arguments* args = asArguments(arguments);
+ argCount = args->numProvidedArguments(callFrame);
+ int32_t sizeDelta = argsOffset + argCount + RegisterFile::CallFrameHeaderSize;
+ Register* newEnd = callFrame->registers() + sizeDelta;
+ if (!registerFile->grow(newEnd) || ((newEnd - callFrame->registers()) != sizeDelta)) {
+ exceptionValue = createStackOverflowError(callFrame);
+ goto vm_throw;
+ }
+ args->copyToRegisters(callFrame, callFrame->registers() + argsOffset, argCount);
+ } else if (isJSArray(&callFrame->globalData(), arguments)) {
+ JSArray* array = asArray(arguments);
+ argCount = array->length();
+ int32_t sizeDelta = argsOffset + argCount + RegisterFile::CallFrameHeaderSize;
+ Register* newEnd = callFrame->registers() + sizeDelta;
+ if (!registerFile->grow(newEnd) || ((newEnd - callFrame->registers()) != sizeDelta)) {
+ exceptionValue = createStackOverflowError(callFrame);
+ goto vm_throw;
+ }
+ array->copyToRegisters(callFrame, callFrame->registers() + argsOffset, argCount);
+ } else if (asObject(arguments)->inherits(&JSArray::info)) {
+ JSObject* argObject = asObject(arguments);
+ argCount = argObject->get(callFrame, callFrame->propertyNames().length).toUInt32(callFrame);
+ int32_t sizeDelta = argsOffset + argCount + RegisterFile::CallFrameHeaderSize;
+ Register* newEnd = callFrame->registers() + sizeDelta;
+ if (!registerFile->grow(newEnd) || ((newEnd - callFrame->registers()) != sizeDelta)) {
+ exceptionValue = createStackOverflowError(callFrame);
+ goto vm_throw;
+ }
+ Register* argsBuffer = callFrame->registers() + argsOffset;
+ for (unsigned i = 0; i < argCount; ++i) {
+ argsBuffer[i] = asObject(arguments)->get(callFrame, i);
+ CHECK_FOR_EXCEPTION();
+ }
+ } else {
+ if (!arguments.isObject()) {
+ exceptionValue = createInvalidParamError(callFrame, "Function.prototype.apply", arguments, vPC - callFrame->codeBlock()->instructions().begin(), callFrame->codeBlock());
+ goto vm_throw;
+ }
+ }
+ }
+ CHECK_FOR_EXCEPTION();
+ callFrame[argCountDst] = argCount + 1;
+ ++vPC;
+ NEXT_INSTRUCTION();
+ }
+ DEFINE_OPCODE(op_call_varargs) {
+ /* call_varargs dst(r) func(r) argCountReg(r) baseRegisterOffset(n)
+
+ Perform a function call with a dynamic set of arguments.
+
+ registerOffset is the distance the callFrame pointer should move
+ before the VM initializes the new call frame's header, excluding
+ space for arguments.
+
+ dst is where op_ret should store its result.
+ */
+
+ int dst = vPC[1].u.operand;
+ int func = vPC[2].u.operand;
+ int argCountReg = vPC[3].u.operand;
+ int registerOffset = vPC[4].u.operand;
+
+ JSValue v = callFrame[func].jsValue();
+ int argCount = callFrame[argCountReg].i();
+ registerOffset += argCount;
+ CallData callData;
+ CallType callType = v.getCallData(callData);
+
+ if (callType == CallTypeJS) {
+ ScopeChainNode* callDataScopeChain = callData.js.scopeChain;
+ FunctionBodyNode* functionBodyNode = callData.js.functionBody;
+ CodeBlock* newCodeBlock = &functionBodyNode->bytecode(callDataScopeChain);
+
+ CallFrame* previousCallFrame = callFrame;
+
+ callFrame = slideRegisterWindowForCall(newCodeBlock, registerFile, callFrame, registerOffset, argCount);
+ if (UNLIKELY(!callFrame)) {
+ callFrame = previousCallFrame;
+ exceptionValue = createStackOverflowError(callFrame);
+ goto vm_throw;
+ }
+
+ callFrame->init(newCodeBlock, vPC + 5, callDataScopeChain, previousCallFrame, dst, argCount, asFunction(v));
+ vPC = newCodeBlock->instructions().begin();
+
+#if ENABLE(OPCODE_STATS)
+ OpcodeStats::resetLastInstruction();
+#endif
+
+ NEXT_INSTRUCTION();
+ }
+
+ if (callType == CallTypeHost) {
+ ScopeChainNode* scopeChain = callFrame->scopeChain();
+ CallFrame* newCallFrame = CallFrame::create(callFrame->registers() + registerOffset);
+ newCallFrame->init(0, vPC + 5, scopeChain, callFrame, dst, argCount, 0);
+
+ Register* thisRegister = newCallFrame->registers() - RegisterFile::CallFrameHeaderSize - argCount;
+ ArgList args(thisRegister + 1, argCount - 1);
+
+ // FIXME: All host methods should be calling toThisObject, but this is not presently the case.
+ JSValue thisValue = thisRegister->jsValue();
+ if (thisValue == jsNull())
+ thisValue = callFrame->globalThisValue();
+
+ JSValue returnValue;
+ {
+ SamplingTool::HostCallRecord callRecord(m_sampler);
+ returnValue = callData.native.function(newCallFrame, asObject(v), thisValue, args);
+ }
+ CHECK_FOR_EXCEPTION();
+
+ callFrame[dst] = JSValue(returnValue);
+
+ vPC += 5;
+ NEXT_INSTRUCTION();
+ }
+
+ ASSERT(callType == CallTypeNone);
+
+ exceptionValue = createNotAFunctionError(callFrame, v, vPC - callFrame->codeBlock()->instructions().begin(), callFrame->codeBlock());
+ goto vm_throw;
+ }
DEFINE_OPCODE(op_tear_off_activation) {
/* tear_off_activation activation(r)
@@ -2997,7 +3262,7 @@ JSValuePtr Interpreter::privateExecute(ExecutionFlag flag, RegisterFile* registe
int src = (++vPC)->u.operand;
ASSERT(callFrame->codeBlock()->needsFullScopeChain());
- asActivation(callFrame[src].getJSValue())->copyRegisters(callFrame->optionalCalleeArguments());
+ asActivation(callFrame[src].jsValue())->copyRegisters(callFrame->optionalCalleeArguments());
++vPC;
NEXT_INSTRUCTION();
@@ -3016,8 +3281,8 @@ JSValuePtr Interpreter::privateExecute(ExecutionFlag flag, RegisterFile* registe
*/
ASSERT(callFrame->codeBlock()->usesArguments() && !callFrame->codeBlock()->needsFullScopeChain());
-
- callFrame->optionalCalleeArguments()->copyRegisters();
+ if (callFrame->optionalCalleeArguments())
+ callFrame->optionalCalleeArguments()->copyRegisters();
++vPC;
NEXT_INSTRUCTION();
@@ -3037,7 +3302,7 @@ JSValuePtr Interpreter::privateExecute(ExecutionFlag flag, RegisterFile* registe
if (callFrame->codeBlock()->needsFullScopeChain())
callFrame->scopeChain()->deref();
- JSValuePtr returnValue = callFrame[result].jsValue(callFrame);
+ JSValue returnValue = callFrame[result].jsValue();
vPC = callFrame->returnPC();
int dst = callFrame->returnValueRegister();
@@ -3046,7 +3311,7 @@ JSValuePtr Interpreter::privateExecute(ExecutionFlag flag, RegisterFile* registe
if (callFrame->hasHostCallFrameFlag())
return returnValue;
- callFrame[dst] = JSValuePtr(returnValue);
+ callFrame[dst] = JSValue(returnValue);
NEXT_INSTRUCTION();
}
@@ -3116,28 +3381,40 @@ JSValuePtr Interpreter::privateExecute(ExecutionFlag flag, RegisterFile* registe
*/
int thisRegister = (++vPC)->u.operand;
- JSValuePtr thisVal = callFrame[thisRegister].getJSValue();
+ JSValue thisVal = callFrame[thisRegister].jsValue();
if (thisVal.needsThisConversion())
- callFrame[thisRegister] = JSValuePtr(thisVal.toThisObject(callFrame));
+ callFrame[thisRegister] = JSValue(thisVal.toThisObject(callFrame));
++vPC;
NEXT_INSTRUCTION();
}
- DEFINE_OPCODE(op_create_arguments) {
+ DEFINE_OPCODE(op_init_arguments) {
/* create_arguments
- Creates the 'arguments' object and places it in both the
- 'arguments' call frame slot and the local 'arguments'
- register.
+ Initialises the arguments object reference to null to ensure
+ we can correctly detect that we need to create it later (or
+ avoid creating it altogether).
This opcode should only be used at the beginning of a code
block.
- */
+ */
+ callFrame[RegisterFile::ArgumentsRegister] = JSValue();
+ ++vPC;
+ NEXT_INSTRUCTION();
+ }
+ DEFINE_OPCODE(op_create_arguments) {
+ /* create_arguments
- Arguments* arguments = new (globalData) Arguments(callFrame);
- callFrame->setCalleeArguments(arguments);
- callFrame[RegisterFile::ArgumentsRegister] = arguments;
+ Creates the 'arguments' object and places it in both the
+ 'arguments' call frame slot and the local 'arguments'
+ register, if it has not already been initialised.
+ */
+ if (!callFrame->optionalCalleeArguments()) {
+ Arguments* arguments = new (globalData) Arguments(callFrame);
+ callFrame->setCalleeArguments(arguments);
+ callFrame[RegisterFile::ArgumentsRegister] = arguments;
+ }
++vPC;
NEXT_INSTRUCTION();
}
@@ -3163,7 +3440,7 @@ JSValuePtr Interpreter::privateExecute(ExecutionFlag flag, RegisterFile* registe
int proto = vPC[5].u.operand;
int thisRegister = vPC[6].u.operand;
- JSValuePtr v = callFrame[func].jsValue(callFrame);
+ JSValue v = callFrame[func].jsValue();
ConstructData constructData;
ConstructType constructType = v.getConstructData(constructData);
@@ -3174,14 +3451,14 @@ JSValuePtr Interpreter::privateExecute(ExecutionFlag flag, RegisterFile* registe
CodeBlock* newCodeBlock = &functionBodyNode->bytecode(callDataScopeChain);
Structure* structure;
- JSValuePtr prototype = callFrame[proto].jsValue(callFrame);
+ JSValue prototype = callFrame[proto].jsValue();
if (prototype.isObject())
structure = asObject(prototype)->inheritorID();
else
structure = callDataScopeChain->globalObject()->emptyObjectStructure();
JSObject* newObject = new (globalData) JSObject(structure);
- callFrame[thisRegister] = JSValuePtr(newObject); // "this" value
+ callFrame[thisRegister] = JSValue(newObject); // "this" value
CallFrame* previousCallFrame = callFrame;
@@ -3209,13 +3486,13 @@ JSValuePtr Interpreter::privateExecute(ExecutionFlag flag, RegisterFile* registe
CallFrame* newCallFrame = CallFrame::create(callFrame->registers() + registerOffset);
newCallFrame->init(0, vPC + 7, scopeChain, callFrame, dst, argCount, 0);
- JSValuePtr returnValue;
+ JSValue returnValue;
{
SamplingTool::HostCallRecord callRecord(m_sampler);
returnValue = constructData.native.function(newCallFrame, asObject(v), args);
}
CHECK_FOR_EXCEPTION();
- callFrame[dst] = JSValuePtr(returnValue);
+ callFrame[dst] = JSValue(returnValue);
vPC += 7;
NEXT_INSTRUCTION();
@@ -3234,7 +3511,7 @@ JSValuePtr Interpreter::privateExecute(ExecutionFlag flag, RegisterFile* registe
*/
int dst = vPC[1].u.operand;
- if (LIKELY(callFrame[dst].jsValue(callFrame).isObject())) {
+ if (LIKELY(callFrame[dst].jsValue().isObject())) {
vPC += 3;
NEXT_INSTRUCTION();
}
@@ -3245,6 +3522,25 @@ JSValuePtr Interpreter::privateExecute(ExecutionFlag flag, RegisterFile* registe
vPC += 3;
NEXT_INSTRUCTION();
}
+ DEFINE_OPCODE(op_strcat) {
+ int dst = (++vPC)->u.operand;
+ int src = (++vPC)->u.operand;
+ int count = (++vPC)->u.operand;
+
+ callFrame[dst] = concatenateStrings(callFrame, &callFrame->registers()[src], count);
+ ++vPC;
+
+ NEXT_INSTRUCTION();
+ }
+ DEFINE_OPCODE(op_to_primitive) {
+ int dst = (++vPC)->u.operand;
+ int src = (++vPC)->u.operand;
+
+ callFrame[dst] = callFrame[src].jsValue().toPrimitive(callFrame);
+ ++vPC;
+
+ NEXT_INSTRUCTION();
+ }
DEFINE_OPCODE(op_push_scope) {
/* push_scope scope(r)
@@ -3253,11 +3549,11 @@ JSValuePtr Interpreter::privateExecute(ExecutionFlag flag, RegisterFile* registe
are replaced by the result of toObject conversion of the scope.
*/
int scope = (++vPC)->u.operand;
- JSValuePtr v = callFrame[scope].jsValue(callFrame);
+ JSValue v = callFrame[scope].jsValue();
JSObject* o = v.toObject(callFrame);
CHECK_FOR_EXCEPTION();
- callFrame[scope] = JSValuePtr(o);
+ callFrame[scope] = JSValue(o);
callFrame->setScopeChain(callFrame->scopeChain()->push(o));
++vPC;
@@ -3284,7 +3580,7 @@ JSValuePtr Interpreter::privateExecute(ExecutionFlag flag, RegisterFile* registe
int dst = (++vPC)->u.operand;
int base = (++vPC)->u.operand;
- callFrame[dst] = JSPropertyNameIterator::create(callFrame, callFrame[base].jsValue(callFrame));
+ callFrame[dst] = JSPropertyNameIterator::create(callFrame, callFrame[base].jsValue());
++vPC;
NEXT_INSTRUCTION();
}
@@ -3302,9 +3598,9 @@ JSValuePtr Interpreter::privateExecute(ExecutionFlag flag, RegisterFile* registe
int target = (++vPC)->u.operand;
JSPropertyNameIterator* it = callFrame[iter].propertyNameIterator();
- if (JSValuePtr temp = it->next(callFrame)) {
+ if (JSValue temp = it->next(callFrame)) {
CHECK_FOR_TIMEOUT();
- callFrame[dst] = JSValuePtr(temp);
+ callFrame[dst] = JSValue(temp);
vPC += target;
NEXT_INSTRUCTION();
}
@@ -3361,7 +3657,7 @@ JSValuePtr Interpreter::privateExecute(ExecutionFlag flag, RegisterFile* registe
ASSERT(!globalData->exception);
int ex = (++vPC)->u.operand;
callFrame[ex] = exceptionValue;
- exceptionValue = noValue();
+ exceptionValue = JSValue();
++vPC;
NEXT_INSTRUCTION();
@@ -3378,7 +3674,7 @@ JSValuePtr Interpreter::privateExecute(ExecutionFlag flag, RegisterFile* registe
*/
int ex = (++vPC)->u.operand;
- exceptionValue = callFrame[ex].jsValue(callFrame);
+ exceptionValue = callFrame[ex].jsValue();
handler = throwException(callFrame, exceptionValue, vPC - callFrame->codeBlock()->instructions().begin(), true);
if (!handler) {
@@ -3396,7 +3692,7 @@ JSValuePtr Interpreter::privateExecute(ExecutionFlag flag, RegisterFile* registe
*/
int dst = (++vPC)->u.operand;
int src = (++vPC)->u.operand;
- callFrame[dst] = JSValuePtr(callFrame->codeBlock()->unexpectedConstant(src));
+ callFrame[dst] = JSValue(callFrame->codeBlock()->unexpectedConstant(src));
++vPC;
NEXT_INSTRUCTION();
@@ -3414,7 +3710,7 @@ JSValuePtr Interpreter::privateExecute(ExecutionFlag flag, RegisterFile* registe
int message = (++vPC)->u.operand;
CodeBlock* codeBlock = callFrame->codeBlock();
- callFrame[dst] = JSValuePtr(Error::create(callFrame, (ErrorType)type, codeBlock->unexpectedConstant(message).toString(callFrame), codeBlock->lineNumberForBytecodeOffset(callFrame, vPC - codeBlock->instructions().begin()), codeBlock->ownerNode()->sourceID(), codeBlock->ownerNode()->sourceURL()));
+ callFrame[dst] = JSValue(Error::create(callFrame, (ErrorType)type, codeBlock->unexpectedConstant(message).toString(callFrame), codeBlock->lineNumberForBytecodeOffset(callFrame, vPC - codeBlock->instructions().begin()), codeBlock->ownerNode()->sourceID(), codeBlock->ownerNode()->sourceURL()));
++vPC;
NEXT_INSTRUCTION();
@@ -3432,7 +3728,7 @@ JSValuePtr Interpreter::privateExecute(ExecutionFlag flag, RegisterFile* registe
scopeChain->deref();
}
int result = (++vPC)->u.operand;
- return callFrame[result].jsValue(callFrame);
+ return callFrame[result].jsValue();
}
DEFINE_OPCODE(op_put_getter) {
/* put_getter base(r) property(id) function(r)
@@ -3449,11 +3745,11 @@ JSValuePtr Interpreter::privateExecute(ExecutionFlag flag, RegisterFile* registe
int property = (++vPC)->u.operand;
int function = (++vPC)->u.operand;
- ASSERT(callFrame[base].jsValue(callFrame).isObject());
- JSObject* baseObj = asObject(callFrame[base].jsValue(callFrame));
+ ASSERT(callFrame[base].jsValue().isObject());
+ JSObject* baseObj = asObject(callFrame[base].jsValue());
Identifier& ident = callFrame->codeBlock()->identifier(property);
- ASSERT(callFrame[function].jsValue(callFrame).isObject());
- baseObj->defineGetter(callFrame, ident, asObject(callFrame[function].jsValue(callFrame)));
+ ASSERT(callFrame[function].jsValue().isObject());
+ baseObj->defineGetter(callFrame, ident, asObject(callFrame[function].jsValue()));
++vPC;
NEXT_INSTRUCTION();
@@ -3473,15 +3769,19 @@ JSValuePtr Interpreter::privateExecute(ExecutionFlag flag, RegisterFile* registe
int property = (++vPC)->u.operand;
int function = (++vPC)->u.operand;
- ASSERT(callFrame[base].jsValue(callFrame).isObject());
- JSObject* baseObj = asObject(callFrame[base].jsValue(callFrame));
+ ASSERT(callFrame[base].jsValue().isObject());
+ JSObject* baseObj = asObject(callFrame[base].jsValue());
Identifier& ident = callFrame->codeBlock()->identifier(property);
- ASSERT(callFrame[function].jsValue(callFrame).isObject());
- baseObj->defineSetter(callFrame, ident, asObject(callFrame[function].jsValue(callFrame)));
+ ASSERT(callFrame[function].jsValue().isObject());
+ baseObj->defineSetter(callFrame, ident, asObject(callFrame[function].jsValue()));
++vPC;
NEXT_INSTRUCTION();
}
+ DEFINE_OPCODE(op_method_check) {
+ vPC++;
+ NEXT_INSTRUCTION();
+ }
DEFINE_OPCODE(op_jsr) {
/* jsr retAddrDst(r) target(offset)
@@ -3530,7 +3830,7 @@ JSValuePtr Interpreter::privateExecute(ExecutionFlag flag, RegisterFile* registe
int function = vPC[1].u.operand;
if (*enabledProfilerReference)
- (*enabledProfilerReference)->willExecute(callFrame, callFrame[function].jsValue(callFrame));
+ (*enabledProfilerReference)->willExecute(callFrame, callFrame[function].jsValue());
vPC += 2;
NEXT_INSTRUCTION();
@@ -3544,13 +3844,13 @@ JSValuePtr Interpreter::privateExecute(ExecutionFlag flag, RegisterFile* registe
int function = vPC[1].u.operand;
if (*enabledProfilerReference)
- (*enabledProfilerReference)->didExecute(callFrame, callFrame[function].jsValue(callFrame));
+ (*enabledProfilerReference)->didExecute(callFrame, callFrame[function].jsValue());
vPC += 2;
NEXT_INSTRUCTION();
}
vm_throw: {
- globalData->exception = noValue();
+ globalData->exception = JSValue();
if (!tickCount) {
// The exceptionValue is a lie! (GCC produces bad code for reasons I
// cannot fathom if we don't assign to the exceptionValue before branching)
@@ -3569,13 +3869,14 @@ JSValuePtr Interpreter::privateExecute(ExecutionFlag flag, RegisterFile* registe
#if !HAVE(COMPUTED_GOTO)
} // iterator loop ends
#endif
+#endif // USE(INTERPRETER)
#undef NEXT_INSTRUCTION
#undef DEFINE_OPCODE
#undef CHECK_FOR_EXCEPTION
#undef CHECK_FOR_TIMEOUT
}
-JSValuePtr Interpreter::retrieveArguments(CallFrame* callFrame, JSFunction* function) const
+JSValue Interpreter::retrieveArguments(CallFrame* callFrame, JSFunction* function) const
{
CallFrame* functionCallFrame = findFunctionCallFrame(callFrame, function);
if (!functionCallFrame)
@@ -3586,7 +3887,12 @@ JSValuePtr Interpreter::retrieveArguments(CallFrame* callFrame, JSFunction* func
ASSERT(codeBlock->codeType() == FunctionCode);
SymbolTable& symbolTable = codeBlock->symbolTable();
int argumentsIndex = symbolTable.get(functionCallFrame->propertyNames().arguments.ustring().rep()).getIndex();
- return functionCallFrame[argumentsIndex].jsValue(callFrame);
+ if (!functionCallFrame[argumentsIndex].arguments()) {
+ Arguments* arguments = new (callFrame) Arguments(functionCallFrame);
+ functionCallFrame->setCalleeArguments(arguments);
+ functionCallFrame[RegisterFile::ArgumentsRegister] = arguments;
+ }
+ return functionCallFrame[argumentsIndex].jsValue();
}
Arguments* arguments = functionCallFrame->optionalCalleeArguments();
@@ -3599,7 +3905,7 @@ JSValuePtr Interpreter::retrieveArguments(CallFrame* callFrame, JSFunction* func
return arguments;
}
-JSValuePtr Interpreter::retrieveCaller(CallFrame* callFrame, InternalFunction* function) const
+JSValue Interpreter::retrieveCaller(CallFrame* callFrame, InternalFunction* function) const
{
CallFrame* functionCallFrame = findFunctionCallFrame(callFrame, function);
if (!functionCallFrame)
@@ -3609,16 +3915,16 @@ JSValuePtr Interpreter::retrieveCaller(CallFrame* callFrame, InternalFunction* f
if (callerFrame->hasHostCallFrameFlag())
return jsNull();
- JSValuePtr caller = callerFrame->callee();
+ JSValue caller = callerFrame->callee();
if (!caller)
return jsNull();
return caller;
}
-void Interpreter::retrieveLastCaller(CallFrame* callFrame, int& lineNumber, intptr_t& sourceID, UString& sourceURL, JSValuePtr& function) const
+void Interpreter::retrieveLastCaller(CallFrame* callFrame, int& lineNumber, intptr_t& sourceID, UString& sourceURL, JSValue& function) const
{
- function = noValue();
+ function = JSValue();
lineNumber = -1;
sourceURL = UString();
@@ -3646,2140 +3952,4 @@ CallFrame* Interpreter::findFunctionCallFrame(CallFrame* callFrame, InternalFunc
return 0;
}
-#ifdef MANUAL_MERGE_REQUIRED
-#if ENABLE(JIT)
-
-#if ENABLE(JIT_OPTIMIZE_PROPERTY_ACCESS)
-
-NEVER_INLINE void Interpreter::tryCTICachePutByID(CallFrame* callFrame, CodeBlock* codeBlock, void* returnAddress, JSValuePtr baseValue, const PutPropertySlot& slot)
-{
- // The interpreter checks for recursion here; I do not believe this can occur in CTI.
-
- if (!baseValue.isCell())
- return;
-
- // Uncacheable: give up.
- if (!slot.isCacheable()) {
- ctiPatchCallByReturnAddress(returnAddress, reinterpret_cast<void*>(cti_op_put_by_id_generic));
- return;
- }
-
- JSCell* baseCell = asCell(baseValue);
- Structure* structure = baseCell->structure();
-
- if (structure->isDictionary()) {
- ctiPatchCallByReturnAddress(returnAddress, reinterpret_cast<void*>(cti_op_put_by_id_generic));
- return;
- }
-
- // If baseCell != base, then baseCell must be a proxy for another object.
- if (baseCell != slot.base()) {
- ctiPatchCallByReturnAddress(returnAddress, reinterpret_cast<void*>(cti_op_put_by_id_generic));
- return;
- }
-
- StructureStubInfo* stubInfo = &codeBlock->getStubInfo(returnAddress);
-
- // Cache hit: Specialize instruction and ref Structures.
-
- // Structure transition, cache transition info
- if (slot.type() == PutPropertySlot::NewProperty) {
- StructureChain* chain = structure->cachedPrototypeChain();
- if (!chain) {
- chain = cachePrototypeChain(callFrame, structure);
- if (!chain) {
- // This happens if someone has manually inserted null into the prototype chain
- stubInfo->opcodeID = op_put_by_id_generic;
- return;
- }
- }
- stubInfo->initPutByIdTransition(structure->previousID(), structure, chain);
- JIT::compilePutByIdTransition(callFrame->scopeChain()->globalData, codeBlock, stubInfo, structure->previousID(), structure, slot.cachedOffset(), chain, returnAddress);
- return;
- }
-
- stubInfo->initPutByIdReplace(structure);
-
-#if USE(CTI_REPATCH_PIC)
- UNUSED_PARAM(callFrame);
- JIT::patchPutByIdReplace(stubInfo, structure, slot.cachedOffset(), returnAddress);
-#else
- JIT::compilePutByIdReplace(callFrame->scopeChain()->globalData, callFrame, codeBlock, stubInfo, structure, slot.cachedOffset(), returnAddress);
-#endif
-}
-
-NEVER_INLINE void Interpreter::tryCTICacheGetByID(CallFrame* callFrame, CodeBlock* codeBlock, void* returnAddress, JSValuePtr baseValue, const Identifier& propertyName, const PropertySlot& slot)
-{
- // FIXME: Write a test that proves we need to check for recursion here just
- // like the interpreter does, then add a check for recursion.
-
- // FIXME: Cache property access for immediates.
- if (!baseValue.isCell()) {
- ctiPatchCallByReturnAddress(returnAddress, reinterpret_cast<void*>(cti_op_get_by_id_generic));
- return;
- }
-
- if (isJSArray(baseValue) && propertyName == callFrame->propertyNames().length) {
-#if USE(CTI_REPATCH_PIC)
- JIT::compilePatchGetArrayLength(callFrame->scopeChain()->globalData, codeBlock, returnAddress);
-#else
- ctiPatchCallByReturnAddress(returnAddress, m_ctiArrayLengthTrampoline);
-#endif
- return;
- }
- if (isJSString(baseValue) && propertyName == callFrame->propertyNames().length) {
- // The tradeoff of compiling an patched inline string length access routine does not seem
- // to pay off, so we currently only do this for arrays.
- ctiPatchCallByReturnAddress(returnAddress, m_ctiStringLengthTrampoline);
- return;
- }
-
- // Uncacheable: give up.
- if (!slot.isCacheable()) {
- ctiPatchCallByReturnAddress(returnAddress, reinterpret_cast<void*>(cti_op_get_by_id_generic));
- return;
- }
-
- JSCell* baseCell = asCell(baseValue);
- Structure* structure = baseCell->structure();
-
- if (structure->isDictionary()) {
- ctiPatchCallByReturnAddress(returnAddress, reinterpret_cast<void*>(cti_op_get_by_id_generic));
- return;
- }
-
- // In the interpreter the last structure is trapped here; in CTI we use the
- // *_second method to achieve a similar (but not quite the same) effect.
-
- StructureStubInfo* stubInfo = &codeBlock->getStubInfo(returnAddress);
-
- // Cache hit: Specialize instruction and ref Structures.
-
- if (slot.slotBase() == baseValue) {
- // set this up, so derefStructures can do it's job.
- stubInfo->initGetByIdSelf(structure);
-
-#if USE(CTI_REPATCH_PIC)
- JIT::patchGetByIdSelf(stubInfo, structure, slot.cachedOffset(), returnAddress);
-#else
- JIT::compileGetByIdSelf(callFrame->scopeChain()->globalData, callFrame, codeBlock, stubInfo, structure, slot.cachedOffset(), returnAddress);
-#endif
- return;
- }
-
- if (slot.slotBase() == structure->prototypeForLookup(callFrame)) {
- ASSERT(slot.slotBase().isObject());
-
- JSObject* slotBaseObject = asObject(slot.slotBase());
-
- // Since we're accessing a prototype in a loop, it's a good bet that it
- // should not be treated as a dictionary.
- if (slotBaseObject->structure()->isDictionary()) {
- RefPtr<Structure> transition = Structure::fromDictionaryTransition(slotBaseObject->structure());
- slotBaseObject->setStructure(transition.release());
- asCell(baseValue)->structure()->setCachedPrototypeChain(0);
- }
-
- stubInfo->initGetByIdProto(structure, slotBaseObject->structure());
-
- JIT::compileGetByIdProto(callFrame->scopeChain()->globalData, callFrame, codeBlock, stubInfo, structure, slotBaseObject->structure(), slot.cachedOffset(), returnAddress);
- return;
- }
-
- size_t count = countPrototypeChainEntriesAndCheckForProxies(callFrame, baseValue, slot);
- if (!count) {
- stubInfo->opcodeID = op_get_by_id_generic;
- return;
- }
-
- StructureChain* chain = structure->cachedPrototypeChain();
- if (!chain)
- chain = cachePrototypeChain(callFrame, structure);
- ASSERT(chain);
-
- stubInfo->initGetByIdChain(structure, chain);
-
- JIT::compileGetByIdChain(callFrame->scopeChain()->globalData, callFrame, codeBlock, stubInfo, structure, chain, count, slot.cachedOffset(), returnAddress);
-}
-
-#endif
-
-#if USE(JIT_STUB_ARGUMENT_VA_LIST)
-#define SETUP_VA_LISTL_ARGS va_list vl_args; va_start(vl_args, args)
-#else // JIT_STUB_ARGUMENT_REGISTER or JIT_STUB_ARGUMENT_STACK
-#define SETUP_VA_LISTL_ARGS
-#endif
-
-#ifndef NDEBUG
-
-extern "C" {
-
-static void jscGeneratedNativeCode()
-{
- // When executing a CTI function (which might do an allocation), we hack the return address
- // to pretend to be executing this function, to keep stack logging tools from blowing out
- // memory.
-}
-
-}
-
-struct StackHack {
- ALWAYS_INLINE StackHack(void** location)
- {
- returnAddressLocation = location;
- savedReturnAddress = *returnAddressLocation;
- ctiSetReturnAddress(returnAddressLocation, reinterpret_cast<void*>(jscGeneratedNativeCode));
- }
- ALWAYS_INLINE ~StackHack()
- {
- ctiSetReturnAddress(returnAddressLocation, savedReturnAddress);
- }
-
- void** returnAddressLocation;
- void* savedReturnAddress;
-};
-
-#define BEGIN_STUB_FUNCTION() SETUP_VA_LISTL_ARGS; StackHack stackHack(&STUB_RETURN_ADDRESS_SLOT)
-#define STUB_SET_RETURN_ADDRESS(address) stackHack.savedReturnAddress = address
-#define STUB_RETURN_ADDRESS stackHack.savedReturnAddress
-
-#else
-
-#define BEGIN_STUB_FUNCTION() SETUP_VA_LISTL_ARGS
-#define STUB_SET_RETURN_ADDRESS(address) ctiSetReturnAddress(&STUB_RETURN_ADDRESS_SLOT, address);
-#define STUB_RETURN_ADDRESS STUB_RETURN_ADDRESS_SLOT
-
-#endif
-
-// The reason this is not inlined is to avoid having to do a PIC branch
-// to get the address of the ctiVMThrowTrampoline function. It's also
-// good to keep the code size down by leaving as much of the exception
-// handling code out of line as possible.
-static NEVER_INLINE void returnToThrowTrampoline(JSGlobalData* globalData, void* exceptionLocation, void*& returnAddressSlot)
-{
- ASSERT(globalData->exception);
- globalData->exceptionLocation = exceptionLocation;
- ctiSetReturnAddress(&returnAddressSlot, reinterpret_cast<void*>(ctiVMThrowTrampoline));
-}
-
-static NEVER_INLINE void throwStackOverflowError(CallFrame* callFrame, JSGlobalData* globalData, void* exceptionLocation, void*& returnAddressSlot)
-{
- globalData->exception = createStackOverflowError(callFrame);
- returnToThrowTrampoline(globalData, exceptionLocation, returnAddressSlot);
-}
-
-#define VM_THROW_EXCEPTION() \
- do { \
- VM_THROW_EXCEPTION_AT_END(); \
- return 0; \
- } while (0)
-#define VM_THROW_EXCEPTION_2() \
- do { \
- VM_THROW_EXCEPTION_AT_END(); \
- RETURN_PAIR(0, 0); \
- } while (0)
-#define VM_THROW_EXCEPTION_AT_END() \
- returnToThrowTrampoline(ARG_globalData, STUB_RETURN_ADDRESS, STUB_RETURN_ADDRESS)
-
-#define CHECK_FOR_EXCEPTION() \
- do { \
- if (UNLIKELY(ARG_globalData->exception != noValue())) \
- VM_THROW_EXCEPTION(); \
- } while (0)
-#define CHECK_FOR_EXCEPTION_AT_END() \
- do { \
- if (UNLIKELY(ARG_globalData->exception != noValue())) \
- VM_THROW_EXCEPTION_AT_END(); \
- } while (0)
-#define CHECK_FOR_EXCEPTION_VOID() \
- do { \
- if (UNLIKELY(ARG_globalData->exception != noValue())) { \
- VM_THROW_EXCEPTION_AT_END(); \
- return; \
- } \
- } while (0)
-
-JSObject* Interpreter::cti_op_convert_this(STUB_ARGS)
-{
- BEGIN_STUB_FUNCTION();
-
- JSValuePtr v1 = ARG_src1;
- CallFrame* callFrame = ARG_callFrame;
-
- JSObject* result = v1.toThisObject(callFrame);
- CHECK_FOR_EXCEPTION_AT_END();
- return result;
-}
-
-void Interpreter::cti_op_end(STUB_ARGS)
-{
- BEGIN_STUB_FUNCTION();
-
- ScopeChainNode* scopeChain = ARG_callFrame->scopeChain();
- ASSERT(scopeChain->refCount > 1);
- scopeChain->deref();
-}
-
-JSValueEncodedAsPointer* Interpreter::cti_op_add(STUB_ARGS)
-{
- BEGIN_STUB_FUNCTION();
-
- JSValuePtr v1 = ARG_src1;
- JSValuePtr v2 = ARG_src2;
-
- double left;
- double right = 0.0;
-
- bool rightIsNumber = v2.getNumber(right);
- if (rightIsNumber && v1.getNumber(left))
- return JSValuePtr::encode(jsNumber(ARG_globalData, left + right));
-
- CallFrame* callFrame = ARG_callFrame;
-
- bool leftIsString = v1.isString();
- if (leftIsString && v2.isString()) {
- RefPtr<UString::Rep> value = concatenate(asString(v1)->value().rep(), asString(v2)->value().rep());
- if (UNLIKELY(!value)) {
- throwOutOfMemoryError(callFrame);
- VM_THROW_EXCEPTION();
- }
-
- return JSValuePtr::encode(jsString(ARG_globalData, value.release()));
- }
-
- if (rightIsNumber & leftIsString) {
- RefPtr<UString::Rep> value = v2.isInt32Fast() ?
- concatenate(asString(v1)->value().rep(), v2.getInt32Fast()) :
- concatenate(asString(v1)->value().rep(), right);
-
- if (UNLIKELY(!value)) {
- throwOutOfMemoryError(callFrame);
- VM_THROW_EXCEPTION();
- }
- return JSValuePtr::encode(jsString(ARG_globalData, value.release()));
- }
-
- // All other cases are pretty uncommon
- JSValuePtr result = jsAddSlowCase(callFrame, v1, v2);
- CHECK_FOR_EXCEPTION_AT_END();
- return JSValuePtr::encode(result);
-}
-
-JSValueEncodedAsPointer* Interpreter::cti_op_pre_inc(STUB_ARGS)
-{
- BEGIN_STUB_FUNCTION();
-
- JSValuePtr v = ARG_src1;
-
- CallFrame* callFrame = ARG_callFrame;
- JSValuePtr result = jsNumber(ARG_globalData, v.toNumber(callFrame) + 1);
- CHECK_FOR_EXCEPTION_AT_END();
- return JSValuePtr::encode(result);
-}
-
-int Interpreter::cti_timeout_check(STUB_ARGS)
-{
- BEGIN_STUB_FUNCTION();
- Interpreter* interpreter = ARG_globalData->interpreter;
-
- if (interpreter->checkTimeout(ARG_callFrame->dynamicGlobalObject())) {
- ARG_globalData->exception = createInterruptedExecutionException(ARG_globalData);
- VM_THROW_EXCEPTION_AT_END();
- }
-
- return interpreter->m_ticksUntilNextTimeoutCheck;
-}
-
-void Interpreter::cti_register_file_check(STUB_ARGS)
-{
- BEGIN_STUB_FUNCTION();
-
- if (LIKELY(ARG_registerFile->grow(ARG_callFrame + ARG_callFrame->codeBlock()->m_numCalleeRegisters)))
- return;
-
- // Rewind to the previous call frame because op_call already optimistically
- // moved the call frame forward.
- CallFrame* oldCallFrame = ARG_callFrame->callerFrame();
- ARG_setCallFrame(oldCallFrame);
- throwStackOverflowError(oldCallFrame, ARG_globalData, oldCallFrame->returnPC(), STUB_RETURN_ADDRESS);
-}
-
-int Interpreter::cti_op_loop_if_less(STUB_ARGS)
-{
- BEGIN_STUB_FUNCTION();
-
- JSValuePtr src1 = ARG_src1;
- JSValuePtr src2 = ARG_src2;
- CallFrame* callFrame = ARG_callFrame;
-
- bool result = jsLess(callFrame, src1, src2);
- CHECK_FOR_EXCEPTION_AT_END();
- return result;
-}
-
-int Interpreter::cti_op_loop_if_lesseq(STUB_ARGS)
-{
- BEGIN_STUB_FUNCTION();
-
- JSValuePtr src1 = ARG_src1;
- JSValuePtr src2 = ARG_src2;
- CallFrame* callFrame = ARG_callFrame;
-
- bool result = jsLessEq(callFrame, src1, src2);
- CHECK_FOR_EXCEPTION_AT_END();
- return result;
-}
-
-JSObject* Interpreter::cti_op_new_object(STUB_ARGS)
-{
- BEGIN_STUB_FUNCTION();
-
- return constructEmptyObject(ARG_callFrame);
-}
-
-void Interpreter::cti_op_put_by_id_generic(STUB_ARGS)
-{
- BEGIN_STUB_FUNCTION();
-
- PutPropertySlot slot;
- ARG_src1.put(ARG_callFrame, *ARG_id2, ARG_src3, slot);
- CHECK_FOR_EXCEPTION_AT_END();
-}
-
-JSValueEncodedAsPointer* Interpreter::cti_op_get_by_id_generic(STUB_ARGS)
-{
- BEGIN_STUB_FUNCTION();
-
- CallFrame* callFrame = ARG_callFrame;
- Identifier& ident = *ARG_id2;
-
- JSValuePtr baseValue = ARG_src1;
- PropertySlot slot(baseValue);
- JSValuePtr result = baseValue.get(callFrame, ident, slot);
-
- CHECK_FOR_EXCEPTION_AT_END();
- return JSValuePtr::encode(result);
-}
-
-#if ENABLE(JIT_OPTIMIZE_PROPERTY_ACCESS)
-
-void Interpreter::cti_op_put_by_id(STUB_ARGS)
-{
- BEGIN_STUB_FUNCTION();
-
- CallFrame* callFrame = ARG_callFrame;
- Identifier& ident = *ARG_id2;
-
- PutPropertySlot slot;
- ARG_src1.put(callFrame, ident, ARG_src3, slot);
-
- ctiPatchCallByReturnAddress(STUB_RETURN_ADDRESS, reinterpret_cast<void*>(cti_op_put_by_id_second));
-
- CHECK_FOR_EXCEPTION_AT_END();
-}
-
-void Interpreter::cti_op_put_by_id_second(STUB_ARGS)
-{
- BEGIN_STUB_FUNCTION();
-
- PutPropertySlot slot;
- ARG_src1.put(ARG_callFrame, *ARG_id2, ARG_src3, slot);
- ARG_globalData->interpreter->tryCTICachePutByID(ARG_callFrame, ARG_callFrame->codeBlock(), STUB_RETURN_ADDRESS, ARG_src1, slot);
- CHECK_FOR_EXCEPTION_AT_END();
-}
-
-void Interpreter::cti_op_put_by_id_fail(STUB_ARGS)
-{
- BEGIN_STUB_FUNCTION();
-
- CallFrame* callFrame = ARG_callFrame;
- Identifier& ident = *ARG_id2;
-
- PutPropertySlot slot;
- ARG_src1.put(callFrame, ident, ARG_src3, slot);
-
- CHECK_FOR_EXCEPTION_AT_END();
-}
-
-JSValueEncodedAsPointer* Interpreter::cti_op_get_by_id(STUB_ARGS)
-{
- BEGIN_STUB_FUNCTION();
-
- CallFrame* callFrame = ARG_callFrame;
- Identifier& ident = *ARG_id2;
-
- JSValuePtr baseValue = ARG_src1;
- PropertySlot slot(baseValue);
- JSValuePtr result = baseValue.get(callFrame, ident, slot);
-
- ctiPatchCallByReturnAddress(STUB_RETURN_ADDRESS, reinterpret_cast<void*>(cti_op_get_by_id_second));
-
- CHECK_FOR_EXCEPTION_AT_END();
- return JSValuePtr::encode(result);
-}
-
-JSValueEncodedAsPointer* Interpreter::cti_op_get_by_id_second(STUB_ARGS)
-{
- BEGIN_STUB_FUNCTION();
-
- CallFrame* callFrame = ARG_callFrame;
- Identifier& ident = *ARG_id2;
-
- JSValuePtr baseValue = ARG_src1;
- PropertySlot slot(baseValue);
- JSValuePtr result = baseValue.get(callFrame, ident, slot);
-
- ARG_globalData->interpreter->tryCTICacheGetByID(callFrame, callFrame->codeBlock(), STUB_RETURN_ADDRESS, baseValue, ident, slot);
-
- CHECK_FOR_EXCEPTION_AT_END();
- return JSValuePtr::encode(result);
-}
-
-JSValueEncodedAsPointer* Interpreter::cti_op_get_by_id_self_fail(STUB_ARGS)
-{
- BEGIN_STUB_FUNCTION();
-
- CallFrame* callFrame = ARG_callFrame;
- Identifier& ident = *ARG_id2;
-
- JSValuePtr baseValue = ARG_src1;
- PropertySlot slot(baseValue);
- JSValuePtr result = baseValue.get(callFrame, ident, slot);
-
- CHECK_FOR_EXCEPTION();
-
- if (baseValue.isCell()
- && slot.isCacheable()
- && !asCell(baseValue)->structure()->isDictionary()
- && slot.slotBase() == baseValue) {
-
- CodeBlock* codeBlock = callFrame->codeBlock();
- StructureStubInfo* stubInfo = &codeBlock->getStubInfo(STUB_RETURN_ADDRESS);
-
- ASSERT(slot.slotBase().isObject());
-
- PolymorphicAccessStructureList* polymorphicStructureList;
- int listIndex = 1;
-
- if (stubInfo->opcodeID == op_get_by_id_self) {
- ASSERT(!stubInfo->stubRoutine);
- polymorphicStructureList = new PolymorphicAccessStructureList(0, stubInfo->u.getByIdSelf.baseObjectStructure);
- stubInfo->initGetByIdSelfList(polymorphicStructureList, 2);
- } else {
- polymorphicStructureList = stubInfo->u.getByIdSelfList.structureList;
- listIndex = stubInfo->u.getByIdSelfList.listSize;
- stubInfo->u.getByIdSelfList.listSize++;
- }
-
- JIT::compileGetByIdSelfList(callFrame->scopeChain()->globalData, codeBlock, stubInfo, polymorphicStructureList, listIndex, asCell(baseValue)->structure(), slot.cachedOffset());
-
- if (listIndex == (POLYMORPHIC_LIST_CACHE_SIZE - 1))
- ctiPatchCallByReturnAddress(STUB_RETURN_ADDRESS, reinterpret_cast<void*>(cti_op_get_by_id_generic));
- } else {
- ctiPatchCallByReturnAddress(STUB_RETURN_ADDRESS, reinterpret_cast<void*>(cti_op_get_by_id_generic));
- }
- return JSValuePtr::encode(result);
-}
-
-static PolymorphicAccessStructureList* getPolymorphicAccessStructureListSlot(StructureStubInfo* stubInfo, int& listIndex)
-{
- PolymorphicAccessStructureList* prototypeStructureList = 0;
- listIndex = 1;
-
- switch (stubInfo->opcodeID) {
- case op_get_by_id_proto:
- prototypeStructureList = new PolymorphicAccessStructureList(stubInfo->stubRoutine, stubInfo->u.getByIdProto.baseObjectStructure, stubInfo->u.getByIdProto.prototypeStructure);
- stubInfo->stubRoutine = 0;
- stubInfo->initGetByIdProtoList(prototypeStructureList, 2);
- break;
- case op_get_by_id_chain:
- prototypeStructureList = new PolymorphicAccessStructureList(stubInfo->stubRoutine, stubInfo->u.getByIdChain.baseObjectStructure, stubInfo->u.getByIdChain.chain);
- stubInfo->stubRoutine = 0;
- stubInfo->initGetByIdProtoList(prototypeStructureList, 2);
- break;
- case op_get_by_id_proto_list:
- prototypeStructureList = stubInfo->u.getByIdProtoList.structureList;
- listIndex = stubInfo->u.getByIdProtoList.listSize;
- stubInfo->u.getByIdProtoList.listSize++;
- break;
- default:
- ASSERT_NOT_REACHED();
- }
-
- ASSERT(listIndex < POLYMORPHIC_LIST_CACHE_SIZE);
- return prototypeStructureList;
-}
-
-JSValueEncodedAsPointer* Interpreter::cti_op_get_by_id_proto_list(STUB_ARGS)
-{
- BEGIN_STUB_FUNCTION();
-
- CallFrame* callFrame = ARG_callFrame;
-
- JSValuePtr baseValue = ARG_src1;
- PropertySlot slot(baseValue);
- JSValuePtr result = baseValue.get(callFrame, *ARG_id2, slot);
-
- CHECK_FOR_EXCEPTION();
-
- if (!baseValue.isCell() || !slot.isCacheable() || asCell(baseValue)->structure()->isDictionary()) {
- ctiPatchCallByReturnAddress(STUB_RETURN_ADDRESS, reinterpret_cast<void*>(cti_op_get_by_id_proto_fail));
- return JSValuePtr::encode(result);
- }
-
- Structure* structure = asCell(baseValue)->structure();
- CodeBlock* codeBlock = callFrame->codeBlock();
- StructureStubInfo* stubInfo = &codeBlock->getStubInfo(STUB_RETURN_ADDRESS);
-
- ASSERT(slot.slotBase().isObject());
- JSObject* slotBaseObject = asObject(slot.slotBase());
-
- if (slot.slotBase() == baseValue)
- ctiPatchCallByReturnAddress(STUB_RETURN_ADDRESS, reinterpret_cast<void*>(cti_op_get_by_id_proto_fail));
- else if (slot.slotBase() == asCell(baseValue)->structure()->prototypeForLookup(callFrame)) {
- // Since we're accessing a prototype in a loop, it's a good bet that it
- // should not be treated as a dictionary.
- if (slotBaseObject->structure()->isDictionary()) {
- RefPtr<Structure> transition = Structure::fromDictionaryTransition(slotBaseObject->structure());
- slotBaseObject->setStructure(transition.release());
- asCell(baseValue)->structure()->setCachedPrototypeChain(0);
- }
-
- int listIndex;
- PolymorphicAccessStructureList* prototypeStructureList = getPolymorphicAccessStructureListSlot(stubInfo, listIndex);
-
- JIT::compileGetByIdProtoList(callFrame->scopeChain()->globalData, callFrame, codeBlock, stubInfo, prototypeStructureList, listIndex, structure, slotBaseObject->structure(), slot.cachedOffset());
-
- if (listIndex == (POLYMORPHIC_LIST_CACHE_SIZE - 1))
- ctiPatchCallByReturnAddress(STUB_RETURN_ADDRESS, reinterpret_cast<void*>(cti_op_get_by_id_proto_list_full));
- } else if (size_t count = countPrototypeChainEntriesAndCheckForProxies(callFrame, baseValue, slot)) {
- StructureChain* chain = structure->cachedPrototypeChain();
- if (!chain)
- chain = cachePrototypeChain(callFrame, structure);
- ASSERT(chain);
-
- int listIndex;
- PolymorphicAccessStructureList* prototypeStructureList = getPolymorphicAccessStructureListSlot(stubInfo, listIndex);
-
- JIT::compileGetByIdChainList(callFrame->scopeChain()->globalData, callFrame, codeBlock, stubInfo, prototypeStructureList, listIndex, structure, chain, count, slot.cachedOffset());
-
- if (listIndex == (POLYMORPHIC_LIST_CACHE_SIZE - 1))
- ctiPatchCallByReturnAddress(STUB_RETURN_ADDRESS, reinterpret_cast<void*>(cti_op_get_by_id_proto_list_full));
- } else
- ctiPatchCallByReturnAddress(STUB_RETURN_ADDRESS, reinterpret_cast<void*>(cti_op_get_by_id_proto_fail));
-
- return JSValuePtr::encode(result);
-}
-
-JSValueEncodedAsPointer* Interpreter::cti_op_get_by_id_proto_list_full(STUB_ARGS)
-{
- BEGIN_STUB_FUNCTION();
-
- JSValuePtr baseValue = ARG_src1;
- PropertySlot slot(baseValue);
- JSValuePtr result = baseValue.get(ARG_callFrame, *ARG_id2, slot);
-
- CHECK_FOR_EXCEPTION_AT_END();
- return JSValuePtr::encode(result);
-}
-
-JSValueEncodedAsPointer* Interpreter::cti_op_get_by_id_proto_fail(STUB_ARGS)
-{
- BEGIN_STUB_FUNCTION();
-
- JSValuePtr baseValue = ARG_src1;
- PropertySlot slot(baseValue);
- JSValuePtr result = baseValue.get(ARG_callFrame, *ARG_id2, slot);
-
- CHECK_FOR_EXCEPTION_AT_END();
- return JSValuePtr::encode(result);
-}
-
-JSValueEncodedAsPointer* Interpreter::cti_op_get_by_id_array_fail(STUB_ARGS)
-{
- BEGIN_STUB_FUNCTION();
-
- JSValuePtr baseValue = ARG_src1;
- PropertySlot slot(baseValue);
- JSValuePtr result = baseValue.get(ARG_callFrame, *ARG_id2, slot);
-
- CHECK_FOR_EXCEPTION_AT_END();
- return JSValuePtr::encode(result);
-}
-
-JSValueEncodedAsPointer* Interpreter::cti_op_get_by_id_string_fail(STUB_ARGS)
-{
- BEGIN_STUB_FUNCTION();
-
- JSValuePtr baseValue = ARG_src1;
- PropertySlot slot(baseValue);
- JSValuePtr result = baseValue.get(ARG_callFrame, *ARG_id2, slot);
-
- CHECK_FOR_EXCEPTION_AT_END();
- return JSValuePtr::encode(result);
-}
-
-#endif
-
-JSValueEncodedAsPointer* Interpreter::cti_op_instanceof(STUB_ARGS)
-{
- BEGIN_STUB_FUNCTION();
-
- CallFrame* callFrame = ARG_callFrame;
- JSValuePtr value = ARG_src1;
- JSValuePtr baseVal = ARG_src2;
- JSValuePtr proto = ARG_src3;
-
- // at least one of these checks must have failed to get to the slow case
- ASSERT(!value.isCell() || !baseVal.isCell() || !proto.isCell()
- || !value.isObject() || !baseVal.isObject() || !proto.isObject()
- || (asObject(baseVal)->structure()->typeInfo().flags() & (ImplementsHasInstance | OverridesHasInstance)) != ImplementsHasInstance);
-
- if (!baseVal.isObject()) {
- CallFrame* callFrame = ARG_callFrame;
- CodeBlock* codeBlock = callFrame->codeBlock();
- unsigned vPCIndex = codeBlock->getBytecodeIndex(callFrame, STUB_RETURN_ADDRESS);
- ARG_globalData->exception = createInvalidParamError(callFrame, "instanceof", baseVal, vPCIndex, codeBlock);
- VM_THROW_EXCEPTION();
- }
-
- if (!asObject(baseVal)->structure()->typeInfo().implementsHasInstance())
- return JSValuePtr::encode(jsBoolean(false));
-
- if (!proto.isObject()) {
- throwError(callFrame, TypeError, "instanceof called on an object with an invalid prototype property.");
- VM_THROW_EXCEPTION();
- }
-
- if (!value.isObject())
- return JSValuePtr::encode(jsBoolean(false));
-
- JSValuePtr result = jsBoolean(asObject(baseVal)->hasInstance(callFrame, value, proto));
- CHECK_FOR_EXCEPTION_AT_END();
-
- return JSValuePtr::encode(result);
-}
-
-JSValueEncodedAsPointer* Interpreter::cti_op_del_by_id(STUB_ARGS)
-{
- BEGIN_STUB_FUNCTION();
-
- CallFrame* callFrame = ARG_callFrame;
-
- JSObject* baseObj = ARG_src1.toObject(callFrame);
-
- JSValuePtr result = jsBoolean(baseObj->deleteProperty(callFrame, *ARG_id2));
- CHECK_FOR_EXCEPTION_AT_END();
- return JSValuePtr::encode(result);
-}
-
-JSValueEncodedAsPointer* Interpreter::cti_op_mul(STUB_ARGS)
-{
- BEGIN_STUB_FUNCTION();
-
- JSValuePtr src1 = ARG_src1;
- JSValuePtr src2 = ARG_src2;
-
- double left;
- double right;
- if (src1.getNumber(left) && src2.getNumber(right))
- return JSValuePtr::encode(jsNumber(ARG_globalData, left * right));
-
- CallFrame* callFrame = ARG_callFrame;
- JSValuePtr result = jsNumber(ARG_globalData, src1.toNumber(callFrame) * src2.toNumber(callFrame));
- CHECK_FOR_EXCEPTION_AT_END();
- return JSValuePtr::encode(result);
-}
-
-JSObject* Interpreter::cti_op_new_func(STUB_ARGS)
-{
- BEGIN_STUB_FUNCTION();
-
- return ARG_func1->makeFunction(ARG_callFrame, ARG_callFrame->scopeChain());
-}
-
-void* Interpreter::cti_op_call_JSFunction(STUB_ARGS)
-{
- BEGIN_STUB_FUNCTION();
-
-#ifndef NDEBUG
- CallData callData;
- ASSERT(ARG_src1.getCallData(callData) == CallTypeJS);
-#endif
-
- ScopeChainNode* callDataScopeChain = asFunction(ARG_src1)->m_scopeChain.node();
- CodeBlock* newCodeBlock = &asFunction(ARG_src1)->body()->bytecode(callDataScopeChain);
-
- if (!newCodeBlock->jitCode())
- JIT::compile(ARG_globalData, newCodeBlock);
-
- return newCodeBlock;
-}
-
-VoidPtrPair Interpreter::cti_op_call_arityCheck(STUB_ARGS)
-{
- BEGIN_STUB_FUNCTION();
-
- CallFrame* callFrame = ARG_callFrame;
- CodeBlock* newCodeBlock = ARG_codeBlock4;
- int argCount = ARG_int3;
-
- ASSERT(argCount != newCodeBlock->m_numParameters);
-
- CallFrame* oldCallFrame = callFrame->callerFrame();
-
- if (argCount > newCodeBlock->m_numParameters) {
- size_t numParameters = newCodeBlock->m_numParameters;
- Register* r = callFrame->registers() + numParameters;
-
- Register* argv = r - RegisterFile::CallFrameHeaderSize - numParameters - argCount;
- for (size_t i = 0; i < numParameters; ++i)
- argv[i + argCount] = argv[i];
-
- callFrame = CallFrame::create(r);
- callFrame->setCallerFrame(oldCallFrame);
- } else {
- size_t omittedArgCount = newCodeBlock->m_numParameters - argCount;
- Register* r = callFrame->registers() + omittedArgCount;
- Register* newEnd = r + newCodeBlock->m_numCalleeRegisters;
- if (!ARG_registerFile->grow(newEnd)) {
- // Rewind to the previous call frame because op_call already optimistically
- // moved the call frame forward.
- ARG_setCallFrame(oldCallFrame);
- throwStackOverflowError(oldCallFrame, ARG_globalData, ARG_returnAddress2, STUB_RETURN_ADDRESS);
- RETURN_PAIR(0, 0);
- }
-
- Register* argv = r - RegisterFile::CallFrameHeaderSize - omittedArgCount;
- for (size_t i = 0; i < omittedArgCount; ++i)
- argv[i] = jsUndefined();
-
- callFrame = CallFrame::create(r);
- callFrame->setCallerFrame(oldCallFrame);
- }
-
- RETURN_PAIR(newCodeBlock, callFrame);
-}
-
-void* Interpreter::cti_vm_dontLazyLinkCall(STUB_ARGS)
-{
- BEGIN_STUB_FUNCTION();
-
- JSFunction* callee = asFunction(ARG_src1);
- CodeBlock* codeBlock = &callee->body()->bytecode(callee->m_scopeChain.node());
- if (!codeBlock->jitCode())
- JIT::compile(ARG_globalData, codeBlock);
-
- ctiPatchCallByReturnAddress(ARG_returnAddress2, ARG_globalData->interpreter->m_ctiVirtualCallLink);
-
- return codeBlock->jitCode();
-}
-
-void* Interpreter::cti_vm_lazyLinkCall(STUB_ARGS)
-{
- BEGIN_STUB_FUNCTION();
-
- JSFunction* callee = asFunction(ARG_src1);
- CodeBlock* codeBlock = &callee->body()->bytecode(callee->m_scopeChain.node());
- if (!codeBlock->jitCode())
- JIT::compile(ARG_globalData, codeBlock);
-
- CallLinkInfo* callLinkInfo = &ARG_callFrame->callerFrame()->codeBlock()->getCallLinkInfo(ARG_returnAddress2);
- JIT::linkCall(callee, codeBlock, codeBlock->jitCode(), callLinkInfo, ARG_int3);
-
- return codeBlock->jitCode();
-}
-
-JSObject* Interpreter::cti_op_push_activation(STUB_ARGS)
-{
- BEGIN_STUB_FUNCTION();
-
- JSActivation* activation = new (ARG_globalData) JSActivation(ARG_callFrame, static_cast<FunctionBodyNode*>(ARG_callFrame->codeBlock()->ownerNode()));
- ARG_callFrame->setScopeChain(ARG_callFrame->scopeChain()->copy()->push(activation));
- return activation;
-}
-
-JSValueEncodedAsPointer* Interpreter::cti_op_call_NotJSFunction(STUB_ARGS)
-{
- BEGIN_STUB_FUNCTION();
-
- JSValuePtr funcVal = ARG_src1;
-
- CallData callData;
- CallType callType = funcVal.getCallData(callData);
-
- ASSERT(callType != CallTypeJS);
-
- if (callType == CallTypeHost) {
- int registerOffset = ARG_int2;
- int argCount = ARG_int3;
- CallFrame* previousCallFrame = ARG_callFrame;
- CallFrame* callFrame = CallFrame::create(previousCallFrame->registers() + registerOffset);
-
- callFrame->init(0, static_cast<Instruction*>(STUB_RETURN_ADDRESS), previousCallFrame->scopeChain(), previousCallFrame, 0, argCount, 0);
- ARG_setCallFrame(callFrame);
-
- Register* argv = ARG_callFrame->registers() - RegisterFile::CallFrameHeaderSize - argCount;
- ArgList argList(argv + 1, argCount - 1);
-
- JSValuePtr returnValue;
- {
- SamplingTool::HostCallRecord callRecord(CTI_SAMPLER);
-
- // FIXME: All host methods should be calling toThisObject, but this is not presently the case.
- JSValuePtr thisValue = argv[0].jsValue(callFrame);
- if (thisValue == jsNull())
- thisValue = callFrame->globalThisValue();
-
- returnValue = callData.native.function(callFrame, asObject(funcVal), thisValue, argList);
- }
- ARG_setCallFrame(previousCallFrame);
- CHECK_FOR_EXCEPTION();
-
- return JSValuePtr::encode(returnValue);
- }
-
- ASSERT(callType == CallTypeNone);
-
- CallFrame* callFrame = ARG_callFrame;
- CodeBlock* codeBlock = callFrame->codeBlock();
- unsigned vPCIndex = codeBlock->getBytecodeIndex(callFrame, STUB_RETURN_ADDRESS);
- ARG_globalData->exception = createNotAFunctionError(ARG_callFrame, funcVal, vPCIndex, codeBlock);
- VM_THROW_EXCEPTION();
-}
-
-void Interpreter::cti_op_create_arguments(STUB_ARGS)
-{
- BEGIN_STUB_FUNCTION();
-
- Arguments* arguments = new (ARG_globalData) Arguments(ARG_callFrame);
- ARG_callFrame->setCalleeArguments(arguments);
- ARG_callFrame[RegisterFile::ArgumentsRegister] = arguments;
-}
-
-void Interpreter::cti_op_create_arguments_no_params(STUB_ARGS)
-{
- BEGIN_STUB_FUNCTION();
-
- Arguments* arguments = new (ARG_globalData) Arguments(ARG_callFrame, Arguments::NoParameters);
- ARG_callFrame->setCalleeArguments(arguments);
- ARG_callFrame[RegisterFile::ArgumentsRegister] = arguments;
-}
-
-void Interpreter::cti_op_tear_off_activation(STUB_ARGS)
-{
- BEGIN_STUB_FUNCTION();
-
- ASSERT(ARG_callFrame->codeBlock()->needsFullScopeChain());
- asActivation(ARG_src1)->copyRegisters(ARG_callFrame->optionalCalleeArguments());
-}
-
-void Interpreter::cti_op_tear_off_arguments(STUB_ARGS)
-{
- BEGIN_STUB_FUNCTION();
-
- ASSERT(ARG_callFrame->codeBlock()->usesArguments() && !ARG_callFrame->codeBlock()->needsFullScopeChain());
- ARG_callFrame->optionalCalleeArguments()->copyRegisters();
-}
-
-void Interpreter::cti_op_profile_will_call(STUB_ARGS)
-{
- BEGIN_STUB_FUNCTION();
-
- ASSERT(*ARG_profilerReference);
- (*ARG_profilerReference)->willExecute(ARG_callFrame, ARG_src1);
-}
-
-void Interpreter::cti_op_profile_did_call(STUB_ARGS)
-{
- BEGIN_STUB_FUNCTION();
-
- ASSERT(*ARG_profilerReference);
- (*ARG_profilerReference)->didExecute(ARG_callFrame, ARG_src1);
-}
-
-void Interpreter::cti_op_ret_scopeChain(STUB_ARGS)
-{
- BEGIN_STUB_FUNCTION();
-
- ASSERT(ARG_callFrame->codeBlock()->needsFullScopeChain());
- ARG_callFrame->scopeChain()->deref();
-}
-
-JSObject* Interpreter::cti_op_new_array(STUB_ARGS)
-{
- BEGIN_STUB_FUNCTION();
-
- ArgList argList(&ARG_callFrame->registers()[ARG_int1], ARG_int2);
- return constructArray(ARG_callFrame, argList);
-}
-
-JSValueEncodedAsPointer* Interpreter::cti_op_resolve(STUB_ARGS)
-{
- BEGIN_STUB_FUNCTION();
-
- CallFrame* callFrame = ARG_callFrame;
- ScopeChainNode* scopeChain = callFrame->scopeChain();
-
- ScopeChainIterator iter = scopeChain->begin();
- ScopeChainIterator end = scopeChain->end();
- ASSERT(iter != end);
-
- Identifier& ident = *ARG_id1;
- do {
- JSObject* o = *iter;
- PropertySlot slot(o);
- if (o->getPropertySlot(callFrame, ident, slot)) {
- JSValuePtr result = slot.getValue(callFrame, ident);
- CHECK_FOR_EXCEPTION_AT_END();
- return JSValuePtr::encode(result);
- }
- } while (++iter != end);
-
- CodeBlock* codeBlock = callFrame->codeBlock();
- unsigned vPCIndex = codeBlock->getBytecodeIndex(callFrame, STUB_RETURN_ADDRESS);
- ARG_globalData->exception = createUndefinedVariableError(callFrame, ident, vPCIndex, codeBlock);
- VM_THROW_EXCEPTION();
-}
-
-JSObject* Interpreter::cti_op_construct_JSConstruct(STUB_ARGS)
-{
- BEGIN_STUB_FUNCTION();
-
-#ifndef NDEBUG
- ConstructData constructData;
- ASSERT(asFunction(ARG_src1)->getConstructData(constructData) == ConstructTypeJS);
-#endif
-
- Structure* structure;
- if (ARG_src4.isObject())
- structure = asObject(ARG_src4)->inheritorID();
- else
- structure = asFunction(ARG_src1)->m_scopeChain.node()->globalObject()->emptyObjectStructure();
- return new (ARG_globalData) JSObject(structure);
-}
-
-JSValueEncodedAsPointer* Interpreter::cti_op_construct_NotJSConstruct(STUB_ARGS)
-{
- BEGIN_STUB_FUNCTION();
-
- CallFrame* callFrame = ARG_callFrame;
-
- JSValuePtr constrVal = ARG_src1;
- int argCount = ARG_int3;
- int thisRegister = ARG_int5;
-
- ConstructData constructData;
- ConstructType constructType = constrVal.getConstructData(constructData);
-
- if (constructType == ConstructTypeHost) {
- ArgList argList(callFrame->registers() + thisRegister + 1, argCount - 1);
-
- JSValuePtr returnValue;
- {
- SamplingTool::HostCallRecord callRecord(CTI_SAMPLER);
- returnValue = constructData.native.function(callFrame, asObject(constrVal), argList);
- }
- CHECK_FOR_EXCEPTION();
-
- return JSValuePtr::encode(returnValue);
- }
-
- ASSERT(constructType == ConstructTypeNone);
-
- CodeBlock* codeBlock = callFrame->codeBlock();
- unsigned vPCIndex = codeBlock->getBytecodeIndex(callFrame, STUB_RETURN_ADDRESS);
- ARG_globalData->exception = createNotAConstructorError(callFrame, constrVal, vPCIndex, codeBlock);
- VM_THROW_EXCEPTION();
-}
-
-JSValueEncodedAsPointer* Interpreter::cti_op_get_by_val(STUB_ARGS)
-{
- BEGIN_STUB_FUNCTION();
-
- CallFrame* callFrame = ARG_callFrame;
- Interpreter* interpreter = ARG_globalData->interpreter;
-
- JSValuePtr baseValue = ARG_src1;
- JSValuePtr subscript = ARG_src2;
-
- JSValuePtr result;
-
- if (LIKELY(subscript.isUInt32Fast())) {
- uint32_t i = subscript.getUInt32Fast();
- if (interpreter->isJSArray(baseValue)) {
- JSArray* jsArray = asArray(baseValue);
- if (jsArray->canGetIndex(i))
- result = jsArray->getIndex(i);
- else
- result = jsArray->JSArray::get(callFrame, i);
- } else if (interpreter->isJSString(baseValue) && asString(baseValue)->canGetIndex(i))
- result = asString(baseValue)->getIndex(ARG_globalData, i);
- else if (interpreter->isJSByteArray(baseValue) && asByteArray(baseValue)->canAccessIndex(i)) {
- // All fast byte array accesses are safe from exceptions so return immediately to avoid exception checks.
- ctiPatchCallByReturnAddress(STUB_RETURN_ADDRESS, reinterpret_cast<void*>(cti_op_get_by_val_byte_array));
- return JSValuePtr::encode(asByteArray(baseValue)->getIndex(callFrame, i));
- } else
- result = baseValue.get(callFrame, i);
- } else {
- Identifier property(callFrame, subscript.toString(callFrame));
- result = baseValue.get(callFrame, property);
- }
-
- CHECK_FOR_EXCEPTION_AT_END();
- return JSValuePtr::encode(result);
-}
-
-JSValueEncodedAsPointer* Interpreter::cti_op_get_by_val_byte_array(STUB_ARGS)
-{
- BEGIN_STUB_FUNCTION();
-
- CallFrame* callFrame = ARG_callFrame;
- Interpreter* interpreter = ARG_globalData->interpreter;
-
- JSValuePtr baseValue = ARG_src1;
- JSValuePtr subscript = ARG_src2;
-
- JSValuePtr result;
-
- if (LIKELY(subscript.isUInt32Fast())) {
- uint32_t i = subscript.getUInt32Fast();
- if (interpreter->isJSByteArray(baseValue) && asByteArray(baseValue)->canAccessIndex(i)) {
- // All fast byte array accesses are safe from exceptions so return immediately to avoid exception checks.
- return JSValuePtr::encode(asByteArray(baseValue)->getIndex(callFrame, i));
- }
-
- result = baseValue.get(callFrame, i);
- if (!interpreter->isJSByteArray(baseValue))
- ctiPatchCallByReturnAddress(STUB_RETURN_ADDRESS, reinterpret_cast<void*>(cti_op_get_by_val));
- } else {
- Identifier property(callFrame, subscript.toString(callFrame));
- result = baseValue.get(callFrame, property);
- }
-
- CHECK_FOR_EXCEPTION_AT_END();
- return JSValuePtr::encode(result);
-}
-
-VoidPtrPair Interpreter::cti_op_resolve_func(STUB_ARGS)
-{
- BEGIN_STUB_FUNCTION();
-
- CallFrame* callFrame = ARG_callFrame;
- ScopeChainNode* scopeChain = callFrame->scopeChain();
-
- ScopeChainIterator iter = scopeChain->begin();
- ScopeChainIterator end = scopeChain->end();
-
- // FIXME: add scopeDepthIsZero optimization
-
- ASSERT(iter != end);
-
- Identifier& ident = *ARG_id1;
- JSObject* base;
- do {
- base = *iter;
- PropertySlot slot(base);
- if (base->getPropertySlot(callFrame, ident, slot)) {
- // ECMA 11.2.3 says that if we hit an activation the this value should be null.
- // However, section 10.2.3 says that in the case where the value provided
- // by the caller is null, the global object should be used. It also says
- // that the section does not apply to internal functions, but for simplicity
- // of implementation we use the global object anyway here. This guarantees
- // that in host objects you always get a valid object for this.
- // We also handle wrapper substitution for the global object at the same time.
- JSObject* thisObj = base->toThisObject(callFrame);
- JSValuePtr result = slot.getValue(callFrame, ident);
- CHECK_FOR_EXCEPTION_AT_END();
-
- RETURN_PAIR(thisObj, JSValuePtr::encode(result));
- }
- ++iter;
- } while (iter != end);
-
- CodeBlock* codeBlock = callFrame->codeBlock();
- unsigned vPCIndex = codeBlock->getBytecodeIndex(callFrame, STUB_RETURN_ADDRESS);
- ARG_globalData->exception = createUndefinedVariableError(callFrame, ident, vPCIndex, codeBlock);
- VM_THROW_EXCEPTION_2();
-}
-
-JSValueEncodedAsPointer* Interpreter::cti_op_sub(STUB_ARGS)
-{
- BEGIN_STUB_FUNCTION();
-
- JSValuePtr src1 = ARG_src1;
- JSValuePtr src2 = ARG_src2;
-
- double left;
- double right;
- if (src1.getNumber(left) && src2.getNumber(right))
- return JSValuePtr::encode(jsNumber(ARG_globalData, left - right));
-
- CallFrame* callFrame = ARG_callFrame;
- JSValuePtr result = jsNumber(ARG_globalData, src1.toNumber(callFrame) - src2.toNumber(callFrame));
- CHECK_FOR_EXCEPTION_AT_END();
- return JSValuePtr::encode(result);
-}
-
-void Interpreter::cti_op_put_by_val(STUB_ARGS)
-{
- BEGIN_STUB_FUNCTION();
-
- CallFrame* callFrame = ARG_callFrame;
- Interpreter* interpreter = ARG_globalData->interpreter;
-
- JSValuePtr baseValue = ARG_src1;
- JSValuePtr subscript = ARG_src2;
- JSValuePtr value = ARG_src3;
-
- if (LIKELY(subscript.isUInt32Fast())) {
- uint32_t i = subscript.getUInt32Fast();
- if (interpreter->isJSArray(baseValue)) {
- JSArray* jsArray = asArray(baseValue);
- if (jsArray->canSetIndex(i))
- jsArray->setIndex(i, value);
- else
- jsArray->JSArray::put(callFrame, i, value);
- } else if (interpreter->isJSByteArray(baseValue) && asByteArray(baseValue)->canAccessIndex(i)) {
- JSByteArray* jsByteArray = asByteArray(baseValue);
- ctiPatchCallByReturnAddress(STUB_RETURN_ADDRESS, reinterpret_cast<void*>(cti_op_put_by_val_byte_array));
- // All fast byte array accesses are safe from exceptions so return immediately to avoid exception checks.
- if (value.isInt32Fast()) {
- jsByteArray->setIndex(i, value.getInt32Fast());
- return;
- } else {
- double dValue = 0;
- if (value.getNumber(dValue)) {
- jsByteArray->setIndex(i, dValue);
- return;
- }
- }
-
- baseValue.put(callFrame, i, value);
- } else
- baseValue.put(callFrame, i, value);
- } else {
- Identifier property(callFrame, subscript.toString(callFrame));
- if (!ARG_globalData->exception) { // Don't put to an object if toString threw an exception.
- PutPropertySlot slot;
- baseValue.put(callFrame, property, value, slot);
- }
- }
-
- CHECK_FOR_EXCEPTION_AT_END();
-}
-
-void Interpreter::cti_op_put_by_val_array(STUB_ARGS)
-{
- BEGIN_STUB_FUNCTION();
-
- CallFrame* callFrame = ARG_callFrame;
-
- JSValuePtr baseValue = ARG_src1;
- int i = ARG_int2;
- JSValuePtr value = ARG_src3;
-
- ASSERT(ARG_globalData->interpreter->isJSArray(baseValue));
-
- if (LIKELY(i >= 0))
- asArray(baseValue)->JSArray::put(callFrame, i, value);
- else {
- // This should work since we're re-boxing an immediate unboxed in JIT code.
- ASSERT(JSValuePtr::makeInt32Fast(i));
- Identifier property(callFrame, JSValuePtr::makeInt32Fast(i).toString(callFrame));
- // FIXME: can toString throw an exception here?
- if (!ARG_globalData->exception) { // Don't put to an object if toString threw an exception.
- PutPropertySlot slot;
- baseValue.put(callFrame, property, value, slot);
- }
- }
-
- CHECK_FOR_EXCEPTION_AT_END();
-}
-
-void Interpreter::cti_op_put_by_val_byte_array(STUB_ARGS)
-{
- BEGIN_STUB_FUNCTION();
-
- CallFrame* callFrame = ARG_callFrame;
- Interpreter* interpreter = ARG_globalData->interpreter;
-
- JSValuePtr baseValue = ARG_src1;
- JSValuePtr subscript = ARG_src2;
- JSValuePtr value = ARG_src3;
-
- if (LIKELY(subscript.isUInt32Fast())) {
- uint32_t i = subscript.getUInt32Fast();
- if (interpreter->isJSByteArray(baseValue) && asByteArray(baseValue)->canAccessIndex(i)) {
- JSByteArray* jsByteArray = asByteArray(baseValue);
-
- // All fast byte array accesses are safe from exceptions so return immediately to avoid exception checks.
- if (value.isInt32Fast()) {
- jsByteArray->setIndex(i, value.getInt32Fast());
- return;
- } else {
- double dValue = 0;
- if (value.getNumber(dValue)) {
- jsByteArray->setIndex(i, dValue);
- return;
- }
- }
- }
-
- if (!interpreter->isJSByteArray(baseValue))
- ctiPatchCallByReturnAddress(STUB_RETURN_ADDRESS, reinterpret_cast<void*>(cti_op_put_by_val));
- baseValue.put(callFrame, i, value);
- } else {
- Identifier property(callFrame, subscript.toString(callFrame));
- if (!ARG_globalData->exception) { // Don't put to an object if toString threw an exception.
- PutPropertySlot slot;
- baseValue.put(callFrame, property, value, slot);
- }
- }
-
- CHECK_FOR_EXCEPTION_AT_END();
-}
-
-JSValueEncodedAsPointer* Interpreter::cti_op_lesseq(STUB_ARGS)
-{
- BEGIN_STUB_FUNCTION();
-
- CallFrame* callFrame = ARG_callFrame;
- JSValuePtr result = jsBoolean(jsLessEq(callFrame, ARG_src1, ARG_src2));
- CHECK_FOR_EXCEPTION_AT_END();
- return JSValuePtr::encode(result);
-}
-
-int Interpreter::cti_op_loop_if_true(STUB_ARGS)
-{
- BEGIN_STUB_FUNCTION();
-
- JSValuePtr src1 = ARG_src1;
-
- CallFrame* callFrame = ARG_callFrame;
-
- bool result = src1.toBoolean(callFrame);
- CHECK_FOR_EXCEPTION_AT_END();
- return result;
-}
-
-JSValueEncodedAsPointer* Interpreter::cti_op_negate(STUB_ARGS)
-{
- BEGIN_STUB_FUNCTION();
-
- JSValuePtr src = ARG_src1;
-
- double v;
- if (src.getNumber(v))
- return JSValuePtr::encode(jsNumber(ARG_globalData, -v));
-
- CallFrame* callFrame = ARG_callFrame;
- JSValuePtr result = jsNumber(ARG_globalData, -src.toNumber(callFrame));
- CHECK_FOR_EXCEPTION_AT_END();
- return JSValuePtr::encode(result);
-}
-
-JSValueEncodedAsPointer* Interpreter::cti_op_resolve_base(STUB_ARGS)
-{
- BEGIN_STUB_FUNCTION();
-
- return JSValuePtr::encode(inlineResolveBase(ARG_callFrame, *ARG_id1, ARG_callFrame->scopeChain()));
-}
-
-JSValueEncodedAsPointer* Interpreter::cti_op_resolve_skip(STUB_ARGS)
-{
- BEGIN_STUB_FUNCTION();
-
- CallFrame* callFrame = ARG_callFrame;
- ScopeChainNode* scopeChain = callFrame->scopeChain();
-
- int skip = ARG_int2;
-
- ScopeChainIterator iter = scopeChain->begin();
- ScopeChainIterator end = scopeChain->end();
- ASSERT(iter != end);
- while (skip--) {
- ++iter;
- ASSERT(iter != end);
- }
- Identifier& ident = *ARG_id1;
- do {
- JSObject* o = *iter;
- PropertySlot slot(o);
- if (o->getPropertySlot(callFrame, ident, slot)) {
- JSValuePtr result = slot.getValue(callFrame, ident);
- CHECK_FOR_EXCEPTION_AT_END();
- return JSValuePtr::encode(result);
- }
- } while (++iter != end);
-
- CodeBlock* codeBlock = callFrame->codeBlock();
- unsigned vPCIndex = codeBlock->getBytecodeIndex(callFrame, STUB_RETURN_ADDRESS);
- ARG_globalData->exception = createUndefinedVariableError(callFrame, ident, vPCIndex, codeBlock);
- VM_THROW_EXCEPTION();
-}
-
-JSValueEncodedAsPointer* Interpreter::cti_op_resolve_global(STUB_ARGS)
-{
- BEGIN_STUB_FUNCTION();
-
- CallFrame* callFrame = ARG_callFrame;
- JSGlobalObject* globalObject = asGlobalObject(ARG_src1);
- Identifier& ident = *ARG_id2;
- unsigned globalResolveInfoIndex = ARG_int3;
- ASSERT(globalObject->isGlobalObject());
-
- PropertySlot slot(globalObject);
- if (globalObject->getPropertySlot(callFrame, ident, slot)) {
- JSValuePtr result = slot.getValue(callFrame, ident);
- if (slot.isCacheable() && !globalObject->structure()->isDictionary()) {
- GlobalResolveInfo& globalResolveInfo = callFrame->codeBlock()->globalResolveInfo(globalResolveInfoIndex);
- if (globalResolveInfo.structure)
- globalResolveInfo.structure->deref();
- globalObject->structure()->ref();
- globalResolveInfo.structure = globalObject->structure();
- globalResolveInfo.offset = slot.cachedOffset();
- return JSValuePtr::encode(result);
- }
-
- CHECK_FOR_EXCEPTION_AT_END();
- return JSValuePtr::encode(result);
- }
-
- unsigned vPCIndex = callFrame->codeBlock()->getBytecodeIndex(callFrame, STUB_RETURN_ADDRESS);
- ARG_globalData->exception = createUndefinedVariableError(callFrame, ident, vPCIndex, callFrame->codeBlock());
- VM_THROW_EXCEPTION();
-}
-
-JSValueEncodedAsPointer* Interpreter::cti_op_div(STUB_ARGS)
-{
- BEGIN_STUB_FUNCTION();
-
- JSValuePtr src1 = ARG_src1;
- JSValuePtr src2 = ARG_src2;
-
- double left;
- double right;
- if (src1.getNumber(left) && src2.getNumber(right))
- return JSValuePtr::encode(jsNumber(ARG_globalData, left / right));
-
- CallFrame* callFrame = ARG_callFrame;
- JSValuePtr result = jsNumber(ARG_globalData, src1.toNumber(callFrame) / src2.toNumber(callFrame));
- CHECK_FOR_EXCEPTION_AT_END();
- return JSValuePtr::encode(result);
-}
-
-JSValueEncodedAsPointer* Interpreter::cti_op_pre_dec(STUB_ARGS)
-{
- BEGIN_STUB_FUNCTION();
-
- JSValuePtr v = ARG_src1;
-
- CallFrame* callFrame = ARG_callFrame;
- JSValuePtr result = jsNumber(ARG_globalData, v.toNumber(callFrame) - 1);
- CHECK_FOR_EXCEPTION_AT_END();
- return JSValuePtr::encode(result);
-}
-
-int Interpreter::cti_op_jless(STUB_ARGS)
-{
- BEGIN_STUB_FUNCTION();
-
- JSValuePtr src1 = ARG_src1;
- JSValuePtr src2 = ARG_src2;
- CallFrame* callFrame = ARG_callFrame;
-
- bool result = jsLess(callFrame, src1, src2);
- CHECK_FOR_EXCEPTION_AT_END();
- return result;
-}
-
-JSValueEncodedAsPointer* Interpreter::cti_op_not(STUB_ARGS)
-{
- BEGIN_STUB_FUNCTION();
-
- JSValuePtr src = ARG_src1;
-
- CallFrame* callFrame = ARG_callFrame;
-
- JSValuePtr result = jsBoolean(!src.toBoolean(callFrame));
- CHECK_FOR_EXCEPTION_AT_END();
- return JSValuePtr::encode(result);
-}
-
-int Interpreter::cti_op_jtrue(STUB_ARGS)
-{
- BEGIN_STUB_FUNCTION();
-
- JSValuePtr src1 = ARG_src1;
-
- CallFrame* callFrame = ARG_callFrame;
-
- bool result = src1.toBoolean(callFrame);
- CHECK_FOR_EXCEPTION_AT_END();
- return result;
-}
-
-VoidPtrPair Interpreter::cti_op_post_inc(STUB_ARGS)
-{
- BEGIN_STUB_FUNCTION();
-
- JSValuePtr v = ARG_src1;
-
- CallFrame* callFrame = ARG_callFrame;
-
- JSValuePtr number = v.toJSNumber(callFrame);
- CHECK_FOR_EXCEPTION_AT_END();
-
- RETURN_PAIR(JSValuePtr::encode(number), JSValuePtr::encode(jsNumber(ARG_globalData, number.uncheckedGetNumber() + 1)));
-}
-
-JSValueEncodedAsPointer* Interpreter::cti_op_eq(STUB_ARGS)
-{
- BEGIN_STUB_FUNCTION();
-
- JSValuePtr src1 = ARG_src1;
- JSValuePtr src2 = ARG_src2;
-
- CallFrame* callFrame = ARG_callFrame;
-
- ASSERT(!JSValuePtr::areBothInt32Fast(src1, src2));
- JSValuePtr result = jsBoolean(JSValuePtr::equalSlowCaseInline(callFrame, src1, src2));
- CHECK_FOR_EXCEPTION_AT_END();
- return JSValuePtr::encode(result);
-}
-
-JSValueEncodedAsPointer* Interpreter::cti_op_lshift(STUB_ARGS)
-{
- BEGIN_STUB_FUNCTION();
-
- JSValuePtr val = ARG_src1;
- JSValuePtr shift = ARG_src2;
-
- int32_t left;
- uint32_t right;
- if (JSValuePtr::areBothInt32Fast(val, shift))
- return JSValuePtr::encode(jsNumber(ARG_globalData, val.getInt32Fast() << (shift.getInt32Fast() & 0x1f)));
- if (val.numberToInt32(left) && shift.numberToUInt32(right))
- return JSValuePtr::encode(jsNumber(ARG_globalData, left << (right & 0x1f)));
-
- CallFrame* callFrame = ARG_callFrame;
- JSValuePtr result = jsNumber(ARG_globalData, (val.toInt32(callFrame)) << (shift.toUInt32(callFrame) & 0x1f));
- CHECK_FOR_EXCEPTION_AT_END();
- return JSValuePtr::encode(result);
-}
-
-JSValueEncodedAsPointer* Interpreter::cti_op_bitand(STUB_ARGS)
-{
- BEGIN_STUB_FUNCTION();
-
- JSValuePtr src1 = ARG_src1;
- JSValuePtr src2 = ARG_src2;
-
- int32_t left;
- int32_t right;
- if (src1.numberToInt32(left) && src2.numberToInt32(right))
- return JSValuePtr::encode(jsNumber(ARG_globalData, left & right));
-
- CallFrame* callFrame = ARG_callFrame;
- JSValuePtr result = jsNumber(ARG_globalData, src1.toInt32(callFrame) & src2.toInt32(callFrame));
- CHECK_FOR_EXCEPTION_AT_END();
- return JSValuePtr::encode(result);
-}
-
-JSValueEncodedAsPointer* Interpreter::cti_op_rshift(STUB_ARGS)
-{
- BEGIN_STUB_FUNCTION();
-
- JSValuePtr val = ARG_src1;
- JSValuePtr shift = ARG_src2;
-
- int32_t left;
- uint32_t right;
- if (JSFastMath::canDoFastRshift(val, shift))
- return JSValuePtr::encode(JSFastMath::rightShiftImmediateNumbers(val, shift));
- if (val.numberToInt32(left) && shift.numberToUInt32(right))
- return JSValuePtr::encode(jsNumber(ARG_globalData, left >> (right & 0x1f)));
-
- CallFrame* callFrame = ARG_callFrame;
- JSValuePtr result = jsNumber(ARG_globalData, (val.toInt32(callFrame)) >> (shift.toUInt32(callFrame) & 0x1f));
- CHECK_FOR_EXCEPTION_AT_END();
- return JSValuePtr::encode(result);
-}
-
-JSValueEncodedAsPointer* Interpreter::cti_op_bitnot(STUB_ARGS)
-{
- BEGIN_STUB_FUNCTION();
-
- JSValuePtr src = ARG_src1;
-
- int value;
- if (src.numberToInt32(value))
- return JSValuePtr::encode(jsNumber(ARG_globalData, ~value));
-
- CallFrame* callFrame = ARG_callFrame;
- JSValuePtr result = jsNumber(ARG_globalData, ~src.toInt32(callFrame));
- CHECK_FOR_EXCEPTION_AT_END();
- return JSValuePtr::encode(result);
-}
-
-VoidPtrPair Interpreter::cti_op_resolve_with_base(STUB_ARGS)
-{
- BEGIN_STUB_FUNCTION();
-
- CallFrame* callFrame = ARG_callFrame;
- ScopeChainNode* scopeChain = callFrame->scopeChain();
-
- ScopeChainIterator iter = scopeChain->begin();
- ScopeChainIterator end = scopeChain->end();
-
- // FIXME: add scopeDepthIsZero optimization
-
- ASSERT(iter != end);
-
- Identifier& ident = *ARG_id1;
- JSObject* base;
- do {
- base = *iter;
- PropertySlot slot(base);
- if (base->getPropertySlot(callFrame, ident, slot)) {
- JSValuePtr result = slot.getValue(callFrame, ident);
- CHECK_FOR_EXCEPTION_AT_END();
-
- RETURN_PAIR(base, JSValuePtr::encode(result));
- }
- ++iter;
- } while (iter != end);
-
- CodeBlock* codeBlock = callFrame->codeBlock();
- unsigned vPCIndex = codeBlock->getBytecodeIndex(callFrame, STUB_RETURN_ADDRESS);
- ARG_globalData->exception = createUndefinedVariableError(callFrame, ident, vPCIndex, codeBlock);
- VM_THROW_EXCEPTION_2();
-}
-
-JSObject* Interpreter::cti_op_new_func_exp(STUB_ARGS)
-{
- BEGIN_STUB_FUNCTION();
-
- return ARG_funcexp1->makeFunction(ARG_callFrame, ARG_callFrame->scopeChain());
-}
-
-JSValueEncodedAsPointer* Interpreter::cti_op_mod(STUB_ARGS)
-{
- BEGIN_STUB_FUNCTION();
-
- JSValuePtr dividendValue = ARG_src1;
- JSValuePtr divisorValue = ARG_src2;
-
- CallFrame* callFrame = ARG_callFrame;
- double d = dividendValue.toNumber(callFrame);
- JSValuePtr result = jsNumber(ARG_globalData, fmod(d, divisorValue.toNumber(callFrame)));
- CHECK_FOR_EXCEPTION_AT_END();
- return JSValuePtr::encode(result);
-}
-
-JSValueEncodedAsPointer* Interpreter::cti_op_less(STUB_ARGS)
-{
- BEGIN_STUB_FUNCTION();
-
- CallFrame* callFrame = ARG_callFrame;
- JSValuePtr result = jsBoolean(jsLess(callFrame, ARG_src1, ARG_src2));
- CHECK_FOR_EXCEPTION_AT_END();
- return JSValuePtr::encode(result);
-}
-
-JSValueEncodedAsPointer* Interpreter::cti_op_neq(STUB_ARGS)
-{
- BEGIN_STUB_FUNCTION();
-
- JSValuePtr src1 = ARG_src1;
- JSValuePtr src2 = ARG_src2;
-
- ASSERT(!JSValuePtr::areBothInt32Fast(src1, src2));
-
- CallFrame* callFrame = ARG_callFrame;
- JSValuePtr result = jsBoolean(!JSValuePtr::equalSlowCaseInline(callFrame, src1, src2));
- CHECK_FOR_EXCEPTION_AT_END();
- return JSValuePtr::encode(result);
-}
-
-VoidPtrPair Interpreter::cti_op_post_dec(STUB_ARGS)
-{
- BEGIN_STUB_FUNCTION();
-
- JSValuePtr v = ARG_src1;
-
- CallFrame* callFrame = ARG_callFrame;
-
- JSValuePtr number = v.toJSNumber(callFrame);
- CHECK_FOR_EXCEPTION_AT_END();
-
- RETURN_PAIR(JSValuePtr::encode(number), JSValuePtr::encode(jsNumber(ARG_globalData, number.uncheckedGetNumber() - 1)));
-}
-
-JSValueEncodedAsPointer* Interpreter::cti_op_urshift(STUB_ARGS)
-{
- BEGIN_STUB_FUNCTION();
-
- JSValuePtr val = ARG_src1;
- JSValuePtr shift = ARG_src2;
-
- CallFrame* callFrame = ARG_callFrame;
-
- if (JSFastMath::canDoFastUrshift(val, shift))
- return JSValuePtr::encode(JSFastMath::rightShiftImmediateNumbers(val, shift));
- else {
- JSValuePtr result = jsNumber(ARG_globalData, (val.toUInt32(callFrame)) >> (shift.toUInt32(callFrame) & 0x1f));
- CHECK_FOR_EXCEPTION_AT_END();
- return JSValuePtr::encode(result);
- }
-}
-
-JSValueEncodedAsPointer* Interpreter::cti_op_bitxor(STUB_ARGS)
-{
- BEGIN_STUB_FUNCTION();
-
- JSValuePtr src1 = ARG_src1;
- JSValuePtr src2 = ARG_src2;
-
- CallFrame* callFrame = ARG_callFrame;
-
- JSValuePtr result = jsNumber(ARG_globalData, src1.toInt32(callFrame) ^ src2.toInt32(callFrame));
- CHECK_FOR_EXCEPTION_AT_END();
- return JSValuePtr::encode(result);
-}
-
-JSObject* Interpreter::cti_op_new_regexp(STUB_ARGS)
-{
- BEGIN_STUB_FUNCTION();
-
- return new (ARG_globalData) RegExpObject(ARG_callFrame->lexicalGlobalObject()->regExpStructure(), ARG_regexp1);
-}
-
-JSValueEncodedAsPointer* Interpreter::cti_op_bitor(STUB_ARGS)
-{
- BEGIN_STUB_FUNCTION();
-
- JSValuePtr src1 = ARG_src1;
- JSValuePtr src2 = ARG_src2;
-
- CallFrame* callFrame = ARG_callFrame;
-
- JSValuePtr result = jsNumber(ARG_globalData, src1.toInt32(callFrame) | src2.toInt32(callFrame));
- CHECK_FOR_EXCEPTION_AT_END();
- return JSValuePtr::encode(result);
-}
-
-JSValueEncodedAsPointer* Interpreter::cti_op_call_eval(STUB_ARGS)
-{
- BEGIN_STUB_FUNCTION();
-
- CallFrame* callFrame = ARG_callFrame;
- RegisterFile* registerFile = ARG_registerFile;
-
- Interpreter* interpreter = ARG_globalData->interpreter;
-
- JSValuePtr funcVal = ARG_src1;
- int registerOffset = ARG_int2;
- int argCount = ARG_int3;
-
- Register* newCallFrame = callFrame->registers() + registerOffset;
- Register* argv = newCallFrame - RegisterFile::CallFrameHeaderSize - argCount;
- JSValuePtr thisValue = argv[0].jsValue(callFrame);
- JSGlobalObject* globalObject = callFrame->scopeChain()->globalObject();
-
- if (thisValue == globalObject && funcVal == globalObject->evalFunction()) {
- JSValuePtr exceptionValue = noValue();
- JSValuePtr result = interpreter->callEval(callFrame, registerFile, argv, argCount, registerOffset, exceptionValue);
- if (UNLIKELY(exceptionValue != noValue())) {
- ARG_globalData->exception = exceptionValue;
- VM_THROW_EXCEPTION_AT_END();
- }
- return JSValuePtr::encode(result);
- }
-
- return JSValuePtr::encode(jsImpossibleValue());
-}
-
-JSValueEncodedAsPointer* Interpreter::cti_op_throw(STUB_ARGS)
-{
- BEGIN_STUB_FUNCTION();
-
- CallFrame* callFrame = ARG_callFrame;
- CodeBlock* codeBlock = callFrame->codeBlock();
-
- unsigned vPCIndex = codeBlock->getBytecodeIndex(callFrame, STUB_RETURN_ADDRESS);
-
- JSValuePtr exceptionValue = ARG_src1;
- ASSERT(exceptionValue);
-
- HandlerInfo* handler = ARG_globalData->interpreter->throwException(callFrame, exceptionValue, vPCIndex, true);
-
- if (!handler) {
- *ARG_exception = exceptionValue;
- return JSValuePtr::encode(jsNull());
- }
-
- ARG_setCallFrame(callFrame);
- void* catchRoutine = handler->nativeCode;
- ASSERT(catchRoutine);
- STUB_SET_RETURN_ADDRESS(catchRoutine);
- return JSValuePtr::encode(exceptionValue);
-}
-
-JSPropertyNameIterator* Interpreter::cti_op_get_pnames(STUB_ARGS)
-{
- BEGIN_STUB_FUNCTION();
-
- return JSPropertyNameIterator::create(ARG_callFrame, ARG_src1);
-}
-
-JSValueEncodedAsPointer* Interpreter::cti_op_next_pname(STUB_ARGS)
-{
- BEGIN_STUB_FUNCTION();
-
- JSPropertyNameIterator* it = ARG_pni1;
- JSValuePtr temp = it->next(ARG_callFrame);
- if (!temp)
- it->invalidate();
- return JSValuePtr::encode(temp);
-}
-
-JSObject* Interpreter::cti_op_push_scope(STUB_ARGS)
-{
- BEGIN_STUB_FUNCTION();
-
- JSObject* o = ARG_src1.toObject(ARG_callFrame);
- CHECK_FOR_EXCEPTION();
- ARG_callFrame->setScopeChain(ARG_callFrame->scopeChain()->push(o));
- return o;
-}
-
-void Interpreter::cti_op_pop_scope(STUB_ARGS)
-{
- BEGIN_STUB_FUNCTION();
-
- ARG_callFrame->setScopeChain(ARG_callFrame->scopeChain()->pop());
-}
-
-JSValueEncodedAsPointer* Interpreter::cti_op_typeof(STUB_ARGS)
-{
- BEGIN_STUB_FUNCTION();
-
- return JSValuePtr::encode(jsTypeStringForValue(ARG_callFrame, ARG_src1));
-}
-
-JSValueEncodedAsPointer* Interpreter::cti_op_is_undefined(STUB_ARGS)
-{
- BEGIN_STUB_FUNCTION();
-
- JSValuePtr v = ARG_src1;
- return JSValuePtr::encode(jsBoolean(v.isCell() ? v.asCell()->structure()->typeInfo().masqueradesAsUndefined() : v.isUndefined()));
-}
-
-JSValueEncodedAsPointer* Interpreter::cti_op_is_boolean(STUB_ARGS)
-{
- BEGIN_STUB_FUNCTION();
-
- return JSValuePtr::encode(jsBoolean(ARG_src1.isBoolean()));
-}
-
-JSValueEncodedAsPointer* Interpreter::cti_op_is_number(STUB_ARGS)
-{
- BEGIN_STUB_FUNCTION();
-
- return JSValuePtr::encode(jsBoolean(ARG_src1.isNumber()));
-}
-
-JSValueEncodedAsPointer* Interpreter::cti_op_is_string(STUB_ARGS)
-{
- BEGIN_STUB_FUNCTION();
-
- return JSValuePtr::encode(jsBoolean(ARG_globalData->interpreter->isJSString(ARG_src1)));
-}
-
-JSValueEncodedAsPointer* Interpreter::cti_op_is_object(STUB_ARGS)
-{
- BEGIN_STUB_FUNCTION();
-
- return JSValuePtr::encode(jsBoolean(jsIsObjectType(ARG_src1)));
-}
-
-JSValueEncodedAsPointer* Interpreter::cti_op_is_function(STUB_ARGS)
-{
- BEGIN_STUB_FUNCTION();
-
- return JSValuePtr::encode(jsBoolean(jsIsFunctionType(ARG_src1)));
-}
-
-JSValueEncodedAsPointer* Interpreter::cti_op_stricteq(STUB_ARGS)
-{
- BEGIN_STUB_FUNCTION();
-
- JSValuePtr src1 = ARG_src1;
- JSValuePtr src2 = ARG_src2;
-
- return JSValuePtr::encode(jsBoolean(JSValuePtr::strictEqual(src1, src2)));
-}
-
-JSValueEncodedAsPointer* Interpreter::cti_op_nstricteq(STUB_ARGS)
-{
- BEGIN_STUB_FUNCTION();
-
- JSValuePtr src1 = ARG_src1;
- JSValuePtr src2 = ARG_src2;
-
- return JSValuePtr::encode(jsBoolean(!JSValuePtr::strictEqual(src1, src2)));
-}
-
-JSValueEncodedAsPointer* Interpreter::cti_op_to_jsnumber(STUB_ARGS)
-{
- BEGIN_STUB_FUNCTION();
-
- JSValuePtr src = ARG_src1;
- CallFrame* callFrame = ARG_callFrame;
-
- JSValuePtr result = src.toJSNumber(callFrame);
- CHECK_FOR_EXCEPTION_AT_END();
- return JSValuePtr::encode(result);
-}
-
-JSValueEncodedAsPointer* Interpreter::cti_op_in(STUB_ARGS)
-{
- BEGIN_STUB_FUNCTION();
-
- CallFrame* callFrame = ARG_callFrame;
- JSValuePtr baseVal = ARG_src2;
-
- if (!baseVal.isObject()) {
- CallFrame* callFrame = ARG_callFrame;
- CodeBlock* codeBlock = callFrame->codeBlock();
- unsigned vPCIndex = codeBlock->getBytecodeIndex(callFrame, STUB_RETURN_ADDRESS);
- ARG_globalData->exception = createInvalidParamError(callFrame, "in", baseVal, vPCIndex, codeBlock);
- VM_THROW_EXCEPTION();
- }
-
- JSValuePtr propName = ARG_src1;
- JSObject* baseObj = asObject(baseVal);
-
- uint32_t i;
- if (propName.getUInt32(i))
- return JSValuePtr::encode(jsBoolean(baseObj->hasProperty(callFrame, i)));
-
- Identifier property(callFrame, propName.toString(callFrame));
- CHECK_FOR_EXCEPTION();
- return JSValuePtr::encode(jsBoolean(baseObj->hasProperty(callFrame, property)));
-}
-
-JSObject* Interpreter::cti_op_push_new_scope(STUB_ARGS)
-{
- BEGIN_STUB_FUNCTION();
-
- JSObject* scope = new (ARG_globalData) JSStaticScopeObject(ARG_callFrame, *ARG_id1, ARG_src2, DontDelete);
-
- CallFrame* callFrame = ARG_callFrame;
- callFrame->setScopeChain(callFrame->scopeChain()->push(scope));
- return scope;
-}
-
-void Interpreter::cti_op_jmp_scopes(STUB_ARGS)
-{
- BEGIN_STUB_FUNCTION();
-
- unsigned count = ARG_int1;
- CallFrame* callFrame = ARG_callFrame;
-
- ScopeChainNode* tmp = callFrame->scopeChain();
- while (count--)
- tmp = tmp->pop();
- callFrame->setScopeChain(tmp);
-}
-
-void Interpreter::cti_op_put_by_index(STUB_ARGS)
-{
- BEGIN_STUB_FUNCTION();
-
- CallFrame* callFrame = ARG_callFrame;
- unsigned property = ARG_int2;
-
- ARG_src1.put(callFrame, property, ARG_src3);
-}
-
-void* Interpreter::cti_op_switch_imm(STUB_ARGS)
-{
- BEGIN_STUB_FUNCTION();
-
- JSValuePtr scrutinee = ARG_src1;
- unsigned tableIndex = ARG_int2;
- CallFrame* callFrame = ARG_callFrame;
- CodeBlock* codeBlock = callFrame->codeBlock();
-
- if (scrutinee.isInt32Fast())
- return codeBlock->immediateSwitchJumpTable(tableIndex).ctiForValue(scrutinee.getInt32Fast());
- else {
- int32_t value;
- if (scrutinee.numberToInt32(value))
- return codeBlock->immediateSwitchJumpTable(tableIndex).ctiForValue(value);
- else
- return codeBlock->immediateSwitchJumpTable(tableIndex).ctiDefault;
- }
-}
-
-void* Interpreter::cti_op_switch_char(STUB_ARGS)
-{
- BEGIN_STUB_FUNCTION();
-
- JSValuePtr scrutinee = ARG_src1;
- unsigned tableIndex = ARG_int2;
- CallFrame* callFrame = ARG_callFrame;
- CodeBlock* codeBlock = callFrame->codeBlock();
-
- void* result = codeBlock->characterSwitchJumpTable(tableIndex).ctiDefault;
-
- if (scrutinee.isString()) {
- UString::Rep* value = asString(scrutinee)->value().rep();
- if (value->size() == 1)
- result = codeBlock->characterSwitchJumpTable(tableIndex).ctiForValue(value->data()[0]);
- }
-
- return result;
-}
-
-void* Interpreter::cti_op_switch_string(STUB_ARGS)
-{
- BEGIN_STUB_FUNCTION();
-
- JSValuePtr scrutinee = ARG_src1;
- unsigned tableIndex = ARG_int2;
- CallFrame* callFrame = ARG_callFrame;
- CodeBlock* codeBlock = callFrame->codeBlock();
-
- void* result = codeBlock->stringSwitchJumpTable(tableIndex).ctiDefault;
-
- if (scrutinee.isString()) {
- UString::Rep* value = asString(scrutinee)->value().rep();
- result = codeBlock->stringSwitchJumpTable(tableIndex).ctiForValue(value);
- }
-
- return result;
-}
-
-JSValueEncodedAsPointer* Interpreter::cti_op_del_by_val(STUB_ARGS)
-{
- BEGIN_STUB_FUNCTION();
-
- CallFrame* callFrame = ARG_callFrame;
-
- JSValuePtr baseValue = ARG_src1;
- JSObject* baseObj = baseValue.toObject(callFrame); // may throw
-
- JSValuePtr subscript = ARG_src2;
- JSValuePtr result;
- uint32_t i;
- if (subscript.getUInt32(i))
- result = jsBoolean(baseObj->deleteProperty(callFrame, i));
- else {
- CHECK_FOR_EXCEPTION();
- Identifier property(callFrame, subscript.toString(callFrame));
- CHECK_FOR_EXCEPTION();
- result = jsBoolean(baseObj->deleteProperty(callFrame, property));
- }
-
- CHECK_FOR_EXCEPTION_AT_END();
- return JSValuePtr::encode(result);
-}
-
-void Interpreter::cti_op_put_getter(STUB_ARGS)
-{
- BEGIN_STUB_FUNCTION();
-
- CallFrame* callFrame = ARG_callFrame;
-
- ASSERT(ARG_src1.isObject());
- JSObject* baseObj = asObject(ARG_src1);
- ASSERT(ARG_src3.isObject());
- baseObj->defineGetter(callFrame, *ARG_id2, asObject(ARG_src3));
-}
-
-void Interpreter::cti_op_put_setter(STUB_ARGS)
-{
- BEGIN_STUB_FUNCTION();
-
- CallFrame* callFrame = ARG_callFrame;
-
- ASSERT(ARG_src1.isObject());
- JSObject* baseObj = asObject(ARG_src1);
- ASSERT(ARG_src3.isObject());
- baseObj->defineSetter(callFrame, *ARG_id2, asObject(ARG_src3));
-}
-
-JSObject* Interpreter::cti_op_new_error(STUB_ARGS)
-{
- BEGIN_STUB_FUNCTION();
-
- CallFrame* callFrame = ARG_callFrame;
- CodeBlock* codeBlock = callFrame->codeBlock();
- unsigned type = ARG_int1;
- JSValuePtr message = ARG_src2;
- unsigned bytecodeOffset = ARG_int3;
-
- unsigned lineNumber = codeBlock->lineNumberForBytecodeOffset(callFrame, bytecodeOffset);
- return Error::create(callFrame, static_cast<ErrorType>(type), message.toString(callFrame), lineNumber, codeBlock->ownerNode()->sourceID(), codeBlock->ownerNode()->sourceURL());
-}
-
-void Interpreter::cti_op_debug(STUB_ARGS)
-{
- BEGIN_STUB_FUNCTION();
-
- CallFrame* callFrame = ARG_callFrame;
-
- int debugHookID = ARG_int1;
- int firstLine = ARG_int2;
- int lastLine = ARG_int3;
-
- ARG_globalData->interpreter->debug(callFrame, static_cast<DebugHookID>(debugHookID), firstLine, lastLine);
-}
-
-JSValueEncodedAsPointer* Interpreter::cti_vm_throw(STUB_ARGS)
-{
- BEGIN_STUB_FUNCTION();
-
- CallFrame* callFrame = ARG_callFrame;
- CodeBlock* codeBlock = callFrame->codeBlock();
- JSGlobalData* globalData = ARG_globalData;
-
- unsigned vPCIndex = codeBlock->getBytecodeIndex(callFrame, globalData->exceptionLocation);
-
- JSValuePtr exceptionValue = globalData->exception;
- ASSERT(exceptionValue);
- globalData->exception = noValue();
-
- HandlerInfo* handler = globalData->interpreter->throwException(callFrame, exceptionValue, vPCIndex, false);
-
- if (!handler) {
- *ARG_exception = exceptionValue;
- return JSValuePtr::encode(jsNull());
- }
-
- ARG_setCallFrame(callFrame);
- void* catchRoutine = handler->nativeCode;
- ASSERT(catchRoutine);
- STUB_SET_RETURN_ADDRESS(catchRoutine);
- return JSValuePtr::encode(exceptionValue);
-}
-
-#undef STUB_RETURN_ADDRESS
-#undef STUB_SET_RETURN_ADDRESS
-#undef BEGIN_STUB_FUNCTION
-#undef CHECK_FOR_EXCEPTION
-#undef CHECK_FOR_EXCEPTION_AT_END
-#undef CHECK_FOR_EXCEPTION_VOID
-#undef VM_THROW_EXCEPTION
-#undef VM_THROW_EXCEPTION_2
-#undef VM_THROW_EXCEPTION_AT_END
-
-#endif // ENABLE(JIT)
-
-#else // MANUAL_MERGE_REQUIRED
-#endif // MANUAL_MERGE_REQUIRED
} // namespace JSC
diff --git a/JavaScriptCore/interpreter/Interpreter.h b/JavaScriptCore/interpreter/Interpreter.h
index 3f261d4..7cab254 100644
--- a/JavaScriptCore/interpreter/Interpreter.h
+++ b/JavaScriptCore/interpreter/Interpreter.h
@@ -30,12 +30,13 @@
#define Interpreter_h
#include "ArgList.h"
+#include "FastAllocBase.h"
+#include "HashMap.h"
#include "JSCell.h"
#include "JSValue.h"
#include "JSObject.h"
#include "Opcode.h"
#include "RegisterFile.h"
-#include <wtf/HashMap.h>
namespace JSC {
@@ -51,6 +52,7 @@ namespace JSC {
class Register;
class ScopeChainNode;
class SamplingTool;
+ struct CallFrameClosure;
struct HandlerInfo;
enum DebugHookID {
@@ -62,12 +64,11 @@ namespace JSC {
WillExecuteStatement
};
- enum { MaxReentryDepth = 64 };
+ enum { MaxMainThreadReentryDepth = 256, MaxSecondaryThreadReentryDepth = 32 };
- class Interpreter {
+ class Interpreter : public WTF::FastAllocBase {
friend class JIT;
- friend class JITStubs;
-
+ friend class CachedCall;
public:
Interpreter();
@@ -94,50 +95,57 @@ namespace JSC {
bool isOpcode(Opcode);
- JSValuePtr execute(ProgramNode*, CallFrame*, ScopeChainNode*, JSObject* thisObj, JSValuePtr* exception);
- JSValuePtr execute(FunctionBodyNode*, CallFrame*, JSFunction*, JSObject* thisObj, const ArgList& args, ScopeChainNode*, JSValuePtr* exception);
- JSValuePtr execute(EvalNode* evalNode, CallFrame* exec, JSObject* thisObj, ScopeChainNode* scopeChain, JSValuePtr* exception);
+ JSValue execute(ProgramNode*, CallFrame*, ScopeChainNode*, JSObject* thisObj, JSValue* exception);
+ JSValue execute(FunctionBodyNode*, CallFrame*, JSFunction*, JSObject* thisObj, const ArgList& args, ScopeChainNode*, JSValue* exception);
+ JSValue execute(EvalNode* evalNode, CallFrame* exec, JSObject* thisObj, ScopeChainNode* scopeChain, JSValue* exception);
- JSValuePtr retrieveArguments(CallFrame*, JSFunction*) const;
- JSValuePtr retrieveCaller(CallFrame*, InternalFunction*) const;
- void retrieveLastCaller(CallFrame*, int& lineNumber, intptr_t& sourceID, UString& sourceURL, JSValuePtr& function) const;
+ JSValue retrieveArguments(CallFrame*, JSFunction*) const;
+ JSValue retrieveCaller(CallFrame*, InternalFunction*) const;
+ void retrieveLastCaller(CallFrame*, int& lineNumber, intptr_t& sourceID, UString& sourceURL, JSValue& function) const;
void getArgumentsData(CallFrame*, JSFunction*&, ptrdiff_t& firstParameterIndex, Register*& argv, int& argc);
+
void setSampler(SamplingTool* sampler) { m_sampler = sampler; }
SamplingTool* sampler() { return m_sampler; }
+ NEVER_INLINE JSValue callEval(CallFrame*, RegisterFile*, Register* argv, int argc, int registerOffset, JSValue& exceptionValue);
+ NEVER_INLINE HandlerInfo* throwException(CallFrame*&, JSValue&, unsigned bytecodeOffset, bool);
+ NEVER_INLINE void debug(CallFrame*, DebugHookID, int firstLine, int lastLine);
+
private:
enum ExecutionFlag { Normal, InitializeAndReturn };
- NEVER_INLINE JSValuePtr callEval(CallFrame*, RegisterFile*, Register* argv, int argc, int registerOffset, JSValuePtr& exceptionValue);
- JSValuePtr execute(EvalNode*, CallFrame*, JSObject* thisObject, int globalRegisterOffset, ScopeChainNode*, JSValuePtr* exception);
+ CallFrameClosure prepareForRepeatCall(FunctionBodyNode*, CallFrame*, JSFunction*, int argCount, ScopeChainNode*, JSValue* exception);
+ void endRepeatCall(CallFrameClosure&);
+ JSValue execute(CallFrameClosure&, JSValue* exception);
- NEVER_INLINE void debug(CallFrame*, DebugHookID, int firstLine, int lastLine);
+ JSValue execute(EvalNode*, CallFrame*, JSObject* thisObject, int globalRegisterOffset, ScopeChainNode*, JSValue* exception);
- NEVER_INLINE bool resolve(CallFrame*, Instruction*, JSValuePtr& exceptionValue);
- NEVER_INLINE bool resolveSkip(CallFrame*, Instruction*, JSValuePtr& exceptionValue);
- NEVER_INLINE bool resolveGlobal(CallFrame*, Instruction*, JSValuePtr& exceptionValue);
+#if USE(INTERPRETER)
+ NEVER_INLINE bool resolve(CallFrame*, Instruction*, JSValue& exceptionValue);
+ NEVER_INLINE bool resolveSkip(CallFrame*, Instruction*, JSValue& exceptionValue);
+ NEVER_INLINE bool resolveGlobal(CallFrame*, Instruction*, JSValue& exceptionValue);
NEVER_INLINE void resolveBase(CallFrame*, Instruction* vPC);
- NEVER_INLINE bool resolveBaseAndProperty(CallFrame*, Instruction*, JSValuePtr& exceptionValue);
+ NEVER_INLINE bool resolveBaseAndProperty(CallFrame*, Instruction*, JSValue& exceptionValue);
+ NEVER_INLINE bool resolveBaseAndFunc(CallFrame*, Instruction*, JSValue& exceptionValue);
NEVER_INLINE ScopeChainNode* createExceptionScope(CallFrame*, const Instruction* vPC);
- NEVER_INLINE bool unwindCallFrame(CallFrame*&, JSValuePtr, unsigned& bytecodeOffset, CodeBlock*&);
- NEVER_INLINE HandlerInfo* throwException(CallFrame*&, JSValuePtr&, unsigned bytecodeOffset, bool);
- NEVER_INLINE bool resolveBaseAndFunc(CallFrame*, Instruction*, JSValuePtr& exceptionValue);
+ void tryCacheGetByID(CallFrame*, CodeBlock*, Instruction*, JSValue baseValue, const Identifier& propertyName, const PropertySlot&);
+ void uncacheGetByID(CodeBlock*, Instruction* vPC);
+ void tryCachePutByID(CallFrame*, CodeBlock*, Instruction*, JSValue baseValue, const PutPropertySlot&);
+ void uncachePutByID(CodeBlock*, Instruction* vPC);
+#endif
+
+ NEVER_INLINE bool unwindCallFrame(CallFrame*&, JSValue, unsigned& bytecodeOffset, CodeBlock*&);
static ALWAYS_INLINE CallFrame* slideRegisterWindowForCall(CodeBlock*, RegisterFile*, CallFrame*, size_t registerOffset, int argc);
static CallFrame* findFunctionCallFrame(CallFrame*, InternalFunction*);
- JSValuePtr privateExecute(ExecutionFlag, RegisterFile*, CallFrame*, JSValuePtr* exception);
+ JSValue privateExecute(ExecutionFlag, RegisterFile*, CallFrame*, JSValue* exception);
void dumpCallFrame(CallFrame*);
void dumpRegisters(CallFrame*);
-
- void tryCacheGetByID(CallFrame*, CodeBlock*, Instruction*, JSValuePtr baseValue, const Identifier& propertyName, const PropertySlot&);
- void uncacheGetByID(CodeBlock*, Instruction* vPC);
- void tryCachePutByID(CallFrame*, CodeBlock*, Instruction*, JSValuePtr baseValue, const PutPropertySlot&);
- void uncachePutByID(CodeBlock*, Instruction* vPC);
bool isCallBytecode(Opcode opcode) { return opcode == getOpcode(op_call) || opcode == getOpcode(op_construct) || opcode == getOpcode(op_call_eval); }
@@ -152,7 +160,7 @@ namespace JSC {
HashMap<Opcode, OpcodeID> m_opcodeIDTable; // Maps Opcode => OpcodeID for decompiling
#endif
};
-
+
} // namespace JSC
#endif // Interpreter_h
diff --git a/JavaScriptCore/interpreter/Register.h b/JavaScriptCore/interpreter/Register.h
index 5277a0f..cceac74 100644
--- a/JavaScriptCore/interpreter/Register.h
+++ b/JavaScriptCore/interpreter/Register.h
@@ -30,6 +30,7 @@
#define Register_h
#include "JSValue.h"
+#include <wtf/Assertions.h>
#include <wtf/VectorTraits.h>
namespace JSC {
@@ -49,25 +50,26 @@ namespace JSC {
class Register {
public:
Register();
- Register(JSValuePtr);
+ Register(JSValue);
+ Register(Arguments*);
- JSValuePtr jsValue(CallFrame*) const;
- JSValuePtr getJSValue() const;
+ JSValue jsValue() const;
bool marked() const;
void mark();
+ int32_t i() const;
+ void* v() const;
+
private:
friend class ExecState;
friend class Interpreter;
- friend class JITStubs;
// Only CallFrame, Interpreter, and JITStubs should use these functions.
Register(intptr_t);
Register(JSActivation*);
- Register(Arguments*);
Register(CallFrame*);
Register(CodeBlock*);
Register(JSFunction*);
@@ -75,9 +77,6 @@ namespace JSC {
Register(ScopeChainNode*);
Register(Instruction*);
- intptr_t i() const;
- void* v() const;
-
JSActivation* activation() const;
Arguments* arguments() const;
CallFrame* callFrame() const;
@@ -90,7 +89,7 @@ namespace JSC {
union {
intptr_t i;
void* v;
- JSValueEncodedAsPointer* value;
+ EncodedJSValue value;
JSActivation* activation;
Arguments* arguments;
@@ -101,136 +100,89 @@ namespace JSC {
ScopeChainNode* scopeChain;
Instruction* vPC;
} u;
-
-#ifndef NDEBUG
- enum {
- EmptyType,
-
- IntType,
- ValueType,
-
- ActivationType,
- ArgumentsType,
- CallFrameType,
- CodeBlockType,
- FunctionType,
- InstructionType,
- PropertyNameIteratorType,
- RegisterType,
- ScopeChainNodeType
- } m_type;
-#endif
};
-#ifndef NDEBUG
- #define SET_TYPE(type) m_type = (type)
- // FIXME: The CTI code to put value into registers doesn't set m_type.
- // Once it does, we can turn this assertion back on.
- #define ASSERT_TYPE(type)
-#else
- #define SET_TYPE(type)
- #define ASSERT_TYPE(type)
-#endif
-
ALWAYS_INLINE Register::Register()
{
#ifndef NDEBUG
- SET_TYPE(EmptyType);
- u.value = JSValuePtr::encode(noValue());
+ u.value = JSValue::encode(JSValue());
#endif
}
- ALWAYS_INLINE Register::Register(JSValuePtr v)
+ ALWAYS_INLINE Register::Register(JSValue v)
{
- SET_TYPE(ValueType);
- u.value = JSValuePtr::encode(v);
+ u.value = JSValue::encode(v);
}
- // This function is scaffolding for legacy clients. It will eventually go away.
- ALWAYS_INLINE JSValuePtr Register::jsValue(CallFrame*) const
+ ALWAYS_INLINE JSValue Register::jsValue() const
{
- // Once registers hold doubles, this function will allocate a JSValue*
- // if the register doesn't hold one already.
- ASSERT_TYPE(ValueType);
- return JSValuePtr::decode(u.value);
- }
-
- ALWAYS_INLINE JSValuePtr Register::getJSValue() const
- {
- ASSERT_TYPE(JSValueType);
- return JSValuePtr::decode(u.value);
+ return JSValue::decode(u.value);
}
ALWAYS_INLINE bool Register::marked() const
{
- return getJSValue().marked();
+ return jsValue().marked();
}
ALWAYS_INLINE void Register::mark()
{
- getJSValue().mark();
+ jsValue().mark();
}
// Interpreter functions
ALWAYS_INLINE Register::Register(Arguments* arguments)
{
- SET_TYPE(ArgumentsType);
u.arguments = arguments;
}
ALWAYS_INLINE Register::Register(JSActivation* activation)
{
- SET_TYPE(ActivationType);
u.activation = activation;
}
ALWAYS_INLINE Register::Register(CallFrame* callFrame)
{
- SET_TYPE(CallFrameType);
u.callFrame = callFrame;
}
ALWAYS_INLINE Register::Register(CodeBlock* codeBlock)
{
- SET_TYPE(CodeBlockType);
u.codeBlock = codeBlock;
}
ALWAYS_INLINE Register::Register(JSFunction* function)
{
- SET_TYPE(FunctionType);
u.function = function;
}
ALWAYS_INLINE Register::Register(Instruction* vPC)
{
- SET_TYPE(InstructionType);
u.vPC = vPC;
}
ALWAYS_INLINE Register::Register(ScopeChainNode* scopeChain)
{
- SET_TYPE(ScopeChainNodeType);
u.scopeChain = scopeChain;
}
ALWAYS_INLINE Register::Register(JSPropertyNameIterator* propertyNameIterator)
{
- SET_TYPE(PropertyNameIteratorType);
u.propertyNameIterator = propertyNameIterator;
}
ALWAYS_INLINE Register::Register(intptr_t i)
{
- SET_TYPE(IntType);
+ // See comment on 'i()' below.
+ ASSERT(i == static_cast<int32_t>(i));
u.i = i;
}
- ALWAYS_INLINE intptr_t Register::i() const
+ // Read 'i' as a 32-bit integer; we only use it to hold 32-bit values,
+ // and we only write 32-bits when writing the arg count from JIT code.
+ ALWAYS_INLINE int32_t Register::i() const
{
- ASSERT_TYPE(IntType);
- return u.i;
+ return static_cast<int32_t>(u.i);
}
ALWAYS_INLINE void* Register::v() const
@@ -240,55 +192,44 @@ namespace JSC {
ALWAYS_INLINE JSActivation* Register::activation() const
{
- ASSERT_TYPE(ActivationType);
return u.activation;
}
ALWAYS_INLINE Arguments* Register::arguments() const
{
- ASSERT_TYPE(ArgumentsType);
return u.arguments;
}
ALWAYS_INLINE CallFrame* Register::callFrame() const
{
- ASSERT_TYPE(CallFrameType);
return u.callFrame;
}
ALWAYS_INLINE CodeBlock* Register::codeBlock() const
{
- ASSERT_TYPE(CodeBlockType);
return u.codeBlock;
}
ALWAYS_INLINE JSFunction* Register::function() const
{
- ASSERT_TYPE(FunctionType);
return u.function;
}
ALWAYS_INLINE JSPropertyNameIterator* Register::propertyNameIterator() const
{
- ASSERT_TYPE(PropertyNameIteratorType);
return u.propertyNameIterator;
}
ALWAYS_INLINE ScopeChainNode* Register::scopeChain() const
{
- ASSERT_TYPE(ScopeChainNodeType);
return u.scopeChain;
}
ALWAYS_INLINE Instruction* Register::vPC() const
{
- ASSERT_TYPE(InstructionType);
return u.vPC;
}
- #undef SET_TYPE
- #undef ASSERT_TYPE
-
} // namespace JSC
namespace WTF {
diff --git a/JavaScriptCore/interpreter/RegisterFile.cpp b/JavaScriptCore/interpreter/RegisterFile.cpp
index 50698f5..cfcf1d3 100644
--- a/JavaScriptCore/interpreter/RegisterFile.cpp
+++ b/JavaScriptCore/interpreter/RegisterFile.cpp
@@ -42,4 +42,15 @@ RegisterFile::~RegisterFile()
#endif
}
+void RegisterFile::releaseExcessCapacity()
+{
+#if HAVE(MMAP) && HAVE(MADV_FREE) && !HAVE(VIRTUALALLOC)
+ while (madvise(m_start, (m_max - m_start) * sizeof(Register), MADV_FREE) == -1 && errno == EAGAIN) { }
+#elif HAVE(VIRTUALALLOC)
+ VirtualFree(m_start, (m_max - m_start) * sizeof(Register), MEM_DECOMMIT);
+ m_commitEnd = m_start;
+#endif
+ m_maxUsed = m_start;
+}
+
} // namespace JSC
diff --git a/JavaScriptCore/interpreter/RegisterFile.h b/JavaScriptCore/interpreter/RegisterFile.h
index c320f04..09a3963 100644
--- a/JavaScriptCore/interpreter/RegisterFile.h
+++ b/JavaScriptCore/interpreter/RegisterFile.h
@@ -29,10 +29,11 @@
#ifndef RegisterFile_h
#define RegisterFile_h
+#include "Collector.h"
#include "ExecutableAllocator.h"
#include "Register.h"
-#include "Collector.h"
#include <wtf/Noncopyable.h>
+#include <wtf/VMTags.h>
#if HAVE(MMAP)
#include <errno.h>
@@ -113,6 +114,8 @@ namespace JSC {
static const size_t defaultCapacity = 524288;
static const size_t defaultMaxGlobals = 8192;
static const size_t commitSize = 1 << 14;
+ // 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();
@@ -137,12 +140,15 @@ namespace JSC {
void markCallFrames(Heap* heap) { heap->markConservatively(m_start, m_end); }
private:
+ void releaseExcessCapacity();
size_t m_numGlobals;
const size_t m_maxGlobals;
Register* m_start;
Register* m_end;
Register* m_max;
Register* m_buffer;
+ Register* m_maxUsed;
+
#if HAVE(VIRTUALALLOC)
Register* m_commitEnd;
#endif
@@ -150,6 +156,9 @@ namespace JSC {
JSGlobalObject* m_globalObject; // The global object whose vars are currently stored in the register file.
};
+ // FIXME: Add a generic getpagesize() to WTF, then move this function to WTF as well.
+ inline bool isPageAligned(size_t size) { return size != 0 && size % (8 * 1024) == 0; }
+
inline RegisterFile::RegisterFile(size_t capacity, size_t maxGlobals)
: m_numGlobals(0)
, m_maxGlobals(maxGlobals)
@@ -159,9 +168,13 @@ namespace JSC {
, m_buffer(0)
, m_globalObject(0)
{
+ // Verify that our values will play nice with mmap and VirtualAlloc.
+ ASSERT(isPageAligned(maxGlobals));
+ ASSERT(isPageAligned(capacity));
+
size_t bufferLength = (capacity + maxGlobals) * sizeof(Register);
#if HAVE(MMAP)
- m_buffer = static_cast<Register*>(mmap(0, bufferLength, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANON, -1, 0));
+ m_buffer = static_cast<Register*>(mmap(0, bufferLength, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANON, VM_TAG_FOR_REGISTERFILE_MEMORY, 0));
if (m_buffer == MAP_FAILED) {
fprintf(stderr, "Could not allocate register file: %d\n", errno);
CRASH();
@@ -184,13 +197,17 @@ namespace JSC {
#endif
m_start = m_buffer + maxGlobals;
m_end = m_start;
+ m_maxUsed = m_end;
m_max = m_start + capacity;
}
inline void RegisterFile::shrink(Register* newEnd)
{
- if (newEnd < m_end)
- m_end = newEnd;
+ if (newEnd >= m_end)
+ return;
+ m_end = newEnd;
+ if (m_end == m_start && (m_maxUsed - m_start) > maxExcessCapacity)
+ releaseExcessCapacity();
}
inline bool RegisterFile::grow(Register* newEnd)
@@ -212,6 +229,9 @@ namespace JSC {
}
#endif
+ if (newEnd > m_maxUsed)
+ m_maxUsed = newEnd;
+
m_end = newEnd;
return true;
}