Merge squirrelfish branch into trunk.
git-svn-id: http://svn.webkit.org/repository/webkit/trunk@33979 268f45cc-cd09-0410-ab3c-d52691b4dbfc
diff --git a/JavaScriptCore/kjs/Activation.h b/JavaScriptCore/kjs/Activation.h
deleted file mode 100644
index 5cbdf1ab..0000000
--- a/JavaScriptCore/kjs/Activation.h
+++ /dev/null
@@ -1,112 +0,0 @@
-/*
- * Copyright (C) 1999-2000 Harri Porten (porten@kde.org)
- * Copyright (C) 2003, 2006, 2007 Apple Inc. All rights reserved.
- * Copyright (C) 2007 Cameron Zwarich (cwzwarich@uwaterloo.ca)
- * Copyright (C) 2007 Maks Orlovich
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Library General Public
- * License as published by the Free Software Foundation; either
- * version 2 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Library General Public License for more details.
- *
- * You should have received a copy of the GNU Library General Public License
- * along with this library; see the file COPYING.LIB. If not, write to
- * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
- * Boston, MA 02110-1301, USA.
- *
- */
-
-#ifndef Activation_h
-#define Activation_h
-
-#include "ExecState.h"
-#include "JSVariableObject.h"
-#include "object.h"
-#include "function.h"
-
-namespace KJS {
-
- class Arguments;
- class FunctionImp;
-
- class ActivationImp : public JSVariableObject {
- friend class JSGlobalObject;
- friend struct StackActivation;
- private:
- struct ActivationData : public JSVariableObjectData {
- ActivationData() : isOnStack(true), leftRelic(false) { }
- ActivationData(const ActivationData&);
-
- ExecState* exec;
- FunctionImp* function;
- Arguments* argumentsObject;
-
- bool isOnStack : 1;
- bool leftRelic : 1;
- };
-
- public:
- ActivationImp() { }
- ActivationImp(const ActivationData&, bool);
-
- virtual ~ActivationImp();
-
- void init(ExecState*);
-
- virtual bool getOwnPropertySlot(ExecState*, const Identifier&, PropertySlot&);
- virtual void put(ExecState*, const Identifier&, JSValue*);
- virtual void putWithAttributes(ExecState*, const Identifier&, JSValue*, unsigned attributes);
- virtual bool deleteProperty(ExecState*, const Identifier& propertyName);
-
- virtual const ClassInfo* classInfo() const { return &info; }
- static const ClassInfo info;
-
- virtual JSObject* toThisObject(ExecState*) const;
-
- virtual void mark();
- void markChildren();
-
- virtual bool isActivationObject() const { return true; }
-
- bool isOnStack() const { return d()->isOnStack; }
- bool needsPop() const { return d()->isOnStack || d()->leftRelic; }
-
- virtual bool isDynamicScope() const;
- private:
- static PropertySlot::GetValueFunc getArgumentsGetter();
- static JSValue* argumentsGetter(ExecState*, JSObject*, const Identifier&, const PropertySlot&);
- void createArgumentsObject(ExecState*);
- ActivationData* d() const { return static_cast<ActivationData*>(JSVariableObject::d); }
- };
-
- inline void ActivationImp::init(ExecState* exec)
- {
- d()->exec = exec;
- d()->function = exec->function();
- d()->symbolTable = &exec->function()->body->symbolTable();
- d()->argumentsObject = 0;
- }
-
- const size_t activationStackNodeSize = 32;
-
- struct StackActivation {
- StackActivation() { activationStorage.JSVariableObject::d = &activationDataStorage; }
- StackActivation(const StackActivation&);
-
- ActivationImp activationStorage;
- ActivationImp::ActivationData activationDataStorage;
- };
-
- struct ActivationStackNode {
- ActivationStackNode* prev;
- StackActivation data[activationStackNodeSize];
- };
-
-} // namespace
-
-#endif
diff --git a/JavaScriptCore/kjs/AllInOneFile.cpp b/JavaScriptCore/kjs/AllInOneFile.cpp
index 5144521..eb1d2b4 100644
--- a/JavaScriptCore/kjs/AllInOneFile.cpp
+++ b/JavaScriptCore/kjs/AllInOneFile.cpp
@@ -39,7 +39,6 @@
#include "DateMath.cpp"
#include "dtoa.cpp"
#include "error_object.cpp"
-#include "ExecState.cpp"
#include "function_object.cpp"
#include "grammar.cpp"
#include "identifier.cpp"
@@ -70,3 +69,5 @@
#include "value.cpp"
#include "wtf/FastMalloc.cpp"
#include "wtf/TCSystemAlloc.cpp"
+#include "VM/CodeGenerator.cpp"
+#include "VM/RegisterFile.cpp"
diff --git a/JavaScriptCore/kjs/CallData.h b/JavaScriptCore/kjs/CallData.h
new file mode 100644
index 0000000..c701c2b
--- /dev/null
+++ b/JavaScriptCore/kjs/CallData.h
@@ -0,0 +1,52 @@
+/*
+ * Copyright (C) 2008 Apple Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of Apple Computer, Inc. ("Apple") nor the names of
+ * its contributors may be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE AND ITS CONTRIBUTORS "AS IS" AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL APPLE OR ITS CONTRIBUTORS BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef CallData_h
+#define CallData_h
+
+namespace KJS {
+
+ class FunctionBodyNode;
+ class ScopeChainNode;
+
+ enum CallType {
+ CallTypeNone,
+ CallTypeNative,
+ CallTypeJS
+ };
+
+ union CallData {
+ struct {
+ FunctionBodyNode* functionBody;
+ ScopeChainNode* scopeChain;
+ } js;
+ };
+
+} // namespace KJS
+
+#endif // CallData_h
diff --git a/JavaScriptCore/kjs/CommonIdentifiers.cpp b/JavaScriptCore/kjs/CommonIdentifiers.cpp
index 543e6aa..00181fe 100644
--- a/JavaScriptCore/kjs/CommonIdentifiers.cpp
+++ b/JavaScriptCore/kjs/CommonIdentifiers.cpp
@@ -35,6 +35,7 @@
CommonIdentifiers::CommonIdentifiers()
: nullIdentifier(nullCString)
, underscoreProto("__proto__")
+ , thisIdentifier("this")
KJS_COMMON_IDENTIFIERS_EACH_PROPERTY_NAME(INITIALIZE_PROPERTY_NAME)
{
}
diff --git a/JavaScriptCore/kjs/CommonIdentifiers.h b/JavaScriptCore/kjs/CommonIdentifiers.h
index f709242..d7507b5 100644
--- a/JavaScriptCore/kjs/CommonIdentifiers.h
+++ b/JavaScriptCore/kjs/CommonIdentifiers.h
@@ -82,6 +82,7 @@
const Identifier nullIdentifier;
const Identifier underscoreProto;
+ const Identifier thisIdentifier;
#define KJS_IDENTIFIER_DECLARE_PROPERTY_NAME_GLOBAL(name) const Identifier name;
KJS_COMMON_IDENTIFIERS_EACH_PROPERTY_NAME(KJS_IDENTIFIER_DECLARE_PROPERTY_NAME_GLOBAL)
diff --git a/JavaScriptCore/kjs/ConstructData.h b/JavaScriptCore/kjs/ConstructData.h
new file mode 100644
index 0000000..9463503
--- /dev/null
+++ b/JavaScriptCore/kjs/ConstructData.h
@@ -0,0 +1,52 @@
+/*
+ * Copyright (C) 2008 Apple Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of Apple Computer, Inc. ("Apple") nor the names of
+ * its contributors may be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE AND ITS CONTRIBUTORS "AS IS" AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL APPLE OR ITS CONTRIBUTORS BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef ConstructData_h
+#define ConstructData_h
+
+namespace KJS {
+
+ class FunctionBodyNode;
+ class ScopeChain;
+
+ enum ConstructType {
+ ConstructTypeNone,
+ ConstructTypeNative,
+ ConstructTypeJS
+ };
+
+ union ConstructData {
+ struct {
+ FunctionBodyNode* functionBody;
+ ScopeChainNode* scopeChain;
+ } js;
+ };
+
+} // namespace KJS
+
+#endif // ConstructData_h
diff --git a/JavaScriptCore/kjs/DebuggerCallFrame.cpp b/JavaScriptCore/kjs/DebuggerCallFrame.cpp
new file mode 100644
index 0000000..81bc193
--- /dev/null
+++ b/JavaScriptCore/kjs/DebuggerCallFrame.cpp
@@ -0,0 +1,85 @@
+/*
+ * Copyright (C) 2008 Apple Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of Apple Computer, Inc. ("Apple") nor the names of
+ * its contributors may be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE AND ITS CONTRIBUTORS "AS IS" AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL APPLE OR ITS CONTRIBUTORS BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include "config.h"
+#include "DebuggerCallFrame.h"
+
+#include "function.h"
+#include "CodeBlock.h"
+#include "Machine.h"
+#include "Parser.h"
+
+namespace KJS {
+
+const UString* DebuggerCallFrame::functionName() const
+{
+ if (!m_codeBlock)
+ return 0;
+
+ int callFrameOffset = m_registerOffset - m_codeBlock->numLocals - Machine::CallFrameHeaderSize;
+ if (callFrameOffset < 0)
+ return 0;
+
+ Register* callFrame = *m_registerBase + callFrameOffset;
+ FunctionImp* function = static_cast<FunctionImp*>(callFrame[Machine::Callee].u.jsValue);
+ if (!function)
+ return 0;
+ return &function->functionName().ustring();
+}
+
+JSObject* DebuggerCallFrame::thisObject() const
+{
+ if (!m_codeBlock)
+ return 0;
+
+ return static_cast<JSObject*>((*m_registerBase + m_registerOffset)[m_codeBlock->thisRegister].u.jsValue);
+}
+
+JSValue* DebuggerCallFrame::evaluate(const UString& script, JSValue*& exception) const
+{
+ if (!m_codeBlock)
+ return 0;
+
+ JSObject* thisObject = this->thisObject();
+
+ ExecState newExec(m_scopeChain->globalObject(), thisObject, m_scopeChain);
+
+ int sourceId;
+ int errLine;
+ UString errMsg;
+
+ RefPtr<EvalNode> evalNode = parser().parse<EvalNode>(&newExec, UString(), 0, UStringSourceProvider::create(script), &sourceId, &errLine, &errMsg);
+
+ if (!evalNode)
+ return Error::create(&newExec, SyntaxError, errMsg, errLine, sourceId, 0);
+
+ JSValue* result = machine().execute(evalNode.get(), &newExec, thisObject, &newExec.dynamicGlobalObject()->registerFileStack(), m_scopeChain, &exception);
+ return result;
+}
+
+} // namespace KJS
diff --git a/JavaScriptCore/kjs/DebuggerCallFrame.h b/JavaScriptCore/kjs/DebuggerCallFrame.h
new file mode 100644
index 0000000..157341b
--- /dev/null
+++ b/JavaScriptCore/kjs/DebuggerCallFrame.h
@@ -0,0 +1,75 @@
+/*
+ * Copyright (C) 2008 Apple Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of Apple Computer, Inc. ("Apple") nor the names of
+ * its contributors may be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE AND ITS CONTRIBUTORS "AS IS" AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL APPLE OR ITS CONTRIBUTORS BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef DebuggerCallFrame_h
+#define DebuggerCallFrame_h
+
+namespace KJS {
+
+ class CodeBlock;
+ class JSGlobalObject;
+ class JSObject;
+ class JSValue;
+ class Machine;
+ class UString;
+ class Register;
+ class ScopeChainNode;
+
+ class DebuggerCallFrame {
+ public:
+ DebuggerCallFrame(Machine* machine, JSGlobalObject* dynamicGlobalObject, const CodeBlock* codeBlock, ScopeChainNode* scopeChain, JSValue* exception, Register** registerBase, int registerOffset)
+ : m_machine(machine)
+ , m_dynamicGlobalObject(dynamicGlobalObject)
+ , m_codeBlock(codeBlock)
+ , m_scopeChain(scopeChain)
+ , m_exception(exception)
+ , m_registerBase(registerBase)
+ , m_registerOffset(registerOffset)
+ {
+ }
+
+ JSGlobalObject* dynamicGlobalObject() const { return m_dynamicGlobalObject; }
+ const ScopeChainNode* scopeChain() const { return m_scopeChain; }
+ const UString* functionName() const;
+ JSObject* thisObject() const;
+ JSValue* evaluate(const UString&, JSValue*& exception) const;
+ JSValue* exception() const { return m_exception; }
+
+ private:
+ Machine* m_machine;
+ JSGlobalObject* m_dynamicGlobalObject;
+ const CodeBlock* m_codeBlock;
+ ScopeChainNode* m_scopeChain;
+ JSValue* m_exception;
+ Register** m_registerBase;
+ int m_registerOffset;
+ };
+
+} // namespace KJS
+
+#endif // DebuggerCallFrame_h
diff --git a/JavaScriptCore/kjs/ExecState.cpp b/JavaScriptCore/kjs/ExecState.cpp
index edab7fc..db89422 100644
--- a/JavaScriptCore/kjs/ExecState.cpp
+++ b/JavaScriptCore/kjs/ExecState.cpp
@@ -24,122 +24,43 @@
#include "config.h"
#include "ExecState.h"
-#include "Activation.h"
#include "JSGlobalObject.h"
#include "function.h"
#include "internal.h"
#include "scope_chain_mark.h"
-#include "ExecStateInlines.h"
namespace KJS {
-// ECMA 10.2
-
-// The constructor for the globalExec pseudo-ExecState
-inline ExecState::ExecState(JSGlobalObject* globalObject, JSObject* thisObject)
+ExecState::ExecState(JSGlobalObject* globalObject, JSObject* globalThisValue, ScopeChainNode* globalScopeChain)
: m_globalObject(globalObject)
+ , m_globalThisValue(globalThisValue)
, m_exception(0)
- , m_callingExec(0)
, m_perThreadData(globalObject->perThreadData())
- , m_scopeNode(0)
- , m_function(0)
- , m_arguments(0)
- , m_activation(0)
- , m_localStorage(&globalObject->localStorage())
- , m_inlineScopeChainNode(0, 0)
- , m_variableObject(globalObject)
- , m_thisValue(thisObject)
- , m_globalThisValue(thisObject)
- , m_iterationDepth(0)
- , m_switchDepth(0)
- , m_codeType(GlobalCode)
+ , m_prev(0)
+ , m_machine(0)
+ , m_registerFile(0)
+ , m_scopeChain(globalScopeChain)
+ , m_callFrameOffset(-1)
{
- m_scopeChain.push(globalObject);
}
-inline ExecState::ExecState(JSGlobalObject* globalObject, JSObject* thisObject, ProgramNode* programNode)
- : m_globalObject(globalObject)
+ExecState::ExecState(ExecState* exec, Machine* machine, RegisterFile* registerFile, ScopeChainNode* scopeChain, int callFrameOffset)
+ : m_globalObject(exec->m_globalObject)
+ , m_globalThisValue(exec->m_globalThisValue)
, m_exception(0)
- , m_callingExec(0)
- , m_perThreadData(globalObject->perThreadData())
- , m_scopeNode(programNode)
- , m_function(0)
- , m_arguments(0)
- , m_activation(0)
- , m_localStorage(&globalObject->localStorage())
- , m_inlineScopeChainNode(0, 0)
- , m_variableObject(globalObject)
- , m_thisValue(thisObject)
- , m_globalThisValue(thisObject)
- , m_iterationDepth(0)
- , m_switchDepth(0)
- , m_codeType(GlobalCode)
-{
- ASSERT(m_scopeNode);
- m_scopeChain.push(globalObject);
-}
-
-inline ExecState::ExecState(JSGlobalObject* globalObject, JSObject* thisObject, EvalNode* evalNode, ExecState* callingExec, const ScopeChain& scopeChain, JSVariableObject* variableObject)
- : m_globalObject(globalObject)
- , m_exception(0)
- , m_callingExec(callingExec)
- , m_perThreadData(callingExec->m_perThreadData)
- , m_scopeNode(evalNode)
- , m_function(0)
- , m_arguments(0)
- , m_activation(0)
- , m_localStorage(callingExec->m_localStorage)
+ , m_perThreadData(exec->m_globalObject->perThreadData())
+ , m_prev(exec)
+ , m_machine(machine)
+ , m_registerFile(registerFile)
, m_scopeChain(scopeChain)
- , m_inlineScopeChainNode(0, 0)
- , m_variableObject(variableObject)
- , m_thisValue(thisObject)
- , m_globalThisValue(thisObject)
- , m_iterationDepth(0)
- , m_switchDepth(0)
- , m_codeType(EvalCode)
-{
- ASSERT(m_scopeNode);
+ , m_callFrameOffset(callFrameOffset)
+{
+ ASSERT(!exec->m_exception);
}
-JSGlobalObject* ExecState::lexicalGlobalObject() const
+bool ExecState::isGlobalObject(JSObject* o) const
{
- JSObject* object = m_scopeChain.bottom();
- if (object && object->isGlobalObject())
- return static_cast<JSGlobalObject*>(object);
- return m_globalObject;
+ return o->isGlobalObject();
}
-GlobalExecState::GlobalExecState(JSGlobalObject* globalObject, JSObject* thisObject)
- : ExecState(globalObject, thisObject)
-{
-}
-
-GlobalExecState::~GlobalExecState()
-{
-}
-
-InterpreterExecState::InterpreterExecState(JSGlobalObject* globalObject, JSObject* thisObject, ProgramNode* programNode)
- : ExecState(globalObject, thisObject, programNode)
-{
- m_globalObject->activeExecStates().append(this);
-}
-
-InterpreterExecState::~InterpreterExecState()
-{
- ASSERT(m_globalObject->activeExecStates().last() == this);
- m_globalObject->activeExecStates().removeLast();
-}
-
-EvalExecState::EvalExecState(JSGlobalObject* globalObject, JSObject* thisObj, EvalNode* evalNode, ExecState* callingExec, const ScopeChain& scopeChain, JSVariableObject* variableObject)
- : ExecState(globalObject, thisObj, evalNode, callingExec, scopeChain, variableObject)
-{
- m_globalObject->activeExecStates().append(this);
-}
-
-EvalExecState::~EvalExecState()
-{
- ASSERT(m_globalObject->activeExecStates().last() == this);
- m_globalObject->activeExecStates().removeLast();
-}
-
} // namespace KJS
diff --git a/JavaScriptCore/kjs/ExecState.h b/JavaScriptCore/kjs/ExecState.h
index 0947703..d4012a2 100644
--- a/JavaScriptCore/kjs/ExecState.h
+++ b/JavaScriptCore/kjs/ExecState.h
@@ -32,7 +32,6 @@
namespace KJS {
- class ActivationImp;
class CommonIdentifiers;
class EvalNode;
class FunctionBodyNode;
@@ -42,11 +41,13 @@
class Interpreter;
class JSGlobalObject;
class JSVariableObject;
+ class Machine;
class ProgramNode;
+ class RegisterFile;
class ScopeNode;
-
- enum CodeType { GlobalCode, EvalCode, FunctionCode };
+ struct Instruction;
+
struct PerThreadData {
const HashTable* arrayTable;
const HashTable* dateTable;
@@ -63,50 +64,32 @@
// Represents the current state of script execution.
// Passed as the first argument to most functions.
class ExecState : Noncopyable {
- friend class JSGlobalObject;
+ friend class Machine;
+ friend class DebuggerCallFrame;
+
public:
- // Global object that was in scope when the current script started executing.
+ ExecState(JSGlobalObject*, JSObject* globalThisValue, ScopeChainNode* globalScopeChain);
+
+ // Global object in which execution began.
JSGlobalObject* dynamicGlobalObject() const { return m_globalObject; }
- // Global object that was in scope when the current body of code was defined.
- JSGlobalObject* lexicalGlobalObject() const;
-
+ // Global object in which the current script was defined. (Can differ
+ // from dynamicGlobalObject() during function calls across frames.)
+ JSGlobalObject* lexicalGlobalObject() const
+ {
+ return m_scopeChain->globalObject();
+ }
+
+ JSObject* globalThisValue() const { return m_globalThisValue; }
+
+ Machine* machine() const { return m_machine; }
+
+ // Exception propogation.
void setException(JSValue* exception) { m_exception = exception; }
void clearException() { m_exception = 0; }
JSValue* exception() const { return m_exception; }
JSValue** exceptionSlot() { return &m_exception; }
bool hadException() const { return !!m_exception; }
- JSValue* takeException() { JSValue* exception = m_exception; m_exception = 0; return exception; }
-
- const ScopeChain& scopeChain() const { return m_scopeChain; }
- void pushScope(JSObject* s) { m_scopeChain.push(s); }
- void popScope() { m_scopeChain.pop(); }
- void replaceScopeChainTop(JSObject* o) { m_scopeChain.replaceTop(o); }
-
- JSVariableObject* variableObject() const { return m_variableObject; }
- void setVariableObject(JSVariableObject* v) { m_variableObject = v; }
-
- JSObject* thisValue() const { return m_thisValue; }
- JSObject* globalThisValue() const { return m_globalThisValue; }
-
- ExecState* callingExecState() { return m_callingExec; }
-
- ActivationImp* activationObject() { return m_activation; }
- void setActivationObject(ActivationImp* a) { m_activation = a; }
- CodeType codeType() { return m_codeType; }
- ScopeNode* scopeNode() { return m_scopeNode; }
- FunctionImp* function() const { return m_function; }
- const List* arguments() const { return m_arguments; }
-
- LabelStack& seenLabels() { return m_labelStack; }
-
- void pushIteration() { m_iterationDepth++; }
- void popIteration() { m_iterationDepth--; }
- bool inIteration() const { return (m_iterationDepth > 0); }
-
- void pushSwitch() { m_switchDepth++; }
- void popSwitch() { m_switchDepth--; }
- bool inSwitch() const { return (m_switchDepth > 0); }
// These pointers are used to avoid accessing global variables for these,
// to avoid taking PIC branches in Mach-O binaries.
@@ -120,8 +103,34 @@
static const HashTable* RegExpObjectImpTable(ExecState* exec) { return exec->m_perThreadData->RegExpObjectImpTable; }
static const HashTable* stringTable(ExecState* exec) { return exec->m_perThreadData->stringTable; }
- LocalStorage& localStorage() { return *m_localStorage; }
- void setLocalStorage(LocalStorage* s) { m_localStorage = s; }
+ private:
+ ExecState(ExecState*, Machine*, RegisterFile*, ScopeChainNode*, int callFrameOffset);
+
+ bool isGlobalObject(JSObject*) const;
+
+ JSGlobalObject* m_globalObject;
+ JSObject* m_globalThisValue;
+
+ JSValue* m_exception;
+
+ const PerThreadData* m_perThreadData;
+
+ // These values are controlled by the machine.
+ ExecState* m_prev;
+ Machine* m_machine;
+ RegisterFile* m_registerFile;
+ ScopeChainNode* m_scopeChain;
+ int m_callFrameOffset; // A negative offset indicates a non-function scope.
+ };
+
+ // This code is now defunct:
+
+ enum CodeType { GlobalCode, EvalCode, FunctionCode };
+ class OldInterpreterExecState : public ExecState {
+ public:
+ void pushSwitch() { m_switchDepth++; }
+ void popSwitch() { m_switchDepth--; }
+ bool inSwitch() const { return (m_switchDepth > 0); }
// These are only valid right after calling execute().
ComplType completionType() const { return m_completionType; }
@@ -184,70 +193,38 @@
m_completionType = Interrupted;
return 0;
}
-
- protected:
- ExecState(JSGlobalObject*, JSObject* thisObject);
- ExecState(JSGlobalObject*, JSObject* thisObject, ProgramNode*);
- ExecState(JSGlobalObject*, JSObject* thisObject, EvalNode*, ExecState* callingExecState, const ScopeChain&, JSVariableObject*);
- ExecState(JSGlobalObject*, JSObject* thisObject, JSObject* globalThisValue, FunctionBodyNode*, ExecState* callingExecState, FunctionImp*, const List& args);
- ~ExecState();
-
- // ExecStates are always stack-allocated, and the garbage collector
- // marks the stack, so we don't need to protect the objects below from GC.
-
- JSGlobalObject* m_globalObject;
- JSValue* m_exception;
-
- ExecState* m_callingExec;
-
- const PerThreadData* m_perThreadData;
-
- ScopeNode* m_scopeNode;
+ CodeType codeType() { return m_codeType; }
+ void pushIteration() { m_iterationDepth++; }
+ void popIteration() { m_iterationDepth--; }
+ bool inIteration() const { return (m_iterationDepth > 0); }
+ LabelStack& seenLabels() { return m_labelStack; }
+ void pushScope(JSObject* s) { m_scopeChain.push(s); }
+ void popScope() { m_scopeChain.pop(); }
+ JSVariableObject* variableObject() const { ASSERT_NOT_REACHED(); return m_variableObject; }
+ void setVariableObject(JSVariableObject* v) { m_variableObject = v; }
+ ExecState* callingExecState() { return m_callingExec; }
+ ScopeNode* scopeNode() { return m_scopeNode; }
+ const List* arguments() const { return m_arguments; }
+ FunctionImp* function() const { return m_function; }
+ LocalStorage& localStorage() { ASSERT_NOT_REACHED(); return *(LocalStorage*)0; }
+ void setLocalStorage(LocalStorage*) { ASSERT_NOT_REACHED(); }
+ ScopeChain& scopeChain() { return m_scopeChain; }
+ JSObject* thisValue() const { return m_thisValue; }
- FunctionImp* m_function;
- const List* m_arguments;
- ActivationImp* m_activation;
- LocalStorage* m_localStorage;
-
- ScopeChain m_scopeChain;
- ScopeChainNode m_inlineScopeChainNode;
- JSVariableObject* m_variableObject;
-
- JSObject* m_thisValue;
- JSObject* m_globalThisValue;
-
- LabelStack m_labelStack;
- int m_iterationDepth;
- int m_switchDepth;
- CodeType m_codeType;
-
ComplType m_completionType;
const Identifier* m_breakOrContinueTarget;
- };
-
- class GlobalExecState : public ExecState {
- public:
- GlobalExecState(JSGlobalObject*, JSObject* thisObject);
- ~GlobalExecState();
- };
-
- class InterpreterExecState : public ExecState {
- public:
- InterpreterExecState(JSGlobalObject*, JSObject* thisObject, ProgramNode*);
- ~InterpreterExecState();
- };
-
- class EvalExecState : public ExecState {
- public:
- EvalExecState(JSGlobalObject*, JSObject* thisObj, EvalNode*, ExecState* callingExec, const ScopeChain&, JSVariableObject*);
- ~EvalExecState();
- };
-
- class FunctionExecState : public ExecState {
- public:
- FunctionExecState(JSGlobalObject*, JSObject* thisObject, JSObject* globalThisValue, FunctionBodyNode*,
- ExecState* callingExecState, FunctionImp*, const List& args);
- ~FunctionExecState();
+ int m_switchDepth;
+ CodeType m_codeType;
+ int m_iterationDepth;
+ LabelStack m_labelStack;
+ ScopeChainNode m_inlineScopeChainNode;
+ ScopeChain m_scopeChain;
+ JSVariableObject* m_variableObject;
+ ScopeNode* m_scopeNode;
+ const List* m_arguments;
+ FunctionImp* m_function;
+ ExecState* m_callingExec;
+ JSObject* m_thisValue;
};
} // namespace KJS
diff --git a/JavaScriptCore/kjs/ExecStateInlines.h b/JavaScriptCore/kjs/ExecStateInlines.h
deleted file mode 100644
index c0d29e5..0000000
--- a/JavaScriptCore/kjs/ExecStateInlines.h
+++ /dev/null
@@ -1,95 +0,0 @@
-// -*- mode: c++; c-basic-offset: 4 -*-
-/*
- * Copyright (C) 1999-2001 Harri Porten (porten@kde.org)
- * Copyright (C) 2001 Peter Kelly (pmk@post.com)
- * Copyright (C) 2003, 2007, 2008 Apple Inc. All rights reserved.
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Library General Public
- * License as published by the Free Software Foundation; either
- * version 2 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Library General Public License for more details.
- *
- * You should have received a copy of the GNU Library General Public License
- * along with this library; see the file COPYING.LIB. If not, write to
- * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
- * Boston, MA 02110-1301, USA.
- *
- */
-
-#ifndef ExecStateInlines_h
-#define ExecStateInlines_h
-
-#include "ExecState.h"
-#include "function.h"
-#include "JSGlobalObject.h"
-
-namespace KJS {
-
- inline ExecState::ExecState(JSGlobalObject* globalObject, JSObject* thisObject, JSObject* globalThisValue,
- FunctionBodyNode* functionBodyNode, ExecState* callingExec,
- FunctionImp* func, const List& args)
- : m_globalObject(globalObject)
- , m_exception(0)
- , m_callingExec(callingExec)
- , m_perThreadData(callingExec->m_perThreadData)
- , m_scopeNode(functionBodyNode)
- , m_function(func)
- , m_arguments(&args)
- , m_scopeChain(func->scope())
- , m_inlineScopeChainNode(0, 0)
- , m_thisValue(thisObject)
- , m_globalThisValue(globalThisValue)
- , m_iterationDepth(0)
- , m_switchDepth(0)
- , m_codeType(FunctionCode)
- {
- ASSERT(m_scopeNode);
-
- ActivationImp* activation = globalObject->pushActivation(this);
- m_activation = activation;
- m_localStorage = &activation->localStorage();
- m_variableObject = activation;
- if (functionBodyNode->usesEval() || functionBodyNode->needsClosure())
- m_scopeChain.push(activation);
- else {
- m_inlineScopeChainNode.object = activation;
- // The ScopeChain will ref this node itself, so we don't need to worry about
- // anything trying to delete our scopenode
- m_scopeChain.push(&m_inlineScopeChainNode);
- }
- }
-
- inline ExecState::~ExecState()
- {
- }
-
- inline FunctionExecState::FunctionExecState(JSGlobalObject* globalObject, JSObject* thisObject, JSObject* globalThisValue,
- FunctionBodyNode* functionBodyNode, ExecState* callingExec,
- FunctionImp* func, const List& args)
- : ExecState(globalObject, thisObject, globalThisValue, functionBodyNode, callingExec, func, args)
- {
- m_globalObject->activeExecStates().append(this);
- }
-
- inline FunctionExecState::~FunctionExecState()
- {
- ASSERT(m_globalObject->activeExecStates().last() == this);
- m_globalObject->activeExecStates().removeLast();
-
- if (m_activation->needsPop())
- m_globalObject->popActivation();
-
- if (m_inlineScopeChainNode.next) {
- m_scopeChain.popInlineScopeNode();
- m_inlineScopeChainNode.next = 0;
- }
- }
-
-} // namespace KJS
-
-#endif // ExecStateInlines_h
diff --git a/JavaScriptCore/kjs/JSActivation.cpp b/JavaScriptCore/kjs/JSActivation.cpp
new file mode 100644
index 0000000..66961fd
--- /dev/null
+++ b/JavaScriptCore/kjs/JSActivation.cpp
@@ -0,0 +1,192 @@
+/*
+ * Copyright (C) 2008 Apple Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of Apple Computer, Inc. ("Apple") nor the names of
+ * its contributors may be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE AND ITS CONTRIBUTORS "AS IS" AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL APPLE OR ITS CONTRIBUTORS BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include "config.h"
+#include "JSActivation.h"
+
+#include "CodeBlock.h"
+#include "Machine.h"
+#include "Register.h"
+#include "function.h"
+
+namespace KJS {
+
+const ClassInfo JSActivation::info = { "JSActivation", 0, 0, 0 };
+
+JSActivation::JSActivation(PassRefPtr<FunctionBodyNode> functionBody, Register** registerBase, int registerOffset)
+ : Base(new JSActivationData(functionBody, registerBase, registerOffset))
+{
+}
+
+JSActivation::~JSActivation()
+{
+ delete d()->registerArray;
+ delete d();
+}
+
+void JSActivation::copyRegisters()
+{
+ int numRegisters = d()->functionBody->generatedCode().numLocals;
+ if (!numRegisters)
+ return;
+
+ Register* registerArray = static_cast<Register*>(fastMalloc(numRegisters * sizeof(Register)));
+
+ Register* end = registers();
+ Register* src = end - numRegisters;
+ Register* dst = registerArray;
+ while (src != end)
+ *dst++ = *src++;
+
+ d()->registerArray = registerArray;
+ d()->registerBase = &d()->registerArray;
+ d()->registerOffset = numRegisters;
+}
+
+bool JSActivation::getOwnPropertySlot(ExecState* exec, const Identifier& propertyName, PropertySlot& slot)
+{
+ if (symbolTableGet(propertyName, slot))
+ return true;
+
+ if (JSValue** location = getDirectLocation(propertyName)) {
+ slot.setValueSlot(this, location);
+ return true;
+ }
+
+ // Only return the built-in arguments object if it wasn't overridden above.
+ if (propertyName == exec->propertyNames().arguments) {
+ slot.setCustom(this, getArgumentsGetter());
+ return true;
+ }
+
+ // We don't call through to JSObject because there's no way to give an
+ // activation object getter properties or a prototype.
+ ASSERT(!_prop.hasGetterSetterProperties());
+ ASSERT(prototype() == jsNull());
+ return false;
+}
+
+void JSActivation::put(ExecState*, const Identifier& propertyName, JSValue* value)
+{
+ if (symbolTablePut(propertyName, value))
+ return;
+
+ // We don't call through to JSObject because __proto__ and getter/setter
+ // properties are non-standard extensions that other implementations do not
+ // expose in the activation object.
+ ASSERT(!_prop.hasGetterSetterProperties());
+ _prop.put(propertyName, value, 0, true);
+}
+
+// FIXME: Make this function honor ReadOnly (const) and DontEnum
+void JSActivation::putWithAttributes(ExecState*, const Identifier& propertyName, JSValue* value, unsigned attributes)
+{
+ if (symbolTablePutWithAttributes(propertyName, value, attributes))
+ return;
+
+ // We don't call through to JSObject because __proto__ and getter/setter
+ // properties are non-standard extensions that other implementations do not
+ // expose in the activation object.
+ ASSERT(!_prop.hasGetterSetterProperties());
+ _prop.put(propertyName, value, attributes, true);
+}
+
+bool JSActivation::deleteProperty(ExecState* exec, const Identifier& propertyName)
+{
+ if (propertyName == exec->propertyNames().arguments)
+ return false;
+
+ return Base::deleteProperty(exec, propertyName);
+}
+
+JSObject* JSActivation::toThisObject(ExecState* exec) const
+{
+ return exec->globalThisValue();
+}
+
+void JSActivation::mark()
+{
+ Base::mark();
+
+ if (d()->argumentsObject)
+ d()->argumentsObject->mark();
+
+ // No need to mark our values if they're still in the regsiter file, since
+ // the register file gets marked independently.
+ if(!d()->registerArray)
+ return;
+
+ int numRegisters = d()->functionBody->generatedCode().numLocals;
+ Register* end = d()->registerArray + numRegisters;
+ for (Register* it = d()->registerArray; it != end; ++it) {
+ JSValue* v = (*it).u.jsValue;
+ if (!v->marked())
+ v->mark();
+ }
+}
+
+bool JSActivation::isActivationObject() const
+{
+ return true;
+}
+
+bool JSActivation::isDynamicScope() const
+{
+ return d()->functionBody->usesEval();
+}
+
+JSValue* JSActivation::argumentsGetter(ExecState* exec, JSObject*, const Identifier&, const PropertySlot& slot)
+{
+ JSActivation* thisObj = static_cast<JSActivation*>(slot.slotBase());
+ if (!thisObj->d()->argumentsObject)
+ thisObj->d()->argumentsObject = thisObj->createArgumentsObject(exec);
+
+ return thisObj->d()->argumentsObject;
+}
+
+// These two functions serve the purpose of isolating the common case from a
+// PIC branch.
+
+PropertySlot::GetValueFunc JSActivation::getArgumentsGetter()
+{
+ return argumentsGetter;
+}
+
+JSObject* JSActivation::createArgumentsObject(ExecState* exec)
+{
+ Register* callFrame = registers() - d()->functionBody->generatedCode().numLocals - Machine::CallFrameHeaderSize;
+
+ FunctionImp* function;
+ Register* argv;
+ int argc;
+ exec->machine()->getFunctionAndArguments(registerBase(), callFrame, function, argv, argc);
+ List args(&argv->u.jsValue, argc);
+ return new Arguments(exec, function, args, this);
+}
+
+} // namespace KJS
diff --git a/JavaScriptCore/kjs/JSActivation.h b/JavaScriptCore/kjs/JSActivation.h
new file mode 100644
index 0000000..a6a269d
--- /dev/null
+++ b/JavaScriptCore/kjs/JSActivation.h
@@ -0,0 +1,88 @@
+/*
+ * Copyright (C) 2008 Apple Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of Apple Computer, Inc. ("Apple") nor the names of
+ * its contributors may be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE AND ITS CONTRIBUTORS "AS IS" AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL APPLE OR ITS CONTRIBUTORS BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef JSActivation_h
+#define JSActivation_h
+
+#include "JSVariableObject.h"
+#include "SymbolTable.h"
+#include "nodes.h"
+
+namespace KJS {
+
+ class Register;
+
+ class JSActivation : public JSVariableObject {
+ typedef JSVariableObject Base;
+ public:
+ JSActivation(PassRefPtr<FunctionBodyNode>, Register**, int registerOffset);
+ virtual ~JSActivation();
+
+ virtual bool isActivationObject() const;
+ virtual bool isDynamicScope() const;
+
+ virtual bool getOwnPropertySlot(ExecState*, const Identifier&, PropertySlot&);
+
+ virtual void put(ExecState*, const Identifier&, JSValue*);
+ virtual void putWithAttributes(ExecState*, const Identifier&, JSValue*, unsigned attributes);
+ virtual bool deleteProperty(ExecState*, const Identifier& propertyName);
+
+ virtual JSObject* toThisObject(ExecState*) const;
+
+ virtual void mark();
+
+ void copyRegisters();
+
+ virtual const ClassInfo* classInfo() const { return &info; }
+ static const ClassInfo info;
+
+ private:
+ struct JSActivationData : public JSVariableObjectData {
+ JSActivationData(PassRefPtr<FunctionBodyNode> functionBody_, Register** registerBase, int registerOffset)
+ : JSVariableObjectData(&functionBody_->symbolTable(), registerBase, registerOffset)
+ , registerArray(0)
+ , functionBody(functionBody_)
+ , argumentsObject(0)
+ {
+ }
+
+ Register* registerArray;
+ RefPtr<FunctionBodyNode> functionBody; // Owns the symbol table and code block
+ JSObject* argumentsObject;
+ };
+
+ static JSValue* argumentsGetter(ExecState*, JSObject*, const Identifier&, const PropertySlot&);
+ NEVER_INLINE PropertySlot::GetValueFunc getArgumentsGetter();
+ NEVER_INLINE JSObject* createArgumentsObject(ExecState*);
+
+ JSActivationData* d() const { return static_cast<JSActivationData*>(JSVariableObject::d); }
+ };
+
+} // namespace KJS
+
+#endif // JSActivation_h
diff --git a/JavaScriptCore/kjs/JSGlobalObject.cpp b/JavaScriptCore/kjs/JSGlobalObject.cpp
index 37ebdcd..55ea9de 100644
--- a/JavaScriptCore/kjs/JSGlobalObject.cpp
+++ b/JavaScriptCore/kjs/JSGlobalObject.cpp
@@ -30,7 +30,7 @@
#include "config.h"
#include "JSGlobalObject.h"
-#include "Activation.h"
+#include "CodeBlock.h"
#include "array_object.h"
#include "bool_object.h"
#include "date_object.h"
@@ -104,15 +104,6 @@
JSGlobalObject* JSGlobalObject::s_head = 0;
-void JSGlobalObject::deleteActivationStack()
-{
- ActivationStackNode* prevNode = 0;
- for (ActivationStackNode* currentNode = d()->activations; currentNode; currentNode = prevNode) {
- prevNode = currentNode->prev;
- delete currentNode;
- }
-}
-
JSGlobalObject::~JSGlobalObject()
{
ASSERT(JSLock::currentThreadIsHoldingLock());
@@ -125,8 +116,10 @@
s_head = d()->next;
if (s_head == this)
s_head = 0;
-
- deleteActivationStack();
+
+ HashSet<ProgramCodeBlock*>::const_iterator end = codeBlocks().end();
+ for (HashSet<ProgramCodeBlock*>::const_iterator it = codeBlocks().begin(); it != end; ++it)
+ (*it)->globalObject = 0;
delete d();
}
@@ -205,11 +198,6 @@
d()->recursion = 0;
d()->debugger = 0;
- ActivationStackNode* newStackNode = new ActivationStackNode;
- newStackNode->prev = 0;
- d()->activations = newStackNode;
- d()->activationCount = 0;
-
d()->perThreadData.arrayTable = &threadClassInfoHashTables()->arrayTable;
d()->perThreadData.dateTable = &threadClassInfoHashTables()->dateTable;
d()->perThreadData.mathTable = &threadClassInfoHashTables()->mathTable;
@@ -219,20 +207,13 @@
d()->perThreadData.stringTable = &threadClassInfoHashTables()->stringTable;
d()->perThreadData.propertyNames = CommonIdentifiers::shared();
- d()->globalExec.set(new GlobalExecState(this, thisValue));
+ d()->globalExec.set(new ExecState(this, thisValue, d()->globalScopeChain.node()));
d()->pageGroupIdentifier = 0;
reset(prototype());
}
-bool JSGlobalObject::getOwnPropertySlot(ExecState* exec, const Identifier& propertyName, PropertySlot& slot)
-{
- if (symbolTableGet(propertyName, slot))
- return true;
- return JSVariableObject::getOwnPropertySlot(exec, propertyName, slot);
-}
-
void JSGlobalObject::put(ExecState* exec, const Identifier& propertyName, JSValue* value)
{
if (symbolTablePut(propertyName, value))
@@ -268,7 +249,8 @@
// dangerous. (The allocations below may cause a GC.)
_prop.clear();
- localStorage().clear();
+ registerFileStack().current()->clear();
+ registerFileStack().current()->addGlobalSlots(1);
symbolTable().clear();
// Prototypes
@@ -389,21 +371,14 @@
putDirect("URIError", d()->URIErrorConstructor);
// Set global values.
- Identifier mathIdent = "Math";
- JSValue* mathObject = new MathObjectImp(exec, d()->objectPrototype);
- symbolTableInsert(mathIdent, mathObject, DontEnum | DontDelete);
-
- Identifier nanIdent = "NaN";
- JSValue* nanValue = jsNaN();
- symbolTableInsert(nanIdent, nanValue, DontEnum | DontDelete);
-
- Identifier infinityIdent = "Infinity";
- JSValue* infinityValue = jsNumber(Inf);
- symbolTableInsert(infinityIdent, infinityValue, DontEnum | DontDelete);
-
- Identifier undefinedIdent = "undefined";
- JSValue* undefinedValue = jsUndefined();
- symbolTableInsert(undefinedIdent, undefinedValue, DontEnum | DontDelete);
+ GlobalPropertyInfo staticGlobals[] = {
+ GlobalPropertyInfo("Math", new MathObjectImp(exec, d()->objectPrototype), DontEnum | DontDelete),
+ GlobalPropertyInfo("NaN", jsNaN(), DontEnum | DontDelete),
+ GlobalPropertyInfo("Infinity", jsNumber(Inf), DontEnum | DontDelete),
+ GlobalPropertyInfo("undefined", jsUndefined(), DontEnum | DontDelete)
+ };
+
+ addStaticGlobals(staticGlobals, sizeof(staticGlobals) / sizeof(GlobalPropertyInfo));
// Set global functions.
@@ -492,10 +467,12 @@
void JSGlobalObject::mark()
{
JSVariableObject::mark();
+
+ HashSet<ProgramCodeBlock*>::const_iterator end = codeBlocks().end();
+ for (HashSet<ProgramCodeBlock*>::const_iterator it = codeBlocks().begin(); it != end; ++it)
+ (*it)->mark();
- ExecStateStack::const_iterator end = d()->activeExecStates.end();
- for (ExecStateStack::const_iterator it = d()->activeExecStates.begin(); it != end; ++it)
- (*it)->m_scopeChain.mark();
+ registerFileStack().mark();
markIfNeeded(d()->globalExec->exception());
@@ -544,28 +521,6 @@
return d()->globalExec.get();
}
-void JSGlobalObject::tearOffActivation(ExecState* exec, bool leaveRelic)
-{
- ActivationImp* oldActivation = exec->activationObject();
- if (!oldActivation || !oldActivation->isOnStack())
- return;
-
- ASSERT(exec->codeType() == FunctionCode);
- ActivationImp* newActivation = new ActivationImp(*oldActivation->d(), leaveRelic);
-
- if (!leaveRelic) {
- checkActivationCount();
- d()->activationCount--;
- }
-
- oldActivation->d()->localStorage.shrink(0);
-
- exec->setActivationObject(newActivation);
- exec->setVariableObject(newActivation);
- exec->setLocalStorage(&newActivation->localStorage());
- exec->replaceScopeChainTop(newActivation);
-}
-
bool JSGlobalObject::isDynamicScope() const
{
return true;
diff --git a/JavaScriptCore/kjs/JSGlobalObject.h b/JavaScriptCore/kjs/JSGlobalObject.h
index dbfe3f9..1ce515c 100644
--- a/JavaScriptCore/kjs/JSGlobalObject.h
+++ b/JavaScriptCore/kjs/JSGlobalObject.h
@@ -1,7 +1,7 @@
// -*- c-basic-offset: 4 -*-
/*
* Copyright (C) 2007 Eric Seidel <eric@webkit.org>
- * Copyright (C) 2007 Apple Inc. All rights reserved.
+ * Copyright (C) 2007, 2008 Apple Inc. All rights reserved.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Library General Public
@@ -24,11 +24,13 @@
#define KJS_GlobalObject_h
#include "JSVariableObject.h"
-#include "Activation.h"
+#include "RegisterFile.h"
+#include "RegisterFileStack.h"
+#include <wtf/HashSet.h>
+#include <wtf/OwnPtr.h>
namespace KJS {
- class ActivationImp;
class ArrayObjectImp;
class ArrayPrototype;
class BooleanObjectImp;
@@ -50,6 +52,7 @@
class NumberPrototype;
class ObjectObjectImp;
class ObjectPrototype;
+ class ProgramCodeBlock;
class PrototypeReflexiveFunction;
class RangeError;
class RangeErrorPrototype;
@@ -77,8 +80,10 @@
using JSVariableObject::JSVariableObjectData;
struct JSGlobalObjectData : public JSVariableObjectData {
- JSGlobalObjectData()
- : JSVariableObjectData(&inlineSymbolTable)
+ JSGlobalObjectData(JSGlobalObject* globalObject, JSObject* thisValue)
+ : JSVariableObjectData(&symbolTable, registerFileStack.globalBasePointer(), 0)
+ , globalScopeChain(globalObject)
+ , globalExec(new ExecState(globalObject, thisValue, globalScopeChain.node()))
{
}
@@ -87,7 +92,10 @@
Debugger* debugger;
- OwnPtr<GlobalExecState> globalExec;
+ RegisterFileStack registerFileStack;
+ ScopeChain globalScopeChain;
+ OwnPtr<ExecState> globalExec;
+
int recursion;
unsigned timeoutTime;
@@ -131,30 +139,26 @@
NativeErrorPrototype* typeErrorPrototype;
NativeErrorPrototype* URIErrorPrototype;
- SymbolTable inlineSymbolTable;
-
- ExecStateStack activeExecStates;
-
- ActivationStackNode* activations;
- size_t activationCount;
-
+ SymbolTable symbolTable;
unsigned pageGroupIdentifier;
- OwnPtr<HashSet<JSObject*> > arrayVisitedElements; // Global data shared by array prototype functions.
-
PerThreadData perThreadData;
+
+ HashSet<ProgramCodeBlock*> codeBlocks;
+
+ OwnPtr<HashSet<JSObject*> > arrayVisitedElements; // Global data shared by array prototype functions.
};
public:
JSGlobalObject()
- : JSVariableObject(new JSGlobalObjectData)
+ : JSVariableObject(new JSGlobalObjectData(this, this))
{
init(this);
}
protected:
JSGlobalObject(JSValue* proto, JSObject* globalThisValue)
- : JSVariableObject(proto, new JSGlobalObjectData)
+ : JSVariableObject(proto, new JSGlobalObjectData(this, globalThisValue))
{
init(globalThisValue);
}
@@ -163,6 +167,7 @@
virtual ~JSGlobalObject();
virtual bool getOwnPropertySlot(ExecState*, const Identifier&, PropertySlot&);
+ virtual bool getOwnPropertySlot(ExecState*, const Identifier&, PropertySlot&, bool& slotIsWriteable);
virtual void put(ExecState*, const Identifier&, JSValue*);
virtual void putWithAttributes(ExecState*, const Identifier& propertyName, JSValue* value, unsigned attributes);
@@ -227,6 +232,8 @@
int recursion() { return d()->recursion; }
void incRecursion() { ++d()->recursion; }
void decRecursion() { --d()->recursion; }
+
+ ScopeChain& globalScopeChain() { return d()->globalScopeChain; }
virtual void mark();
@@ -239,16 +246,14 @@
virtual bool allowsAccessFrom(const JSGlobalObject*) const { return true; }
- ActivationImp* pushActivation(ExecState*);
- void popActivation();
- void tearOffActivation(ExecState*, bool markAsRelic = false);
-
virtual bool isDynamicScope() const;
- ExecStateStack& activeExecStates() const { return d()->activeExecStates; }
-
HashSet<JSObject*>& arrayVisitedElements() { if (!d()->arrayVisitedElements) d()->arrayVisitedElements.set(new HashSet<JSObject*>); return *d()->arrayVisitedElements; }
+ HashSet<ProgramCodeBlock*>& codeBlocks() { return d()->codeBlocks; }
+
+ RegisterFileStack& registerFileStack() { return d()->registerFileStack; }
+
// Per-thread hash tables, cached on the global object for faster access.
const PerThreadData* perThreadData() const { return &d()->perThreadData; }
@@ -260,15 +265,55 @@
JSGlobalObjectData* d() const { return static_cast<JSGlobalObjectData*>(JSVariableObject::d); }
+ struct GlobalPropertyInfo {
+ GlobalPropertyInfo(const Identifier& i, JSValue* v, unsigned a)
+ : identifier(i)
+ , value(v)
+ , attributes(a)
+ {
+ }
+
+ const Identifier& identifier;
+ JSValue* value;
+ unsigned attributes;
+ };
+ void addStaticGlobals(GlobalPropertyInfo*, int count);
+
bool checkTimeout();
void resetTimeoutCheck();
- void deleteActivationStack();
- void checkActivationCount();
-
static JSGlobalObject* s_head;
};
+ inline void JSGlobalObject::addStaticGlobals(GlobalPropertyInfo* globals, int count)
+ {
+ RegisterFile* registerFile = registerFileStack().current();
+ ASSERT(registerFile->safeForReentry() && registerFile->isGlobal() && !registerFile->size());
+ int index = -registerFile->numGlobalSlots() - 1;
+ registerFile->addGlobalSlots(count);
+ for (int i = 0; i < count; ++i) {
+ ASSERT(globals[i].attributes & DontDelete);
+ SymbolTableEntry newEntry(index, globals[i].attributes);
+ symbolTable().add(globals[i].identifier.ustring().rep(), newEntry);
+ valueAt(index) = globals[i].value;
+ --index;
+ }
+ }
+
+ inline bool JSGlobalObject::getOwnPropertySlot(ExecState* exec, const Identifier& propertyName, PropertySlot& slot)
+ {
+ if (JSVariableObject::getOwnPropertySlot(exec, propertyName, slot))
+ return true;
+ return symbolTableGet(propertyName, slot);
+ }
+
+ inline bool JSGlobalObject::getOwnPropertySlot(ExecState* exec, const Identifier& propertyName, PropertySlot& slot, bool& slotIsWriteable)
+ {
+ if (JSVariableObject::getOwnPropertySlotForWrite(exec, propertyName, slot, slotIsWriteable))
+ return true;
+ return symbolTableGet(propertyName, slot, slotIsWriteable);
+ }
+
inline bool JSGlobalObject::timedOut()
{
d()->tickCount++;
@@ -279,35 +324,11 @@
return checkTimeout();
}
- inline ActivationImp* JSGlobalObject::pushActivation(ExecState* exec)
+ inline JSGlobalObject* ScopeChainNode::globalObject() const
{
- if (d()->activationCount == activationStackNodeSize) {
- ActivationStackNode* newNode = new ActivationStackNode;
- newNode->prev = d()->activations;
- d()->activations = newNode;
- d()->activationCount = 0;
- }
-
- StackActivation* stackEntry = &d()->activations->data[d()->activationCount++];
- stackEntry->activationStorage.init(exec);
- return &stackEntry->activationStorage;
- }
-
- inline void JSGlobalObject::checkActivationCount()
- {
- if (!d()->activationCount) {
- ActivationStackNode* prev = d()->activations->prev;
- ASSERT(prev);
- delete d()->activations;
- d()->activations = prev;
- d()->activationCount = activationStackNodeSize;
- }
- }
-
- inline void JSGlobalObject::popActivation()
- {
- checkActivationCount();
- d()->activations->data[--d()->activationCount].activationDataStorage.localStorage.shrink(0);
+ JSGlobalObject* globalObject = static_cast<JSGlobalObject*>(bottom());
+ ASSERT(globalObject->isGlobalObject());
+ return globalObject;
}
} // namespace KJS
diff --git a/JavaScriptCore/kjs/JSImmediate.cpp b/JavaScriptCore/kjs/JSImmediate.cpp
index 5f4a108..e416729 100644
--- a/JavaScriptCore/kjs/JSImmediate.cpp
+++ b/JavaScriptCore/kjs/JSImmediate.cpp
@@ -23,6 +23,7 @@
#include "JSGlobalObject.h"
#include "bool_object.h"
+#include "JSNotAnObject.h"
#include "number_object.h"
#include "object.h"
@@ -32,9 +33,9 @@
{
ASSERT(isImmediate(v));
if (v == jsNull())
- return throwError(exec, TypeError, "Null value");
+ return new JSNotAnObject(throwError(exec, TypeError, "Null value"));
else if (v == jsUndefined())
- return throwError(exec, TypeError, "Undefined value");
+ return new JSNotAnObject(throwError(exec, TypeError, "Undefined value"));
else if (isBoolean(v)) {
List args;
args.append(const_cast<JSValue *>(v));
@@ -62,14 +63,4 @@
return UString::from(getTruncatedInt32(v));
}
-JSType JSImmediate::type(const JSValue *v)
-{
- ASSERT(isImmediate(v));
-
- uintptr_t tag = getTag(v);
- if (tag == UndefinedType)
- return v == jsUndefined() ? UndefinedType : NullType;
- return static_cast<JSType>(tag);
-}
-
} // namespace KJS
diff --git a/JavaScriptCore/kjs/JSImmediate.h b/JavaScriptCore/kjs/JSImmediate.h
index bc0cb16..3ab6a20 100644
--- a/JavaScriptCore/kjs/JSImmediate.h
+++ b/JavaScriptCore/kjs/JSImmediate.h
@@ -122,6 +122,8 @@
static JSValue* falseImmediate();
static JSValue* undefinedImmediate();
static JSValue* nullImmediate();
+
+ static JSValue* impossibleValue();
private:
static const uintptr_t TagMask = 3; // type tags are 2 bits long
@@ -152,6 +154,9 @@
ALWAYS_INLINE JSValue* JSImmediate::undefinedImmediate() { return tag(1 << 2, UndefinedType); }
ALWAYS_INLINE JSValue* JSImmediate::nullImmediate() { return tag(0, UndefinedType); }
+// This value is impossible because 0x4 is not a valid pointer but a tag of 0 would indicate non-immediate
+ALWAYS_INLINE JSValue* JSImmediate::impossibleValue() { return tag(1 << 2, 0); }
+
ALWAYS_INLINE bool JSImmediate::toBoolean(const JSValue* v)
{
ASSERT(isImmediate(v));
@@ -273,6 +278,16 @@
return getUInt32(v, i);
}
+ALWAYS_INLINE JSType JSImmediate::type(const JSValue* v)
+{
+ ASSERT(isImmediate(v));
+
+ uintptr_t tag = getTag(v);
+ if (tag == UndefinedType)
+ return v == undefinedImmediate() ? UndefinedType : NullType;
+ return static_cast<JSType>(tag);
+}
+
} // namespace KJS
#endif
diff --git a/JavaScriptCore/kjs/JSNotAnObject.cpp b/JavaScriptCore/kjs/JSNotAnObject.cpp
new file mode 100644
index 0000000..4c02c16
--- /dev/null
+++ b/JavaScriptCore/kjs/JSNotAnObject.cpp
@@ -0,0 +1,161 @@
+/*
+ * Copyright (C) 2008 Apple Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of Apple Computer, Inc. ("Apple") nor the names of
+ * its contributors may be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE AND ITS CONTRIBUTORS "AS IS" AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL APPLE OR ITS CONTRIBUTORS BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+
+#include "config.h"
+#include "JSNotAnObject.h"
+
+#include <wtf/UnusedParam.h>
+
+namespace KJS {
+ // JSValue methods
+ JSValue *JSNotAnObject::toPrimitive(ExecState* exec, JSType) const
+ {
+ UNUSED_PARAM(exec);
+ ASSERT(exec->hadException() && exec->exception() == m_exception);
+ return m_exception;
+ }
+
+ bool JSNotAnObject::getPrimitiveNumber(ExecState* exec, double&, JSValue*&)
+ {
+ UNUSED_PARAM(exec);
+ ASSERT(exec->hadException() && exec->exception() == m_exception);
+ return false;
+ }
+
+ bool JSNotAnObject::toBoolean(ExecState* exec) const
+ {
+ UNUSED_PARAM(exec);
+ ASSERT(exec->hadException() && exec->exception() == m_exception);
+ return false;
+ }
+
+ double JSNotAnObject::toNumber(ExecState* exec) const
+ {
+ UNUSED_PARAM(exec);
+ ASSERT(exec->hadException() && exec->exception() == m_exception);
+ return NaN;
+ }
+
+ UString JSNotAnObject::toString(ExecState* exec) const
+ {
+ UNUSED_PARAM(exec);
+ ASSERT(exec->hadException() && exec->exception() == m_exception);
+ return "";
+ }
+
+ JSObject *JSNotAnObject::toObject(ExecState* exec) const
+ {
+ UNUSED_PARAM(exec);
+ ASSERT(exec->hadException() && exec->exception() == m_exception);
+ return m_exception;
+ }
+
+ // marking
+ void JSNotAnObject::mark()
+ {
+ JSCell::mark();
+ if (!m_exception->marked())
+ m_exception->mark();
+ }
+
+ bool JSNotAnObject::getOwnPropertySlot(ExecState* exec, const Identifier&, PropertySlot&)
+ {
+ UNUSED_PARAM(exec);
+ ASSERT(exec->hadException() && exec->exception() == m_exception);
+ return false;
+ }
+
+ bool JSNotAnObject::getOwnPropertySlot(ExecState* exec, unsigned, PropertySlot&)
+ {
+ UNUSED_PARAM(exec);
+ ASSERT(exec->hadException() && exec->exception() == m_exception);
+ return false;
+ }
+
+ void JSNotAnObject::put(ExecState* exec, const Identifier& , JSValue*)
+ {
+ UNUSED_PARAM(exec);
+ ASSERT(exec->hadException() && exec->exception() == m_exception);
+ }
+
+ void JSNotAnObject::put(ExecState* exec, unsigned, JSValue*)
+ {
+ UNUSED_PARAM(exec);
+ ASSERT(exec->hadException() && exec->exception() == m_exception);
+ }
+
+ bool JSNotAnObject::deleteProperty(ExecState* exec, const Identifier &)
+ {
+ UNUSED_PARAM(exec);
+ ASSERT(exec->hadException() && exec->exception() == m_exception);
+ return false;
+ }
+
+ bool JSNotAnObject::deleteProperty(ExecState* exec, unsigned)
+ {
+ UNUSED_PARAM(exec);
+ ASSERT(exec->hadException() && exec->exception() == m_exception);
+ return false;
+ }
+
+ JSValue *JSNotAnObject::defaultValue(ExecState* exec, JSType) const
+ {
+ UNUSED_PARAM(exec);
+ ASSERT(exec->hadException() && exec->exception() == m_exception);
+ return m_exception;
+ }
+
+ JSObject* JSNotAnObject::construct(ExecState* exec, const List&)
+ {
+ UNUSED_PARAM(exec);
+ ASSERT(exec->hadException() && exec->exception() == m_exception);
+ return m_exception;
+ }
+
+ JSObject* JSNotAnObject::construct(ExecState* exec, const List&, const Identifier&, const UString&, int)
+ {
+ UNUSED_PARAM(exec);
+ ASSERT(exec->hadException() && exec->exception() == m_exception);
+ return m_exception;
+ }
+
+ JSValue* JSNotAnObject::callAsFunction(ExecState* exec, JSObject *, const List &)
+ {
+ UNUSED_PARAM(exec);
+ ASSERT(exec->hadException() && exec->exception() == m_exception);
+ return m_exception;
+ }
+
+ void JSNotAnObject::getPropertyNames(ExecState* exec, PropertyNameArray&)
+ {
+ UNUSED_PARAM(exec);
+ ASSERT(exec->hadException() && exec->exception() == m_exception);
+ }
+
+}
diff --git a/JavaScriptCore/kjs/JSNotAnObject.h b/JavaScriptCore/kjs/JSNotAnObject.h
new file mode 100644
index 0000000..c99fd4a
--- /dev/null
+++ b/JavaScriptCore/kjs/JSNotAnObject.h
@@ -0,0 +1,80 @@
+/*
+ * Copyright (C) 2008 Apple Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of Apple Computer, Inc. ("Apple") nor the names of
+ * its contributors may be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE AND ITS CONTRIBUTORS "AS IS" AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL APPLE OR ITS CONTRIBUTORS BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef JSNotAnObject_h
+#define JSNotAnObject_h
+
+#include "object.h"
+
+namespace KJS {
+
+ // This unholy class is used to allow us to avoid multiple exception checks
+ // in certain SquirrelFish opcodes -- effectively it just silently consumes
+ // any operations performed on the result of a failed toObject call.
+ class JSNotAnObject : public JSObject {
+ public:
+ JSNotAnObject(JSObject* exception)
+ : m_exception(exception)
+ {
+ }
+
+ // JSValue methods
+ virtual JSValue *toPrimitive(ExecState* exec, JSType preferredType = UnspecifiedType) const;
+ virtual bool getPrimitiveNumber(ExecState* exec, double& number, JSValue*& value);
+ virtual bool toBoolean(ExecState* exec) const;
+ virtual double toNumber(ExecState* exec) const;
+ virtual UString toString(ExecState* exec) const;
+ virtual JSObject *toObject(ExecState* exec) const;
+
+ // marking
+ virtual void mark();
+
+ virtual bool getOwnPropertySlot(ExecState* , const Identifier&, PropertySlot&);
+ virtual bool getOwnPropertySlot(ExecState* , unsigned index, PropertySlot&);
+
+ virtual void put(ExecState*, const Identifier& propertyName, JSValue* value);
+ virtual void put(ExecState*, unsigned propertyName, JSValue* value);
+
+ virtual bool deleteProperty(ExecState* exec, const Identifier &propertyName);
+ virtual bool deleteProperty(ExecState* exec, unsigned propertyName);
+
+ virtual JSValue *defaultValue(ExecState* exec, JSType hint) const;
+
+ virtual JSObject* construct(ExecState* exec, const List& args);
+ virtual JSObject* construct(ExecState* exec, const List& args, const Identifier& functionName, const UString& sourceURL, int lineNumber);
+
+ virtual JSValue *callAsFunction(ExecState* exec, JSObject *thisObj, const List &args);
+
+ virtual void getPropertyNames(ExecState*, PropertyNameArray&);
+
+ private:
+ JSObject* m_exception;
+ };
+}
+
+#endif
diff --git a/JavaScriptCore/kjs/JSVariableObject.cpp b/JavaScriptCore/kjs/JSVariableObject.cpp
index 720a7bca..51e396d 100644
--- a/JavaScriptCore/kjs/JSVariableObject.cpp
+++ b/JavaScriptCore/kjs/JSVariableObject.cpp
@@ -46,35 +46,23 @@
{
SymbolTable::const_iterator end = symbolTable().end();
for (SymbolTable::const_iterator it = symbolTable().begin(); it != end; ++it) {
- if ((localStorage()[it->second].attributes & DontEnum) == 0)
- propertyNames.add(it->first.get());
+ if (!(it->second.getAttributes() & DontEnum))
+ propertyNames.add(Identifier(it->first.get()));
}
-
+
JSObject::getPropertyNames(exec, propertyNames);
}
bool JSVariableObject::getPropertyAttributes(ExecState* exec, const Identifier& propertyName, unsigned& attributes) const
{
- size_t index = symbolTable().get(propertyName.ustring().rep());
- if (index != missingSymbolMarker()) {
- attributes = localStorage()[index].attributes;
+ SymbolTableEntry entry = symbolTable().get(propertyName.ustring().rep());
+ if (!entry.isEmpty()) {
+ attributes = entry.getAttributes() | DontDelete;
return true;
}
return JSObject::getPropertyAttributes(exec, propertyName, attributes);
}
-void JSVariableObject::mark()
-{
- JSObject::mark();
-
- size_t size = d->localStorage.size();
- for (size_t i = 0; i < size; ++i) {
- JSValue* value = d->localStorage[i].value;
- if (!value->marked())
- value->mark();
- }
-}
-
bool JSVariableObject::isVariableObject() const
{
return true;
diff --git a/JavaScriptCore/kjs/JSVariableObject.h b/JavaScriptCore/kjs/JSVariableObject.h
index ee12221..af873c4 100644
--- a/JavaScriptCore/kjs/JSVariableObject.h
+++ b/JavaScriptCore/kjs/JSVariableObject.h
@@ -29,45 +29,50 @@
#ifndef JSVariableObject_h
#define JSVariableObject_h
-#include "LocalStorageEntry.h"
+#include "Register.h"
#include "SymbolTable.h"
+#include "UnusedParam.h"
#include "object.h"
+#include <wtf/UnusedParam.h>
namespace KJS {
+ class Register;
+
class JSVariableObject : public JSObject {
public:
SymbolTable& symbolTable() const { return *d->symbolTable; }
- LocalStorage& localStorage() const { return d->localStorage; }
virtual void putWithAttributes(ExecState*, const Identifier&, JSValue*, unsigned attributes) = 0;
virtual bool deleteProperty(ExecState*, const Identifier&);
virtual void getPropertyNames(ExecState*, PropertyNameArray&);
- virtual void mark();
-
virtual bool isVariableObject() const;
virtual bool isDynamicScope() const = 0;
virtual bool getPropertyAttributes(ExecState*, const Identifier& propertyName, unsigned& attributes) const;
+ JSValue*& valueAt(int index) const { return registers()[index].u.jsValue; }
protected:
// Subclasses of JSVariableObject can subclass this struct to add data
// without increasing their own size (since there's a hard limit on the
// size of a JSCell).
struct JSVariableObjectData {
- JSVariableObjectData() { }
- JSVariableObjectData(SymbolTable* s)
- : symbolTable(s) // Subclass owns this pointer.
+ JSVariableObjectData(SymbolTable* symbolTable_, Register** registerBase_, int registerOffset_)
+ : symbolTable(symbolTable_)
+ , registerBase(registerBase_)
+ , registerOffset(registerOffset_)
{
+ ASSERT(symbolTable_);
+ ASSERT(registerBase_);
}
- LocalStorage localStorage; // Storage for variables in the symbol table.
- SymbolTable* symbolTable; // Maps name -> index in localStorage.
- };
+ SymbolTable* symbolTable; // Maps name -> offset from "r" in register file.
- JSVariableObject() { }
+ Register** registerBase; // Location where a pointer to the base of the register file is stored.
+ int registerOffset; // Offset of "r", the register past the end of local storage.
+ };
JSVariableObject(JSVariableObjectData* data)
: d(data) // Subclass owns this pointer.
@@ -80,64 +85,58 @@
{
}
+ Register** registerBase() const { return d->registerBase; }
+ Register* registers() const { return *registerBase() + d->registerOffset; }
+
bool symbolTableGet(const Identifier&, PropertySlot&);
+ bool symbolTableGet(const Identifier&, PropertySlot&, bool& slotIsWriteable);
bool symbolTablePut(const Identifier&, JSValue*);
bool symbolTablePutWithAttributes(const Identifier&, JSValue*, unsigned attributes);
- bool symbolTableInsert(const Identifier&, JSValue*, unsigned attributes);
JSVariableObjectData* d;
};
inline bool JSVariableObject::symbolTableGet(const Identifier& propertyName, PropertySlot& slot)
{
- size_t index = symbolTable().inlineGet(propertyName.ustring().rep());
- if (index == missingSymbolMarker())
- return false;
-#ifndef NDEBUG
- // During initialization, the variable object needs to advertise that it has certain
- // properties, even if they're not ready for access yet. This check verifies that
- // no one tries to access such a property. In a release build, we optimize this check
- // away and just return an invalid pointer. There's no harm in an invalid pointer,
- // since no one dereferences it.
- if (index >= d->localStorage.size()) {
- slot.setUngettable(this);
+ SymbolTableEntry entry = symbolTable().inlineGet(propertyName.ustring().rep());
+ if (!entry.isEmpty()) {
+ slot.setValueSlot(this, &valueAt(entry.getIndex()));
return true;
}
-#endif
- slot.setValueSlot(this, &d->localStorage[index].value);
- return true;
+ return false;
+ }
+
+ inline bool JSVariableObject::symbolTableGet(const Identifier& propertyName, PropertySlot& slot, bool& slotIsWriteable)
+ {
+ SymbolTableEntry entry = symbolTable().inlineGet(propertyName.ustring().rep());
+ if (!entry.isEmpty()) {
+ slot.setValueSlot(this, &valueAt(entry.getIndex()));
+ slotIsWriteable = !entry.isReadOnly();
+ return true;
+ }
+ return false;
}
inline bool JSVariableObject::symbolTablePut(const Identifier& propertyName, JSValue* value)
{
- size_t index = symbolTable().inlineGet(propertyName.ustring().rep());
- if (index == missingSymbolMarker())
+ SymbolTableEntry entry = symbolTable().inlineGet(propertyName.ustring().rep());
+ if (entry.isEmpty())
return false;
- LocalStorageEntry& entry = d->localStorage[index];
- if (entry.attributes & ReadOnly)
+ if (entry.isReadOnly())
return true;
- entry.value = value;
+ valueAt(entry.getIndex()) = value;
return true;
}
inline bool JSVariableObject::symbolTablePutWithAttributes(const Identifier& propertyName, JSValue* value, unsigned attributes)
{
- size_t index = symbolTable().get(propertyName.ustring().rep());
- if (index == missingSymbolMarker())
+ SymbolTable::iterator iter = symbolTable().find(propertyName.ustring().rep());
+ if (iter == symbolTable().end())
return false;
- LocalStorageEntry& entry = d->localStorage[index];
- entry.value = value;
- entry.attributes = attributes;
- return true;
- }
-
- inline bool JSVariableObject::symbolTableInsert(const Identifier& propertyName, JSValue* value, unsigned attributes)
- {
- if (symbolTable().get(propertyName.ustring().rep()) != missingSymbolMarker())
- return false;
- size_t localStorageIndex = d->localStorage.size();
- d->localStorage.append(LocalStorageEntry(value, attributes));
- symbolTable().add(propertyName.ustring().rep(), localStorageIndex);
+ SymbolTableEntry& entry = iter->second;
+ ASSERT(!entry.isEmpty());
+ entry.setAttributes(attributes);
+ valueAt(entry.getIndex()) = value;
return true;
}
diff --git a/JavaScriptCore/kjs/NodeInfo.h b/JavaScriptCore/kjs/NodeInfo.h
index 442dd97..3101145 100644
--- a/JavaScriptCore/kjs/NodeInfo.h
+++ b/JavaScriptCore/kjs/NodeInfo.h
@@ -30,6 +30,7 @@
const FeatureInfo NoFeatures = 0;
const FeatureInfo EvalFeature = 1 << 0;
const FeatureInfo ClosureFeature = 1 << 1;
+ const FeatureInfo AssignFeature = 1 << 2;
template <typename T> struct NodeFeatureInfo {
T m_node;
diff --git a/JavaScriptCore/kjs/Parser.cpp b/JavaScriptCore/kjs/Parser.cpp
index 5569801..e2b2563 100644
--- a/JavaScriptCore/kjs/Parser.cpp
+++ b/JavaScriptCore/kjs/Parser.cpp
@@ -24,6 +24,7 @@
#include "config.h"
#include "Parser.h"
+#include "debugger.h"
#include "lexer.h"
#include <wtf/HashSet.h>
@@ -42,23 +43,32 @@
{
}
-void Parser::parse(int startingLineNumber,
- const UChar* code, unsigned length,
- int* sourceId, int* errLine, UString* errMsg)
+void Parser::parse(ExecState* exec, const UString& sourceURL, int startingLineNumber,
+ PassRefPtr<SourceProvider> prpSource,
+ int* sourceId, int* errLine, UString* errMsg)
{
ASSERT(!m_sourceElements);
+
+ int defaultSourceId;
+ int defaultErrLine;
+ UString defaultErrMsg;
+
+ RefPtr<SourceProvider> source = prpSource;
- if (errLine)
- *errLine = -1;
- if (errMsg)
- *errMsg = 0;
+ if (!sourceId)
+ sourceId = &defaultSourceId;
+ if (!errLine)
+ errLine = &defaultErrLine;
+ if (!errMsg)
+ errMsg = &defaultErrMsg;
+
+ *errLine = -1;
+ *errMsg = 0;
Lexer& lexer = KJS::lexer();
- lexer.setCode(startingLineNumber, code, length);
- m_sourceId++;
- if (sourceId)
- *sourceId = m_sourceId;
+ lexer.setCode(startingLineNumber, source);
+ *sourceId = ++m_sourceId;
int parseError = kjsyyparse(&lexer);
bool lexError = lexer.sawError();
@@ -67,18 +77,19 @@
ParserRefCounted::deleteNewObjects();
if (parseError || lexError) {
- if (errLine)
- *errLine = lexer.lineNo();
- if (errMsg)
- *errMsg = "Parse error";
+ *errLine = lexer.lineNo();
+ *errMsg = "Parse error";
m_sourceElements.clear();
}
+
+ if (Debugger* debugger = exec->dynamicGlobalObject()->debugger())
+ debugger->sourceParsed(exec, *sourceId, sourceURL, *source, startingLineNumber, *errLine, *errMsg);
}
void Parser::didFinishParsing(SourceElements* sourceElements, ParserRefCountedData<DeclarationStacks::VarStack>* varStack,
ParserRefCountedData<DeclarationStacks::FunctionStack>* funcStack, bool usesEval, bool needsClosure, int lastLine)
{
- m_sourceElements = sourceElements ? sourceElements : new SourceElements;
+ m_sourceElements = sourceElements;
m_varDeclarations = varStack;
m_funcDeclarations = funcStack;
m_usesEval = usesEval;
diff --git a/JavaScriptCore/kjs/Parser.h b/JavaScriptCore/kjs/Parser.h
index f71eb5d8..cbfad36 100644
--- a/JavaScriptCore/kjs/Parser.h
+++ b/JavaScriptCore/kjs/Parser.h
@@ -25,11 +25,12 @@
#ifndef Parser_h
#define Parser_h
+#include "nodes.h"
+#include "SourceProvider.h"
#include <wtf/Forward.h>
#include <wtf/Noncopyable.h>
#include <wtf/OwnPtr.h>
#include <wtf/RefPtr.h>
-#include "nodes.h"
namespace WTF {
template<typename T> class ThreadSpecific;
@@ -48,9 +49,9 @@
class Parser : Noncopyable {
public:
template <class ParsedNode>
- PassRefPtr<ParsedNode> parse(const UString& sourceURL, int startingLineNumber,
- const UChar* code, unsigned length,
- int* sourceId = 0, int* errLine = 0, UString* errMsg = 0);
+ PassRefPtr<ParsedNode> parse(ExecState*, const UString& sourceURL, int startingLineNumber,
+ PassRefPtr<SourceProvider> source,
+ int* sourceId = 0, int* errLine = 0, UString* errMsg = 0);
UString sourceURL() const { return m_sourceURL; }
int sourceId() const { return m_sourceId; }
@@ -63,8 +64,8 @@
friend class WTF::ThreadSpecific<Parser>;
Parser(); // Use parser() instead.
- void parse(int startingLineNumber, const UChar* code, unsigned length,
- int* sourceId, int* errLine, UString* errMsg);
+ void parse(ExecState*, const UString& sourceURL, int startingLineNumber, PassRefPtr<SourceProvider> source,
+ int* sourceId, int* errLine, UString* errMsg);
UString m_sourceURL;
int m_sourceId;
@@ -79,12 +80,12 @@
Parser& parser(); // Returns the singleton JavaScript parser.
template <class ParsedNode>
- PassRefPtr<ParsedNode> Parser::parse(const UString& sourceURL, int startingLineNumber,
- const UChar* code, unsigned length,
- int* sourceId, int* errLine, UString* errMsg)
+ PassRefPtr<ParsedNode> Parser::parse(ExecState* exec, const UString& sourceURL, int startingLineNumber,
+ PassRefPtr<SourceProvider> source,
+ int* sourceId, int* errLine, UString* errMsg)
{
m_sourceURL = sourceURL;
- parse(startingLineNumber, code, length, sourceId, errLine, errMsg);
+ parse(exec, sourceURL, startingLineNumber, source, sourceId, errLine, errMsg);
if (!m_sourceElements) {
m_sourceURL = UString();
return 0;
diff --git a/JavaScriptCore/kjs/PropertyNameArray.h b/JavaScriptCore/kjs/PropertyNameArray.h
index 3b18b25..0d7236d 100644
--- a/JavaScriptCore/kjs/PropertyNameArray.h
+++ b/JavaScriptCore/kjs/PropertyNameArray.h
@@ -43,6 +43,7 @@
Identifier& operator[](unsigned i) { return m_vector[i]; }
const Identifier& operator[](unsigned i) const { return m_vector[i]; }
+ Identifier* releaseIdentifiers() { return size() ? m_vector.releaseBuffer() : 0; }
private:
typedef HashSet<UString::Rep*, PtrHash<UString::Rep*> > IdentifierSet;
diff --git a/JavaScriptCore/kjs/SourceProvider.h b/JavaScriptCore/kjs/SourceProvider.h
new file mode 100644
index 0000000..10d0362
--- /dev/null
+++ b/JavaScriptCore/kjs/SourceProvider.h
@@ -0,0 +1,60 @@
+/*
+ * Copyright (C) 2008 Apple Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of Apple Computer, Inc. ("Apple") nor the names of
+ * its contributors may be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE AND ITS CONTRIBUTORS "AS IS" AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL APPLE OR ITS CONTRIBUTORS BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef SourceProvider_h
+#define SourceProvider_h
+
+#include "ustring.h"
+#include <wtf/RefCounted.h>
+
+namespace KJS {
+
+ class SourceProvider : public RefCounted<SourceProvider> {
+ public:
+ virtual ~SourceProvider() {}
+ virtual UString getRange(int start, int end) const = 0;
+ virtual const UChar* data() const = 0;
+ virtual int length() const = 0;
+ };
+
+ class UStringSourceProvider : public SourceProvider {
+ public:
+ static PassRefPtr<UStringSourceProvider> create(const UString& source) { return adoptRef(new UStringSourceProvider(source)); }
+
+ UString getRange(int start, int end) const { return m_source.substr(start, end - start); }
+ const UChar* data() const { return m_source.data(); }
+ int length() const { return m_source.size(); }
+
+ private:
+ UStringSourceProvider(const UString& source) : m_source(source) {}
+ UString m_source;
+ };
+
+}
+
+#endif // SourceProvider_h
diff --git a/JavaScriptCore/kjs/SourceRange.h b/JavaScriptCore/kjs/SourceRange.h
new file mode 100644
index 0000000..20c49fc
--- /dev/null
+++ b/JavaScriptCore/kjs/SourceRange.h
@@ -0,0 +1,57 @@
+/*
+ * Copyright (C) 2008 Apple Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of Apple Computer, Inc. ("Apple") nor the names of
+ * its contributors may be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE AND ITS CONTRIBUTORS "AS IS" AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL APPLE OR ITS CONTRIBUTORS BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef SourceRange_h
+#define SourceRange_h
+
+#include "SourceProvider.h"
+#include <wtf/RefPtr.h>
+
+namespace KJS {
+
+ class SourceRange {
+ public:
+ SourceRange(PassRefPtr<SourceProvider> provider, int start, int end)
+ : m_sourceProvider(provider)
+ , m_startChar(start)
+ , m_endChar(end)
+ {
+ }
+ SourceRange() {}
+
+ UString toString() const { if (!m_sourceProvider) return UString(); return m_sourceProvider->getRange(m_startChar, m_endChar); }
+
+ private:
+ RefPtr<SourceProvider> m_sourceProvider;
+ int m_startChar;
+ int m_endChar;
+ };
+
+}
+
+#endif // SourceRange_h
diff --git a/JavaScriptCore/kjs/SymbolTable.h b/JavaScriptCore/kjs/SymbolTable.h
index d046a2e..768693b 100644
--- a/JavaScriptCore/kjs/SymbolTable.h
+++ b/JavaScriptCore/kjs/SymbolTable.h
@@ -29,6 +29,7 @@
#ifndef SymbolTable_h
#define SymbolTable_h
+#include "object.h"
#include "ustring.h"
#include <wtf/AlwaysInline.h>
@@ -39,14 +40,81 @@
static unsigned hash(UString::Rep* key) { return key->computedHash(); }
};
- static ALWAYS_INLINE size_t missingSymbolMarker() { return std::numeric_limits<size_t>::max(); }
+ static ALWAYS_INLINE int missingSymbolMarker() { return std::numeric_limits<int>::max(); }
- struct SymbolTableIndexHashTraits : HashTraits<size_t> {
- static const bool emptyValueIsZero = false;
- static size_t emptyValue() { return missingSymbolMarker(); }
+ struct SymbolTableEntry {
+ SymbolTableEntry()
+ : rawValue(0)
+ {
+ }
+
+ SymbolTableEntry(int index)
+ {
+ rawValue = index & ~0x80000000 & ~0x40000000;
+ }
+
+ SymbolTableEntry(int index, unsigned attributes)
+ {
+ rawValue = index;
+
+ if (!(attributes & ReadOnly))
+ rawValue &= ~0x80000000;
+
+ if (!(attributes & DontEnum))
+ rawValue &= ~0x40000000;
+ }
+
+ bool isEmpty() const
+ {
+ return rawValue == 0;
+ }
+
+ int getIndex() const
+ {
+ // Every register index we store is negative, so this bit twiddling works correctly
+ return rawValue | 0x80000000 | 0x40000000;
+ }
+
+ unsigned getAttributes() const
+ {
+ unsigned attributes = 0;
+
+ if (rawValue & 0x80000000)
+ attributes |= ReadOnly;
+
+ if (rawValue & 0x40000000)
+ attributes |= DontEnum;
+
+ return attributes;
+ }
+
+ void setAttributes(unsigned attributes)
+ {
+ rawValue = getIndex();
+
+ if (!(attributes & ReadOnly))
+ rawValue &= ~0x80000000;
+
+ if (!(attributes & DontEnum))
+ rawValue &= ~0x40000000;
+ }
+
+ bool isReadOnly() const
+ {
+ return rawValue & 0x80000000;
+ }
+
+ int rawValue;
};
- typedef HashMap<RefPtr<UString::Rep>, size_t, IdentifierRepHash, HashTraits<RefPtr<UString::Rep> >, SymbolTableIndexHashTraits> SymbolTable;
+ struct SymbolTableIndexHashTraits {
+ typedef SymbolTableEntry TraitType;
+ static SymbolTableEntry emptyValue() { return SymbolTableEntry(); }
+ static const bool emptyValueIsZero = false;
+ static const bool needsDestruction = false;
+ };
+
+ typedef HashMap<RefPtr<UString::Rep>, SymbolTableEntry, IdentifierRepHash, HashTraits<RefPtr<UString::Rep> >, SymbolTableIndexHashTraits> SymbolTable;
} // namespace KJS
diff --git a/JavaScriptCore/kjs/array_object.cpp b/JavaScriptCore/kjs/array_object.cpp
index 26b877d..99b619b 100644
--- a/JavaScriptCore/kjs/array_object.cpp
+++ b/JavaScriptCore/kjs/array_object.cpp
@@ -674,7 +674,7 @@
JSValue* e = getProperty(exec, thisObj, index);
if (!e)
continue;
- if (strictEqual(exec, searchElement, e))
+ if (strictEqual(searchElement, e))
return jsNumber(index);
}
@@ -703,7 +703,7 @@
JSValue* e = getProperty(exec, thisObj, index);
if (!e)
continue;
- if (strictEqual(exec, searchElement, e))
+ if (strictEqual(searchElement, e))
return jsNumber(index);
}
@@ -722,9 +722,9 @@
putDirect(exec->propertyNames().length, jsNumber(1), ReadOnly|DontDelete|DontEnum);
}
-bool ArrayObjectImp::implementsConstruct() const
+ConstructType ArrayObjectImp::getConstructData(ConstructData&)
{
- return true;
+ return ConstructTypeNative;
}
// ECMA 15.4.2
diff --git a/JavaScriptCore/kjs/array_object.h b/JavaScriptCore/kjs/array_object.h
index e109c470..965de82 100644
--- a/JavaScriptCore/kjs/array_object.h
+++ b/JavaScriptCore/kjs/array_object.h
@@ -40,8 +40,9 @@
public:
ArrayObjectImp(ExecState*, FunctionPrototype*, ArrayPrototype*);
- virtual bool implementsConstruct() const;
+ virtual ConstructType getConstructData(ConstructData&);
virtual JSObject* construct(ExecState*, const List&);
+
virtual JSValue* callAsFunction(ExecState*, JSObject*, const List&);
};
diff --git a/JavaScriptCore/kjs/bool_object.cpp b/JavaScriptCore/kjs/bool_object.cpp
index 2d770ee..ba694bb 100644
--- a/JavaScriptCore/kjs/bool_object.cpp
+++ b/JavaScriptCore/kjs/bool_object.cpp
@@ -93,9 +93,9 @@
putDirect(exec->propertyNames().length, jsNumber(1), ReadOnly | DontDelete | DontEnum);
}
-bool BooleanObjectImp::implementsConstruct() const
+ConstructType BooleanObjectImp::getConstructData(ConstructData&)
{
- return true;
+ return ConstructTypeNative;
}
// ECMA 15.6.2
diff --git a/JavaScriptCore/kjs/bool_object.h b/JavaScriptCore/kjs/bool_object.h
index c3d5a9f..51c2ac4 100644
--- a/JavaScriptCore/kjs/bool_object.h
+++ b/JavaScriptCore/kjs/bool_object.h
@@ -54,7 +54,7 @@
public:
BooleanObjectImp(ExecState*, FunctionPrototype*, BooleanPrototype*);
- virtual bool implementsConstruct() const;
+ virtual ConstructType getConstructData(ConstructData&);
virtual JSObject* construct(ExecState*, const List&);
virtual JSValue* callAsFunction(ExecState*, JSObject*, const List&);
diff --git a/JavaScriptCore/kjs/collector.cpp b/JavaScriptCore/kjs/collector.cpp
index 41a0c27..acab28d 100644
--- a/JavaScriptCore/kjs/collector.cpp
+++ b/JavaScriptCore/kjs/collector.cpp
@@ -291,16 +291,17 @@
return newCell;
}
-
-void* Collector::allocate(size_t s)
+#if !PLATFORM(MAC)
+void* Collector::allocate(size_t s)
{
return heapAllocate<PrimaryHeap>(s);
}
-void* Collector::allocateNumber(size_t s)
+void* Collector::allocateNumber(size_t s)
{
return heapAllocate<NumberHeap>(s);
}
+#endif
static inline void* currentThreadStackBase()
{
@@ -1051,18 +1052,4 @@
return (primaryHeap.operationInProgress != NoOperation) | (numberHeap.operationInProgress != NoOperation);
}
-void Collector::reportOutOfMemoryToAllExecStates()
-{
- if (!JSGlobalObject::head())
- return;
-
- JSGlobalObject* globalObject = JSGlobalObject::head();
- do {
- ExecStateStack::const_iterator end = globalObject->activeExecStates().end();
- for (ExecStateStack::const_iterator it = globalObject->activeExecStates().begin(); it != end; ++it)
- (*it)->setException(Error::create(*it, GeneralError, "Out of memory"));
- globalObject = globalObject->next();
- } while (globalObject != JSGlobalObject::head());
-}
-
} // namespace KJS
diff --git a/JavaScriptCore/kjs/collector.h b/JavaScriptCore/kjs/collector.h
index 70db6b5..5aa0576 100644
--- a/JavaScriptCore/kjs/collector.h
+++ b/JavaScriptCore/kjs/collector.h
@@ -35,8 +35,21 @@
class Collector {
public:
+ class Thread;
+ enum HeapType { PrimaryHeap, NumberHeap };
+
+#if PLATFORM(MAC)
+ // We can inline these functions on Mac because everything is compiled as
+ // one file, so the heapAllocate template definitions are available.
+ // FIXME: This should be enabled for all platforms using AllInOneFile.cpp
+ static void* allocate(size_t s) { return heapAllocate<PrimaryHeap>(s); }
+ static void* allocateNumber(size_t s) { return heapAllocate<NumberHeap>(s); }
+#else
static void* allocate(size_t s);
+
static void* allocateNumber(size_t s);
+#endif
+
static bool collect();
static bool isBusy(); // true if an allocation or collection is in progress
@@ -56,7 +69,6 @@
static size_t protectedGlobalObjectCount();
static HashCountedSet<const char*>* protectedObjectTypeCounts();
- class Thread;
static void registerThread();
static void registerAsMainThread();
@@ -64,7 +76,7 @@
static bool isCellMarked(const JSCell*);
static void markCell(JSCell*);
- enum HeapType { PrimaryHeap, NumberHeap };
+ static void markStackObjectsConservatively(void* start, void* end);
private:
template <Collector::HeapType heapType> static void* heapAllocate(size_t s);
@@ -82,11 +94,9 @@
static void markCurrentThreadConservativelyInternal();
static void markOtherThreadConservatively(Thread*);
static void markStackObjectsConservatively();
- static void markStackObjectsConservatively(void* start, void* end);
static size_t mainThreadOnlyObjectCount;
static bool memoryFull;
- static void reportOutOfMemoryToAllExecStates();
};
// tunable parameters
diff --git a/JavaScriptCore/kjs/date_object.cpp b/JavaScriptCore/kjs/date_object.cpp
index 5c0ac17..0b079c2 100644
--- a/JavaScriptCore/kjs/date_object.cpp
+++ b/JavaScriptCore/kjs/date_object.cpp
@@ -495,9 +495,9 @@
putDirect(exec->propertyNames().length, 7, ReadOnly|DontDelete|DontEnum);
}
-bool DateObjectImp::implementsConstruct() const
+ConstructType DateObjectImp::getConstructData(ConstructData&)
{
- return true;
+ return ConstructTypeNative;
}
// ECMA 15.9.3
diff --git a/JavaScriptCore/kjs/date_object.h b/JavaScriptCore/kjs/date_object.h
index d78d308..03dc655 100644
--- a/JavaScriptCore/kjs/date_object.h
+++ b/JavaScriptCore/kjs/date_object.h
@@ -127,13 +127,14 @@
*/
class DateObjectImp : public InternalFunctionImp {
public:
- DateObjectImp(ExecState *, FunctionPrototype *, DatePrototype *);
+ DateObjectImp(ExecState*, FunctionPrototype*, DatePrototype*);
- virtual bool implementsConstruct() const;
- virtual JSObject *construct(ExecState *, const List &args);
- virtual JSValue *callAsFunction(ExecState *, JSObject *thisObj, const List &args);
+ virtual ConstructType getConstructData(ConstructData&);
+ virtual JSObject* construct(ExecState*, const List& args);
- JSObject *construct(const List &);
+ virtual JSValue* callAsFunction(ExecState*, JSObject* thisObj, const List& args);
+
+ JSObject* construct(const List&);
};
} // namespace
diff --git a/JavaScriptCore/kjs/debugger.cpp b/JavaScriptCore/kjs/debugger.cpp
index af9c5fa..4d28630 100644
--- a/JavaScriptCore/kjs/debugger.cpp
+++ b/JavaScriptCore/kjs/debugger.cpp
@@ -1,6 +1,6 @@
// -*- c-basic-offset: 2 -*-
/*
- * This file is part of the KDE libraries
+ * Copyright (C) 2008 Apple Inc. All rights reserved.
* Copyright (C) 1999-2001 Harri Porten (porten@kde.org)
* Copyright (C) 2001 Peter Kelly (pmk@post.com)
*
@@ -24,111 +24,32 @@
#include "debugger.h"
#include "JSGlobalObject.h"
-#include "internal.h"
-#include "ustring.h"
-
-using namespace KJS;
-
-// ------------------------------ Debugger -------------------------------------
namespace KJS {
- struct AttachedGlobalObject
- {
- public:
- AttachedGlobalObject(JSGlobalObject* o, AttachedGlobalObject* ai) : globalObj(o), next(ai) { ++Debugger::debuggersPresent; }
- ~AttachedGlobalObject() { --Debugger::debuggersPresent; }
- JSGlobalObject* globalObj;
- AttachedGlobalObject* next;
- };
-
-}
-
-int Debugger::debuggersPresent = 0;
Debugger::Debugger()
{
- rep = new DebuggerImp();
}
Debugger::~Debugger()
{
- detach(0);
- delete rep;
+ HashSet<JSGlobalObject*>::iterator end = m_globalObjects.end();
+ for (HashSet<JSGlobalObject*>::iterator it = m_globalObjects.begin(); it != end; ++it)
+ (*it)->setDebugger(0);
}
void Debugger::attach(JSGlobalObject* globalObject)
{
- Debugger* other = globalObject->debugger();
- if (other == this)
- return;
- if (other)
- other->detach(globalObject);
- globalObject->setDebugger(this);
- rep->globalObjects = new AttachedGlobalObject(globalObject, rep->globalObjects);
+ ASSERT(!globalObject->debugger());
+ globalObject->setDebugger(this);
+ m_globalObjects.add(globalObject);
}
-void Debugger::detach(JSGlobalObject* globalObj)
+void Debugger::detach(JSGlobalObject* globalObject)
{
- // iterate the addresses where AttachedGlobalObject pointers are stored
- // so we can unlink items from the list
- AttachedGlobalObject **p = &rep->globalObjects;
- AttachedGlobalObject *q;
- while ((q = *p)) {
- if (!globalObj || q->globalObj == globalObj) {
- *p = q->next;
- q->globalObj->setDebugger(0);
- delete q;
- } else
- p = &q->next;
- }
-
- if (globalObj)
- latestExceptions.remove(globalObj);
- else
- latestExceptions.clear();
+ ASSERT(m_globalObjects.contains(globalObject));
+ m_globalObjects.remove(globalObject);
+ globalObject->setDebugger(0);
}
-bool Debugger::hasHandledException(ExecState *exec, JSValue *exception)
-{
- if (latestExceptions.get(exec->dynamicGlobalObject()).get() == exception)
- return true;
-
- latestExceptions.set(exec->dynamicGlobalObject(), exception);
- return false;
-}
-
-bool Debugger::sourceParsed(ExecState*, int /*sourceId*/, const UString &/*sourceURL*/,
- const UString &/*source*/, int /*startingLineNumber*/, int /*errorLine*/, const UString & /*errorMsg*/)
-{
- return true;
-}
-
-bool Debugger::sourceUnused(ExecState*, int /*sourceId*/)
-{
- return true;
-}
-
-bool Debugger::exception(ExecState*, int /*sourceId*/, int /*lineno*/,
- JSValue* /*exception */)
-{
- return true;
-}
-
-bool Debugger::atStatement(ExecState*, int /*sourceId*/, int /*firstLine*/,
- int /*lastLine*/)
-{
- return true;
-}
-
-bool Debugger::callEvent(ExecState*, int /*sourceId*/, int /*lineno*/,
- JSObject* /*function*/, const List &/*args*/)
-{
- return true;
-}
-
-bool Debugger::returnEvent(ExecState*, int /*sourceId*/, int /*lineno*/,
- JSObject* /*function*/)
-{
- return true;
-}
-
+} // namespace KJS
diff --git a/JavaScriptCore/kjs/debugger.h b/JavaScriptCore/kjs/debugger.h
index 2d5cb6f..f417177 100644
--- a/JavaScriptCore/kjs/debugger.h
+++ b/JavaScriptCore/kjs/debugger.h
@@ -20,34 +20,29 @@
*
*/
-#ifndef _KJSDEBUGGER_H_
-#define _KJSDEBUGGER_H_
+#ifndef Debugger_h
+#define Debugger_h
-#include <wtf/HashMap.h>
+#include <wtf/HashSet.h>
#include "protect.h"
namespace KJS {
- class DebuggerImp;
+ class DebuggerCallFrame;
class ExecState;
class JSGlobalObject;
class JSObject;
class JSValue;
- class UString;
class List;
-
+ class SourceProvider;
+ class UString;
+
/**
* @internal
*
* Provides an interface which receives notification about various
* script-execution related events such as statement execution and function
* calls.
- *
- * WARNING: This interface is still a work in progress and is not yet
- * offically publicly available. It is likely to change in binary incompatible
- * (and possibly source incompatible) ways in future versions. It is
- * anticipated that at some stage the interface will be frozen and made
- * available for general use.
*/
class Debugger {
public:
@@ -63,8 +58,6 @@
*/
virtual ~Debugger();
- DebuggerImp *imp() const { return rep; }
-
/**
* Attaches the debugger to specified global object. This will cause this
* object to receive notification of events during execution.
@@ -76,18 +69,13 @@
* original debugger to be detached.
*
* @param The global object to attach to.
- *
- * @see detach()
*/
void attach(JSGlobalObject*);
/**
* Detach the debugger from a global object.
*
- * @param The global object to detach from. If 0, the debugger will be
- * detached from all global objects to which it is attached.
- *
- * @see attach()
+ * @param The global object to detach from.
*/
void detach(JSGlobalObject*);
@@ -111,27 +99,9 @@
* error, or -1 if the source code was valid and parsed successfully
* @param errorMsg The error description, or null if the source code
was valid and parsed successfully
- * @return true if execution should be continue, false if it should
- * be aborted
*/
- virtual bool sourceParsed(ExecState *exec, int sourceId, const UString &sourceURL,
- const UString &source, int startingLineNumber, int errorLine, const UString &errorMsg);
-
- /**
- * Called when all functions/programs associated with a particular
- * sourceId have been deleted. After this function has been called for
- * a particular sourceId, that sourceId will not be used again.
- *
- * The default implementation does nothing. Override this method if
- * you want to process this event.
- *
- * @param exec The current execution state
- * @param sourceId The ID of the source code (corresponds to the
- * sourceId supplied in other functions such as atLine()
- * @return true if execution should be continue, false if it should
- * be aborted
- */
- virtual bool sourceUnused(ExecState *exec, int sourceId);
+ virtual void sourceParsed(ExecState*, int sourceId, const UString& sourceURL,
+ const SourceProvider& source, int startingLineNumber, int errorLine, const UString& errorMsg) = 0;
/**
* Called when an exception is thrown during script execution.
@@ -143,13 +113,8 @@
* @param sourceId The ID of the source code being executed
* @param lineno The line at which the error occurred
* @param exceptionObj The exception object
- * @return true if execution should be continue, false if it should
- * be aborted
*/
- virtual bool exception(ExecState *exec, int sourceId, int lineno,
- JSValue *exception);
-
- bool hasHandledException(ExecState *, JSValue *);
+ virtual void exception(const DebuggerCallFrame&, int sourceId, int lineno) = 0;
/**
* Called when a line of the script is reached (before it is executed)
@@ -163,11 +128,8 @@
* executed
* @param lastLine The ending line of the statement that is about to be
* executed (usually the same as firstLine)
- * @return true if execution should be continue, false if it should
- * be aborted
*/
- virtual bool atStatement(ExecState *exec, int sourceId, int firstLine,
- int lastLine);
+ virtual void atStatement(const DebuggerCallFrame&, int sourceId, int lineno) = 0;
/**
* Called on each function call. Use together with @ref #returnEvent
* if you want to keep track of the call stack.
@@ -182,14 +144,8 @@
* @param exec The current execution state
* @param sourceId The ID of the source code being executed
* @param lineno The line that is about to be executed
- * @param function The function being called
- * @param args The arguments that were passed to the function
- * line is being executed
- * @return true if execution should be continue, false if it should
- * be aborted
*/
- virtual bool callEvent(ExecState *exec, int sourceId, int lineno,
- JSObject *function, const List &args);
+ virtual void callEvent(const DebuggerCallFrame&, int sourceId, int lineno) = 0;
/**
* Called on each function exit. The function being returned from is that
@@ -205,21 +161,13 @@
* @param exec The current execution state
* @param sourceId The ID of the source code being executed
* @param lineno The line that is about to be executed
- * @param function The function being called
- * @return true if execution should be continue, false if it should
- * be aborted
*/
- virtual bool returnEvent(ExecState *exec, int sourceId, int lineno,
- JSObject *function);
+ virtual void returnEvent(const DebuggerCallFrame&, int sourceId, int lineno) = 0;
private:
- DebuggerImp *rep;
- HashMap<JSGlobalObject*, ProtectedPtr<JSValue> > latestExceptions;
-
- public:
- static int debuggersPresent;
+ HashSet<JSGlobalObject*> m_globalObjects;
};
-}
+} // namespace KJS
#endif
diff --git a/JavaScriptCore/kjs/error_object.cpp b/JavaScriptCore/kjs/error_object.cpp
index ac773b6..73c9026 100644
--- a/JavaScriptCore/kjs/error_object.cpp
+++ b/JavaScriptCore/kjs/error_object.cpp
@@ -78,9 +78,9 @@
putDirect(exec->propertyNames().length, jsNumber(1), DontDelete|ReadOnly|DontEnum);
}
-bool ErrorObjectImp::implementsConstruct() const
+ConstructType ErrorObjectImp::getConstructData(ConstructData&)
{
- return true;
+ return ConstructTypeNative;
}
// ECMA 15.9.3
@@ -124,9 +124,9 @@
putDirect(exec->propertyNames().prototype, proto, DontDelete|ReadOnly|DontEnum);
}
-bool NativeErrorImp::implementsConstruct() const
+ConstructType NativeErrorImp::getConstructData(ConstructData&)
{
- return true;
+ return ConstructTypeNative;
}
JSObject* NativeErrorImp::construct(ExecState* exec, const List& args)
diff --git a/JavaScriptCore/kjs/error_object.h b/JavaScriptCore/kjs/error_object.h
index 9734085..57d607c 100644
--- a/JavaScriptCore/kjs/error_object.h
+++ b/JavaScriptCore/kjs/error_object.h
@@ -44,7 +44,7 @@
public:
ErrorObjectImp(ExecState*, FunctionPrototype*, ErrorPrototype*);
- virtual bool implementsConstruct() const;
+ virtual ConstructType getConstructData(ConstructData&);
virtual JSObject* construct(ExecState*, const List&);
virtual JSValue* callAsFunction(ExecState*, JSObject*, const List&);
@@ -59,8 +59,9 @@
public:
NativeErrorImp(ExecState*, FunctionPrototype*, NativeErrorPrototype*);
- virtual bool implementsConstruct() const;
+ virtual ConstructType getConstructData(ConstructData&);
virtual JSObject* construct(ExecState*, const List&);
+
virtual JSValue* callAsFunction(ExecState*, JSObject*, const List&);
virtual void mark();
diff --git a/JavaScriptCore/kjs/function.cpp b/JavaScriptCore/kjs/function.cpp
index a536b58..8a970e4 100644
--- a/JavaScriptCore/kjs/function.cpp
+++ b/JavaScriptCore/kjs/function.cpp
@@ -26,9 +26,10 @@
#include "config.h"
#include "function.h"
-#include "Activation.h"
#include "ExecState.h"
+#include "JSActivation.h"
#include "JSGlobalObject.h"
+#include "Machine.h"
#include "Parser.h"
#include "PropertyNameArray.h"
#include "debugger.h"
@@ -39,7 +40,6 @@
#include "nodes.h"
#include "operations.h"
#include "scope_chain_mark.h"
-#include "ExecStateInlines.h"
#include <errno.h>
#include <profiler/Profiler.h>
#include <stdio.h>
@@ -59,67 +59,58 @@
const ClassInfo FunctionImp::info = { "Function", &InternalFunctionImp::info, 0, 0 };
-FunctionImp::FunctionImp(ExecState* exec, const Identifier& name, FunctionBodyNode* b, const ScopeChain& sc)
+FunctionImp::FunctionImp(ExecState* exec, const Identifier& name, FunctionBodyNode* b, ScopeChainNode* scopeChain)
: InternalFunctionImp(exec->lexicalGlobalObject()->functionPrototype(), name)
, body(b)
- , _scope(sc)
+ , _scope(scopeChain)
{
}
void FunctionImp::mark()
{
InternalFunctionImp::mark();
+ body->mark();
_scope.mark();
}
+CallType FunctionImp::getCallData(CallData& callData)
+{
+ callData.js.functionBody = body.get();
+ callData.js.scopeChain = _scope.node();
+ return CallTypeJS;
+}
+
JSValue* FunctionImp::callAsFunction(ExecState* exec, JSObject* thisObj, const List& args)
{
- FunctionExecState newExec(exec->dynamicGlobalObject(), thisObj, exec->globalThisValue(), body.get(), exec, this, args);
- JSValue* result = body->execute(&newExec);
- if (newExec.completionType() == ReturnValue)
+ JSValue* exception = 0;
+ RegisterFileStack* stack = &exec->dynamicGlobalObject()->registerFileStack();
+ RegisterFile* current = stack->current();
+ if (!current->safeForReentry()) {
+ stack->pushFunctionRegisterFile();
+ JSValue* result = machine().execute(body.get(), exec, this, thisObj, args, stack, _scope.node(), &exception);
+ stack->popFunctionRegisterFile();
+ exec->setException(exception);
return result;
- if (newExec.completionType() == Throw) {
- exec->setException(result);
+ } else {
+ JSValue* result = machine().execute(body.get(), exec, this, thisObj, args, stack, _scope.node(), &exception);
+ current->setSafeForReentry(true);
+ exec->setException(exception);
return result;
}
- return jsUndefined();
}
-JSValue* FunctionImp::argumentsGetter(ExecState* exec, JSObject*, const Identifier& propertyName, const PropertySlot& slot)
+JSValue* FunctionImp::argumentsGetter(ExecState* exec, JSObject*, const Identifier&, const PropertySlot& slot)
{
- FunctionImp* thisObj = static_cast<FunctionImp*>(slot.slotBase());
-
- for (ExecState* e = exec; e; e = e->callingExecState())
- if (e->function() == thisObj) {
- e->dynamicGlobalObject()->tearOffActivation(e, e != exec);
- return e->activationObject()->get(exec, propertyName);
- }
-
- return jsNull();
+ FunctionImp* thisObj = static_cast<FunctionImp*>(slot.slotBase());
+ ASSERT(exec->machine());
+ return exec->machine()->retrieveArguments(exec, thisObj);
}
JSValue* FunctionImp::callerGetter(ExecState* exec, JSObject*, const Identifier&, const PropertySlot& slot)
{
FunctionImp* thisObj = static_cast<FunctionImp*>(slot.slotBase());
- ExecState* e = exec;
- while (e) {
- if (e->function() == thisObj)
- break;
- e = e->callingExecState();
- }
-
- if (!e)
- return jsNull();
-
- ExecState* callingExecState = e->callingExecState();
- if (!callingExecState)
- return jsNull();
-
- FunctionImp* callingFunction = callingExecState->function();
- if (!callingFunction)
- return jsNull();
-
- return callingFunction;
+ ASSERT(exec->machine());
+ return exec->machine()->retrieveCaller(exec, thisObj);
}
JSValue* FunctionImp::lengthGetter(ExecState*, JSObject*, const Identifier&, const PropertySlot& slot)
@@ -130,13 +121,11 @@
bool FunctionImp::getOwnPropertySlot(ExecState* exec, const Identifier& propertyName, PropertySlot& slot)
{
- // Find the arguments from the closest context.
if (propertyName == exec->propertyNames().arguments) {
slot.setCustom(this, argumentsGetter);
return true;
}
- // Compute length of parameters.
if (propertyName == exec->propertyNames().length) {
slot.setCustom(this, lengthGetter);
return true;
@@ -190,23 +179,34 @@
}
// ECMA 13.2.2 [[Construct]]
+ConstructType FunctionImp::getConstructData(ConstructData& constructData)
+{
+ constructData.js.functionBody = body.get();
+ constructData.js.scopeChain = _scope.node();
+ return ConstructTypeJS;
+}
+
JSObject* FunctionImp::construct(ExecState* exec, const List& args)
{
- JSObject* proto;
- JSValue* p = get(exec, exec->propertyNames().prototype);
- if (p->isObject())
- proto = static_cast<JSObject*>(p);
- else
- proto = exec->lexicalGlobalObject()->objectPrototype();
+ JSObject* proto;
+ JSValue* p = get(exec, exec->propertyNames().prototype);
+ if (p->isObject())
+ proto = static_cast<JSObject*>(p);
+ else
+ proto = exec->lexicalGlobalObject()->objectPrototype();
- JSObject* obj(new JSObject(proto));
+ JSObject* thisObj = new JSObject(proto);
- JSValue* res = call(exec,obj,args);
+ JSValue* exception = 0;
+ JSValue* result = machine().execute(body.get(), exec, this, thisObj, args, &exec->dynamicGlobalObject()->registerFileStack(), _scope.node(), &exception);
+ if (exception) {
+ exec->setException(exception);
+ return thisObj;
+ }
- if (res->isObject())
- return static_cast<JSObject*>(res);
- else
- return obj;
+ if (result->isObject())
+ return static_cast<JSObject*>(result);
+ return thisObj;
}
// ------------------------------ IndexToNameMap ---------------------------------
@@ -278,7 +278,7 @@
const ClassInfo Arguments::info = { "Arguments", 0, 0, 0 };
// ECMA 10.1.8
-Arguments::Arguments(ExecState* exec, FunctionImp* func, const List& args, ActivationImp* act)
+Arguments::Arguments(ExecState* exec, FunctionImp* func, const List& args, JSActivation* act)
: JSObject(exec->lexicalGlobalObject()->objectPrototype())
, _activationObject(act)
, indexToNameMap(func, args)
@@ -336,152 +336,6 @@
}
}
-// ------------------------------ ActivationImp --------------------------------
-
-const ClassInfo ActivationImp::info = { "Activation", 0, 0, 0 };
-
-ActivationImp::ActivationImp(const ActivationData& oldData, bool leaveRelic)
-{
- JSVariableObject::d = new ActivationData(oldData);
- d()->leftRelic = leaveRelic;
-}
-
-ActivationImp::~ActivationImp()
-{
- if (!d()->isOnStack)
- delete d();
-}
-
-JSValue* ActivationImp::argumentsGetter(ExecState* exec, JSObject*, const Identifier&, const PropertySlot& slot)
-{
- ActivationImp* thisObj = static_cast<ActivationImp*>(slot.slotBase());
-
- if (!thisObj->d()->argumentsObject)
- thisObj->createArgumentsObject(exec);
-
- return thisObj->d()->argumentsObject;
-}
-
-PropertySlot::GetValueFunc ActivationImp::getArgumentsGetter()
-{
- return ActivationImp::argumentsGetter;
-}
-
-bool ActivationImp::getOwnPropertySlot(ExecState* exec, const Identifier& propertyName, PropertySlot& slot)
-{
- if (symbolTableGet(propertyName, slot))
- return true;
-
- if (JSValue** location = getDirectLocation(propertyName)) {
- slot.setValueSlot(this, location);
- return true;
- }
-
- // Only return the built-in arguments object if it wasn't overridden above.
- if (propertyName == exec->propertyNames().arguments) {
- for (ExecState* e = exec; e; e = e->callingExecState())
- if (e->function() == d()->function) {
- e->dynamicGlobalObject()->tearOffActivation(e, e != exec);
- ActivationImp* newActivation = e->activationObject();
- slot.setCustom(newActivation, newActivation->getArgumentsGetter());
- return true;
- }
-
- slot.setCustom(this, getArgumentsGetter());
- return true;
- }
-
- // We don't call through to JSObject because there's no way to give an
- // activation object getter properties or a prototype.
- ASSERT(!_prop.hasGetterSetterProperties());
- ASSERT(prototype() == jsNull());
- return false;
-}
-
-bool ActivationImp::deleteProperty(ExecState* exec, const Identifier& propertyName)
-{
- if (propertyName == exec->propertyNames().arguments)
- return false;
-
- return JSVariableObject::deleteProperty(exec, propertyName);
-}
-
-void ActivationImp::put(ExecState*, const Identifier& propertyName, JSValue* value)
-{
- if (symbolTablePut(propertyName, value))
- return;
-
- // We don't call through to JSObject because __proto__ and getter/setter
- // properties are non-standard extensions that other implementations do not
- // expose in the activation object.
- ASSERT(!_prop.hasGetterSetterProperties());
- _prop.put(propertyName, value, 0, true);
-}
-
-void ActivationImp::putWithAttributes(ExecState*, const Identifier& propertyName, JSValue* value, unsigned attributes)
-{
- if (symbolTablePutWithAttributes(propertyName, value, attributes))
- return;
-
- // We don't call through to JSObject because __proto__ and getter/setter
- // properties are non-standard extensions that other implementations do not
- // expose in the activation object.
- ASSERT(!_prop.hasGetterSetterProperties());
- _prop.put(propertyName, value, attributes, true);
-}
-
-void ActivationImp::markChildren()
-{
- LocalStorage& localStorage = d()->localStorage;
- size_t size = localStorage.size();
-
- for (size_t i = 0; i < size; ++i) {
- JSValue* value = localStorage[i].value;
-
- if (!value->marked())
- value->mark();
- }
-
- if (!d()->function->marked())
- d()->function->mark();
-
- if (d()->argumentsObject && !d()->argumentsObject->marked())
- d()->argumentsObject->mark();
-}
-
-void ActivationImp::mark()
-{
- JSObject::mark();
- markChildren();
-}
-
-void ActivationImp::createArgumentsObject(ExecState* exec)
-{
- // Since "arguments" is only accessible while a function is being called,
- // we can retrieve our argument list from the ExecState for our function
- // call instead of storing the list ourselves.
- d()->argumentsObject = new Arguments(exec, d()->exec->function(), *d()->exec->arguments(), this);
-}
-
-JSObject* ActivationImp::toThisObject(ExecState* exec) const
-{
- return exec->globalThisValue();
-}
-
-ActivationImp::ActivationData::ActivationData(const ActivationData& old)
- : JSVariableObjectData(old)
- , exec(old.exec)
- , function(old.function)
- , argumentsObject(old.argumentsObject)
- , isOnStack(false)
-{
-}
-
-bool ActivationImp::isDynamicScope() const
-{
- return d()->function->body->usesEval();
-}
-
// ------------------------------ Global Functions -----------------------------------
static JSValue* encode(ExecState* exec, const List& args, const char* do_not_escape)
@@ -703,14 +557,19 @@
return s.toDouble( true /*tolerant*/, false /* NaN for empty string */ );
}
-JSValue* eval(ExecState* exec, const ScopeChain& scopeChain, JSVariableObject* variableObject, JSGlobalObject* globalObject, JSObject* thisObj, const List& args)
+JSValue* globalFuncEval(ExecState* exec, PrototypeReflexiveFunction* function, JSObject* thisObj, const List& args)
{
+ JSGlobalObject* globalObject = thisObj->toGlobalObject(exec);
+
+ if (!globalObject || globalObject->evalFunction() != function)
+ return throwError(exec, EvalError, "The \"this\" value passed to eval must be the global object from which eval originated");
+
JSValue* x = args[0];
if (!x->isString())
return x;
-
+
UString s = x->toString(exec);
-
+
int sourceId;
int errLine;
UString errMsg;
@@ -719,45 +578,26 @@
Profiler::profiler()->willExecute(exec, UString(), 0);
#endif
- RefPtr<EvalNode> evalNode = parser().parse<EvalNode>(UString(), 0, s.data(), s.size(), &sourceId, &errLine, &errMsg);
-
- Debugger* dbg = exec->dynamicGlobalObject()->debugger();
- if (dbg) {
- bool cont = dbg->sourceParsed(exec, sourceId, UString(), s, 0, errLine, errMsg);
- if (!cont)
- return jsUndefined();
- }
-
+ RefPtr<EvalNode> evalNode = parser().parse<EvalNode>(exec, UString(), 0, UStringSourceProvider::create(s), &sourceId, &errLine, &errMsg);
+
if (!evalNode)
return throwError(exec, SyntaxError, errMsg, errLine, sourceId, NULL);
- EvalExecState newExec(globalObject, thisObj, evalNode.get(), exec, scopeChain, variableObject);
-
- JSValue* value = evalNode->execute(&newExec);
+ JSValue* exception = 0;
+ JSValue* value = machine().execute(evalNode.get(), exec, thisObj, &exec->dynamicGlobalObject()->registerFileStack(), globalObject->globalScopeChain().node(), &exception);
#if JAVASCRIPT_PROFILING
Profiler::profiler()->didExecute(exec, UString(), 0);
#endif
- if (newExec.completionType() == Throw) {
- exec->setException(value);
+ if (exception) {
+ exec->setException(exception);
return value;
}
-
+
return value ? value : jsUndefined();
}
-JSValue* globalFuncEval(ExecState* exec, PrototypeReflexiveFunction* function, JSObject* thisObj, const List& args)
-{
- JSGlobalObject* globalObject = thisObj->toGlobalObject(exec);
-
- if (!globalObject || globalObject->evalFunction() != function)
- return throwError(exec, EvalError, "The \"this\" value passed to eval must be the global object from which eval originated");
-
- ScopeChain scopeChain(globalObject);
- return eval(exec, scopeChain, globalObject, globalObject, function->cachedGlobalObject()->toThisObject(exec), args);
-}
-
JSValue* globalFuncParseInt(ExecState* exec, JSObject*, const List& args)
{
return jsNumber(parseInt(args[0]->toString(exec), args[1]->toInt32(exec)));
diff --git a/JavaScriptCore/kjs/function.h b/JavaScriptCore/kjs/function.h
index 7bf71d5..15dd059 100644
--- a/JavaScriptCore/kjs/function.h
+++ b/JavaScriptCore/kjs/function.h
@@ -26,16 +26,15 @@
#define KJS_FUNCTION_H
#include "JSVariableObject.h"
-#include "LocalStorageEntry.h"
#include "SymbolTable.h"
#include "nodes.h"
#include "object.h"
namespace KJS {
- class ActivationImp;
class FunctionBodyNode;
class FunctionPrototype;
+ class JSActivation;
class JSGlobalObject;
class InternalFunctionImp : public JSObject {
@@ -43,7 +42,8 @@
InternalFunctionImp();
InternalFunctionImp(FunctionPrototype*, const Identifier&);
- virtual bool implementsCall() const;
+ virtual CallType getCallData(CallData&);
+
virtual JSValue* callAsFunction(ExecState*, JSObject* thisObjec, const List& args) = 0;
virtual bool implementsHasInstance() const;
@@ -56,17 +56,17 @@
};
class FunctionImp : public InternalFunctionImp {
- friend class ActivationImp;
public:
- FunctionImp(ExecState*, const Identifier& name, FunctionBodyNode*, const ScopeChain&);
+ FunctionImp(ExecState*, const Identifier&, FunctionBodyNode*, ScopeChainNode*);
virtual bool getOwnPropertySlot(ExecState*, const Identifier&, PropertySlot&);
virtual void put(ExecState*, const Identifier& propertyName, JSValue*);
virtual bool deleteProperty(ExecState*, const Identifier& propertyName);
- virtual bool implementsConstruct() const { return true; }
+ virtual ConstructType getConstructData(ConstructData&);
virtual JSObject* construct(ExecState*, const List& args);
-
+
+ virtual CallType getCallData(CallData&);
virtual JSValue* callAsFunction(ExecState*, JSObject* thisObj, const List& args);
// Note: unlike body->paramName, this returns Identifier::null for parameters
@@ -79,7 +79,7 @@
RefPtr<FunctionBodyNode> body;
void setScope(const ScopeChain& s) { _scope = s; }
- const ScopeChain& scope() const { return _scope; }
+ ScopeChain& scope() { return _scope; }
virtual void mark();
@@ -107,7 +107,7 @@
class Arguments : public JSObject {
public:
- Arguments(ExecState*, FunctionImp* func, const List& args, ActivationImp* act);
+ Arguments(ExecState*, FunctionImp* func, const List& args, JSActivation* act);
virtual void mark();
virtual bool getOwnPropertySlot(ExecState*, const Identifier&, PropertySlot&);
virtual void put(ExecState*, const Identifier& propertyName, JSValue*);
@@ -117,7 +117,7 @@
private:
static JSValue* mappedIndexGetter(ExecState*, JSObject*, const Identifier&, const PropertySlot& slot);
- ActivationImp* _activationObject;
+ JSActivation* _activationObject;
mutable IndexToNameMap indexToNameMap;
};
@@ -168,8 +168,6 @@
JSValue* globalFuncKJSPrint(ExecState*, JSObject*, const List&);
#endif
- JSValue* eval(ExecState*, const ScopeChain&, JSVariableObject*, JSGlobalObject*, JSObject* thisObj, const List& args);
-
static const double mantissaOverflowLowerBound = 9007199254740992.0;
double parseIntOverflow(const char*, int length, int radix);
diff --git a/JavaScriptCore/kjs/function_object.cpp b/JavaScriptCore/kjs/function_object.cpp
index c849b4d..dacbd43 100644
--- a/JavaScriptCore/kjs/function_object.cpp
+++ b/JavaScriptCore/kjs/function_object.cpp
@@ -70,7 +70,7 @@
if (thisObj->inherits(&FunctionImp::info)) {
FunctionImp* fi = static_cast<FunctionImp*>(thisObj);
- return jsString("function " + fi->functionName().ustring() + "(" + fi->body->paramString() + ") " + fi->body->toString());
+ return jsString("function " + fi->functionName().ustring() + "(" + fi->body->paramString() + ") " + fi->body->toSourceString());
}
return jsString("function " + static_cast<InternalFunctionImp*>(thisObj)->functionName().ustring() + "() {\n [native code]\n}");
@@ -136,9 +136,9 @@
putDirect(exec->propertyNames().length, jsNumber(1), ReadOnly | DontDelete | DontEnum);
}
-bool FunctionObjectImp::implementsConstruct() const
+ConstructType FunctionObjectImp::getConstructData(ConstructData&)
{
- return true;
+ return ConstructTypeNative;
}
// ECMA 15.3.2 The Function Constructor
@@ -162,24 +162,19 @@
int sourceId;
int errLine;
UString errMsg;
- RefPtr<FunctionBodyNode> functionBody = parser().parse<FunctionBodyNode>(sourceURL, lineNumber, body.data(), body.size(), &sourceId, &errLine, &errMsg);
-
- // notify debugger that source has been parsed
- // send empty sourceURL to indicate constructed code
- Debugger* dbg = exec->dynamicGlobalObject()->debugger();
- if (dbg && !dbg->sourceParsed(exec, sourceId, UString(), body, lineNumber, errLine, errMsg))
- return new JSObject();
+ RefPtr<SourceProvider> source = UStringSourceProvider::create(body);
+ RefPtr<FunctionBodyNode> functionBody = parser().parse<FunctionBodyNode>(exec, sourceURL, lineNumber, source, &sourceId, &errLine, &errMsg);
// No program node == syntax error - throw a syntax error
if (!functionBody)
// We can't return a Completion(Throw) here, so just set the exception
// and return it
return throwError(exec, SyntaxError, errMsg, errLine, sourceId, sourceURL);
+
+ functionBody->setSource(SourceRange(source, 0, source->length()));
+ ScopeChain scopeChain(exec->lexicalGlobalObject());
- ScopeChain scopeChain;
- scopeChain.push(exec->lexicalGlobalObject());
-
- FunctionImp* fimp = new FunctionImp(exec, functionName, functionBody.get(), scopeChain);
+ FunctionImp* fimp = new FunctionImp(exec, functionName, functionBody.get(), scopeChain.node());
// parse parameter list. throw syntax error on illegal identifiers
int len = p.size();
@@ -212,8 +207,6 @@
return throwError(exec, SyntaxError, "Syntax error in parameter list");
}
- List consArgs;
-
JSObject* objCons = exec->lexicalGlobalObject()->objectConstructor();
JSObject* prototype = objCons->construct(exec, exec->emptyList());
prototype->putDirect(exec->propertyNames().constructor, fimp, DontEnum);
diff --git a/JavaScriptCore/kjs/function_object.h b/JavaScriptCore/kjs/function_object.h
index cd0fe3e..8531070 100644
--- a/JavaScriptCore/kjs/function_object.h
+++ b/JavaScriptCore/kjs/function_object.h
@@ -50,9 +50,10 @@
public:
FunctionObjectImp(ExecState*, FunctionPrototype*);
- virtual bool implementsConstruct() const;
+ virtual ConstructType getConstructData(ConstructData&);
virtual JSObject* construct(ExecState*, const List&);
virtual JSObject* construct(ExecState*, const List&, const Identifier& functionName, const UString& sourceURL, int lineNumber);
+
virtual JSValue* callAsFunction(ExecState*, JSObject*, const List&);
};
diff --git a/JavaScriptCore/kjs/grammar.y b/JavaScriptCore/kjs/grammar.y
index f34806a..51bcc03 100644
--- a/JavaScriptCore/kjs/grammar.y
+++ b/JavaScriptCore/kjs/grammar.y
@@ -49,11 +49,13 @@
#define YYERROR_VERBOSE
#endif
+#define LEXER (static_cast<KJS::Lexer*>(lexer))
+
int kjsyylex(void* lvalp, void* llocp, void* lexer);
int kjsyyerror(const char*);
static inline bool allowAutomaticSemicolon(KJS::Lexer&, int);
-#define AUTO_SEMICOLON do { if (!allowAutomaticSemicolon(*static_cast<KJS::Lexer*>(lexer), yychar)) YYABORT; } while (0)
+#define AUTO_SEMICOLON do { if (!allowAutomaticSemicolon(*LEXER, yychar)) YYABORT; } while (0)
#define DBG(l, s, e) (l)->setLoc((s).first_line, (e).last_line)
using namespace KJS;
@@ -61,10 +63,10 @@
static AddNode* makeAddNode(ExpressionNode*, ExpressionNode*);
static LessNode* makeLessNode(ExpressionNode*, ExpressionNode*);
-static ExpressionNode* makeAssignNode(ExpressionNode* loc, Operator, ExpressionNode* expr);
+static ExpressionNode* makeAssignNode(ExpressionNode* loc, Operator, ExpressionNode* expr, bool locHasAssignments, bool exprHasAssignments);
static ExpressionNode* makePrefixNode(ExpressionNode* expr, Operator);
static ExpressionNode* makePostfixNode(ExpressionNode* expr, Operator);
-static PropertyNode* makeGetterOrSetterPropertyNode(const Identifier &getOrSet, const Identifier& name, ParameterNode*, FunctionBodyNode*);
+static PropertyNode* makeGetterOrSetterPropertyNode(const Identifier &getOrSet, const Identifier& name, ParameterNode*, FunctionBodyNode*, const SourceRange&);
static ExpressionNodeInfo makeFunctionCallNode(ExpressionNodeInfo func, ArgumentsNodeInfo);
static ExpressionNode* makeTypeOfNode(ExpressionNode*);
static ExpressionNode* makeDeleteNode(ExpressionNode*);
@@ -95,14 +97,14 @@
ParserRefCountedData<DeclarationStacks::FunctionStack>* funcDecls,
FeatureInfo info)
{
- ASSERT((info & ~(EvalFeature | ClosureFeature)) == 0);
+ ASSERT((info & ~(EvalFeature | ClosureFeature | AssignFeature)) == 0);
NodeDeclarationInfo<T> result = {node, varDecls, funcDecls, info};
return result;
}
template <typename T> NodeFeatureInfo<T> createNodeFeatureInfo(T node, FeatureInfo info)
{
- ASSERT((info & ~(EvalFeature | ClosureFeature)) == 0);
+ ASSERT((info & ~(EvalFeature | ClosureFeature | AssignFeature)) == 0);
NodeFeatureInfo<T> result = {node, info};
return result;
}
@@ -209,6 +211,8 @@
%token RSHIFTEQUAL URSHIFTEQUAL /* >>= and >>>= */
%token ANDEQUAL MODEQUAL /* &= and %= */
%token XOREQUAL OREQUAL /* ^= and |= */
+%token <intValue> OPENBRACE /* { (with char offset) */
+%token <intValue> CLOSEBRACE /* { (with char offset) */
/* terminal types */
%token <doubleValue> NUMBER
@@ -281,13 +285,13 @@
| NUMBER { $$ = createNodeFeatureInfo<ExpressionNode*>(makeNumberNode($1), 0); }
| STRING { $$ = createNodeFeatureInfo<ExpressionNode*>(new StringNode($1), 0); }
| '/' /* regexp */ {
- Lexer& l = *static_cast<Lexer*>(lexer);
+ Lexer& l = *LEXER;
if (!l.scanRegExp())
YYABORT;
$$ = createNodeFeatureInfo<ExpressionNode*>(new RegExpNode(l.pattern(), l.flags()), 0);
}
| DIVEQUAL /* regexp with /= */ {
- Lexer& l = *static_cast<Lexer*>(lexer);
+ Lexer& l = *LEXER;
if (!l.scanRegExp())
YYABORT;
$$ = createNodeFeatureInfo<ExpressionNode*>(new RegExpNode("=" + l.pattern(), l.flags()), 0);
@@ -298,9 +302,9 @@
IDENT ':' AssignmentExpr { $$ = createNodeFeatureInfo<PropertyNode*>(new PropertyNode(*$1, $3.m_node, PropertyNode::Constant), $3.m_featureInfo); }
| STRING ':' AssignmentExpr { $$ = createNodeFeatureInfo<PropertyNode*>(new PropertyNode(Identifier(*$1), $3.m_node, PropertyNode::Constant), $3.m_featureInfo); }
| NUMBER ':' AssignmentExpr { $$ = createNodeFeatureInfo<PropertyNode*>(new PropertyNode(Identifier(UString::from($1)), $3.m_node, PropertyNode::Constant), $3.m_featureInfo); }
- | IDENT IDENT '(' ')' '{' FunctionBody '}' { $$ = createNodeFeatureInfo<PropertyNode*>(makeGetterOrSetterPropertyNode(*$1, *$2, 0, $6), ClosureFeature); DBG($6, @5, @7); if (!$$.m_node) YYABORT; }
- | IDENT IDENT '(' FormalParameterList ')' '{' FunctionBody '}'
- { $$ = createNodeFeatureInfo<PropertyNode*>(makeGetterOrSetterPropertyNode(*$1, *$2, $4.head, $7), ClosureFeature); DBG($7, @6, @8); if (!$$.m_node) YYABORT; }
+ | IDENT IDENT '(' ')' OPENBRACE FunctionBody CLOSEBRACE { $$ = createNodeFeatureInfo<PropertyNode*>(makeGetterOrSetterPropertyNode(*$1, *$2, 0, $6, LEXER->sourceRange($5, $7)), ClosureFeature); DBG($6, @5, @7); if (!$$.m_node) YYABORT; }
+ | IDENT IDENT '(' FormalParameterList ')' OPENBRACE FunctionBody CLOSEBRACE
+ { $$ = createNodeFeatureInfo<PropertyNode*>(makeGetterOrSetterPropertyNode(*$1, *$2, $4.head, $7, LEXER->sourceRange($6, $8)), ClosureFeature); DBG($7, @6, @8); if (!$$.m_node) YYABORT; }
;
PropertyList:
@@ -314,10 +318,10 @@
PrimaryExpr:
PrimaryExprNoBrace
- | '{' '}' { $$ = createNodeFeatureInfo<ExpressionNode*>(new ObjectLiteralNode(), 0); }
- | '{' PropertyList '}' { $$ = createNodeFeatureInfo<ExpressionNode*>(new ObjectLiteralNode($2.m_node.head), $2.m_featureInfo); }
+ | OPENBRACE CLOSEBRACE { $$ = createNodeFeatureInfo<ExpressionNode*>(new ObjectLiteralNode(), 0); }
+ | OPENBRACE PropertyList CLOSEBRACE { $$ = createNodeFeatureInfo<ExpressionNode*>(new ObjectLiteralNode($2.m_node.head), $2.m_featureInfo); }
/* allow extra comma, see http://bugs.webkit.org/show_bug.cgi?id=5939 */
- | '{' PropertyList ',' '}' { $$ = createNodeFeatureInfo<ExpressionNode*>(new ObjectLiteralNode($2.m_node.head), $2.m_featureInfo); }
+ | OPENBRACE PropertyList ',' CLOSEBRACE { $$ = createNodeFeatureInfo<ExpressionNode*>(new ObjectLiteralNode($2.m_node.head), $2.m_featureInfo); }
;
PrimaryExprNoBrace:
@@ -419,24 +423,24 @@
PostfixExpr:
LeftHandSideExpr
- | LeftHandSideExpr PLUSPLUS { $$ = createNodeFeatureInfo<ExpressionNode*>(makePostfixNode($1.m_node, OpPlusPlus), $1.m_featureInfo); }
- | LeftHandSideExpr MINUSMINUS { $$ = createNodeFeatureInfo<ExpressionNode*>(makePostfixNode($1.m_node, OpMinusMinus), $1.m_featureInfo); }
+ | LeftHandSideExpr PLUSPLUS { $$ = createNodeFeatureInfo<ExpressionNode*>(makePostfixNode($1.m_node, OpPlusPlus), $1.m_featureInfo | AssignFeature); }
+ | LeftHandSideExpr MINUSMINUS { $$ = createNodeFeatureInfo<ExpressionNode*>(makePostfixNode($1.m_node, OpMinusMinus), $1.m_featureInfo | AssignFeature); }
;
PostfixExprNoBF:
LeftHandSideExprNoBF
- | LeftHandSideExprNoBF PLUSPLUS { $$ = createNodeFeatureInfo<ExpressionNode*>(makePostfixNode($1.m_node, OpPlusPlus), $1.m_featureInfo); }
- | LeftHandSideExprNoBF MINUSMINUS { $$ = createNodeFeatureInfo<ExpressionNode*>(makePostfixNode($1.m_node, OpMinusMinus), $1.m_featureInfo); }
+ | LeftHandSideExprNoBF PLUSPLUS { $$ = createNodeFeatureInfo<ExpressionNode*>(makePostfixNode($1.m_node, OpPlusPlus), $1.m_featureInfo | AssignFeature); }
+ | LeftHandSideExprNoBF MINUSMINUS { $$ = createNodeFeatureInfo<ExpressionNode*>(makePostfixNode($1.m_node, OpMinusMinus), $1.m_featureInfo | AssignFeature); }
;
UnaryExprCommon:
DELETETOKEN UnaryExpr { $$ = createNodeFeatureInfo<ExpressionNode*>(makeDeleteNode($2.m_node), $2.m_featureInfo); }
| VOIDTOKEN UnaryExpr { $$ = createNodeFeatureInfo<ExpressionNode*>(new VoidNode($2.m_node), $2.m_featureInfo); }
| TYPEOF UnaryExpr { $$ = createNodeFeatureInfo<ExpressionNode*>(makeTypeOfNode($2.m_node), $2.m_featureInfo); }
- | PLUSPLUS UnaryExpr { $$ = createNodeFeatureInfo<ExpressionNode*>(makePrefixNode($2.m_node, OpPlusPlus), $2.m_featureInfo); }
- | AUTOPLUSPLUS UnaryExpr { $$ = createNodeFeatureInfo<ExpressionNode*>(makePrefixNode($2.m_node, OpPlusPlus), $2.m_featureInfo); }
- | MINUSMINUS UnaryExpr { $$ = createNodeFeatureInfo<ExpressionNode*>(makePrefixNode($2.m_node, OpMinusMinus), $2.m_featureInfo); }
- | AUTOMINUSMINUS UnaryExpr { $$ = createNodeFeatureInfo<ExpressionNode*>(makePrefixNode($2.m_node, OpMinusMinus), $2.m_featureInfo); }
+ | PLUSPLUS UnaryExpr { $$ = createNodeFeatureInfo<ExpressionNode*>(makePrefixNode($2.m_node, OpPlusPlus), $2.m_featureInfo | AssignFeature); }
+ | AUTOPLUSPLUS UnaryExpr { $$ = createNodeFeatureInfo<ExpressionNode*>(makePrefixNode($2.m_node, OpPlusPlus), $2.m_featureInfo | AssignFeature); }
+ | MINUSMINUS UnaryExpr { $$ = createNodeFeatureInfo<ExpressionNode*>(makePrefixNode($2.m_node, OpMinusMinus), $2.m_featureInfo | AssignFeature); }
+ | AUTOMINUSMINUS UnaryExpr { $$ = createNodeFeatureInfo<ExpressionNode*>(makePrefixNode($2.m_node, OpMinusMinus), $2.m_featureInfo | AssignFeature); }
| '+' UnaryExpr { $$ = createNodeFeatureInfo<ExpressionNode*>(new UnaryPlusNode($2.m_node), $2.m_featureInfo); }
| '-' UnaryExpr { $$ = createNodeFeatureInfo<ExpressionNode*>(makeNegateNode($2.m_node), $2.m_featureInfo); }
| '~' UnaryExpr { $$ = createNodeFeatureInfo<ExpressionNode*>(new BitwiseNotNode($2.m_node), $2.m_featureInfo); }
@@ -663,19 +667,19 @@
AssignmentExpr:
ConditionalExpr
| LeftHandSideExpr AssignmentOperator AssignmentExpr
- { $$ = createNodeFeatureInfo<ExpressionNode*>(makeAssignNode($1.m_node, $2, $3.m_node), $1.m_featureInfo | $3.m_featureInfo); }
+ { $$ = createNodeFeatureInfo<ExpressionNode*>(makeAssignNode($1.m_node, $2, $3.m_node, $1.m_featureInfo & AssignFeature, $3.m_featureInfo & AssignFeature), $1.m_featureInfo | $3.m_featureInfo | AssignFeature); }
;
AssignmentExprNoIn:
ConditionalExprNoIn
| LeftHandSideExpr AssignmentOperator AssignmentExprNoIn
- { $$ = createNodeFeatureInfo<ExpressionNode*>(makeAssignNode($1.m_node, $2, $3.m_node), $1.m_featureInfo | $3.m_featureInfo); }
+ { $$ = createNodeFeatureInfo<ExpressionNode*>(makeAssignNode($1.m_node, $2, $3.m_node, $1.m_featureInfo & AssignFeature, $3.m_featureInfo & AssignFeature), $1.m_featureInfo | $3.m_featureInfo | AssignFeature); }
;
AssignmentExprNoBF:
ConditionalExprNoBF
| LeftHandSideExprNoBF AssignmentOperator AssignmentExpr
- { $$ = createNodeFeatureInfo<ExpressionNode*>(makeAssignNode($1.m_node, $2, $3.m_node), $1.m_featureInfo | $3.m_featureInfo); }
+ { $$ = createNodeFeatureInfo<ExpressionNode*>(makeAssignNode($1.m_node, $2, $3.m_node, $1.m_featureInfo & AssignFeature, $3.m_featureInfo & AssignFeature), $1.m_featureInfo | $3.m_featureInfo | AssignFeature); }
;
AssignmentOperator:
@@ -728,9 +732,9 @@
;
Block:
- '{' '}' { $$ = createNodeDeclarationInfo<StatementNode*>(new BlockNode(0), 0, 0, 0);
+ OPENBRACE CLOSEBRACE { $$ = createNodeDeclarationInfo<StatementNode*>(new BlockNode(0), 0, 0, 0);
DBG($$.m_node, @1, @2); }
- | '{' SourceElements '}' { $$ = createNodeDeclarationInfo<StatementNode*>(new BlockNode($2.m_node), $2.m_varDeclarations, $2.m_funcDeclarations, $2.m_featureInfo);
+ | OPENBRACE SourceElements CLOSEBRACE { $$ = createNodeDeclarationInfo<StatementNode*>(new BlockNode($2.m_node), $2.m_varDeclarations, $2.m_funcDeclarations, $2.m_featureInfo);
DBG($$.m_node, @1, @3); }
;
@@ -749,7 +753,7 @@
$$.m_funcDeclarations = 0;
$$.m_featureInfo = 0;
}
- | IDENT Initializer { $$.m_node = new AssignResolveNode(*$1, $2.m_node);
+ | IDENT Initializer { $$.m_node = new AssignResolveNode(*$1, $2.m_node, $2.m_featureInfo & AssignFeature);
$$.m_varDeclarations = new ParserRefCountedData<DeclarationStacks::VarStack>;
appendToVarDeclarationList($$.m_varDeclarations, *$1, DeclarationStacks::HasInitializer);
$$.m_funcDeclarations = 0;
@@ -763,7 +767,7 @@
$$.m_featureInfo = $1.m_featureInfo;
}
| VariableDeclarationList ',' IDENT Initializer
- { $$.m_node = combineVarInitializers($1.m_node, new AssignResolveNode(*$3, $4.m_node));
+ { $$.m_node = combineVarInitializers($1.m_node, new AssignResolveNode(*$3, $4.m_node, $4.m_featureInfo & AssignFeature));
$$.m_varDeclarations = $1.m_varDeclarations;
appendToVarDeclarationList($$.m_varDeclarations, *$3, DeclarationStacks::HasInitializer);
$$.m_funcDeclarations = 0;
@@ -778,7 +782,7 @@
$$.m_funcDeclarations = 0;
$$.m_featureInfo = 0;
}
- | IDENT InitializerNoIn { $$.m_node = new AssignResolveNode(*$1, $2.m_node);
+ | IDENT InitializerNoIn { $$.m_node = new AssignResolveNode(*$1, $2.m_node, $2.m_featureInfo & AssignFeature);
$$.m_varDeclarations = new ParserRefCountedData<DeclarationStacks::VarStack>;
appendToVarDeclarationList($$.m_varDeclarations, *$1, DeclarationStacks::HasInitializer);
$$.m_funcDeclarations = 0;
@@ -792,7 +796,7 @@
$$.m_featureInfo = $1.m_featureInfo;
}
| VariableDeclarationListNoIn ',' IDENT InitializerNoIn
- { $$.m_node = combineVarInitializers($1.m_node, new AssignResolveNode(*$3, $4.m_node));
+ { $$.m_node = combineVarInitializers($1.m_node, new AssignResolveNode(*$3, $4.m_node, $4.m_featureInfo & AssignFeature));
$$.m_varDeclarations = $1.m_varDeclarations;
appendToVarDeclarationList($$.m_varDeclarations, *$3, DeclarationStacks::HasInitializer);
$$.m_funcDeclarations = 0;
@@ -949,8 +953,8 @@
;
CaseBlock:
- '{' CaseClausesOpt '}' { $$ = createNodeDeclarationInfo<CaseBlockNode*>(new CaseBlockNode($2.m_node.head, 0, 0), $2.m_varDeclarations, $2.m_funcDeclarations, $2.m_featureInfo); }
- | '{' CaseClausesOpt DefaultClause CaseClausesOpt '}'
+ OPENBRACE CaseClausesOpt CLOSEBRACE { $$ = createNodeDeclarationInfo<CaseBlockNode*>(new CaseBlockNode($2.m_node.head, 0, 0), $2.m_varDeclarations, $2.m_funcDeclarations, $2.m_featureInfo); }
+ | OPENBRACE CaseClausesOpt DefaultClause CaseClausesOpt CLOSEBRACE
{ $$ = createNodeDeclarationInfo<CaseBlockNode*>(new CaseBlockNode($2.m_node.head, $3.m_node, $4.m_node.head),
mergeDeclarationLists(mergeDeclarationLists($2.m_varDeclarations, $3.m_varDeclarations), $4.m_varDeclarations),
mergeDeclarationLists(mergeDeclarationLists($2.m_funcDeclarations, $3.m_funcDeclarations), $4.m_funcDeclarations),
@@ -1023,16 +1027,16 @@
;
FunctionDeclaration:
- FUNCTION IDENT '(' ')' '{' FunctionBody '}' { $$ = new FuncDeclNode(*$2, $6); DBG($6, @5, @7); }
- | FUNCTION IDENT '(' FormalParameterList ')' '{' FunctionBody '}'
- { $$ = new FuncDeclNode(*$2, $4.head, $7); DBG($7, @6, @8); }
+ FUNCTION IDENT '(' ')' OPENBRACE FunctionBody CLOSEBRACE { $$ = new FuncDeclNode(*$2, $6, LEXER->sourceRange($5, $7)); DBG($6, @5, @7); }
+ | FUNCTION IDENT '(' FormalParameterList ')' OPENBRACE FunctionBody CLOSEBRACE
+ { $$ = new FuncDeclNode(*$2, $7, LEXER->sourceRange($6, $8), $4.head); DBG($7, @6, @8); }
;
FunctionExpr:
- FUNCTION '(' ')' '{' FunctionBody '}' { $$ = createNodeFeatureInfo(new FuncExprNode(CommonIdentifiers::shared()->nullIdentifier, $5), ClosureFeature); DBG($5, @4, @6); }
- | FUNCTION '(' FormalParameterList ')' '{' FunctionBody '}' { $$ = createNodeFeatureInfo(new FuncExprNode(CommonIdentifiers::shared()->nullIdentifier, $6, $3.head), ClosureFeature); DBG($6, @5, @7); }
- | FUNCTION IDENT '(' ')' '{' FunctionBody '}' { $$ = createNodeFeatureInfo(new FuncExprNode(*$2, $6), ClosureFeature); DBG($6, @5, @7); }
- | FUNCTION IDENT '(' FormalParameterList ')' '{' FunctionBody '}' { $$ = createNodeFeatureInfo(new FuncExprNode(*$2, $7, $4.head), ClosureFeature); DBG($7, @6, @8); }
+ FUNCTION '(' ')' OPENBRACE FunctionBody CLOSEBRACE { $$ = createNodeFeatureInfo(new FuncExprNode(CommonIdentifiers::shared()->nullIdentifier, $5, LEXER->sourceRange($4, $6)), ClosureFeature); DBG($5, @4, @6); }
+ | FUNCTION '(' FormalParameterList ')' OPENBRACE FunctionBody CLOSEBRACE { $$ = createNodeFeatureInfo(new FuncExprNode(CommonIdentifiers::shared()->nullIdentifier, $6, LEXER->sourceRange($5, $7), $3.head), ClosureFeature); DBG($6, @5, @7); }
+ | FUNCTION IDENT '(' ')' OPENBRACE FunctionBody CLOSEBRACE { $$ = createNodeFeatureInfo(new FuncExprNode(*$2, $6, LEXER->sourceRange($5, $7)), ClosureFeature); DBG($6, @5, @7); }
+ | FUNCTION IDENT '(' FormalParameterList ')' OPENBRACE FunctionBody CLOSEBRACE { $$ = createNodeFeatureInfo(new FuncExprNode(*$2, $7, LEXER->sourceRange($6, $8), $4.head), ClosureFeature); DBG($7, @6, @8); }
;
FormalParameterList:
@@ -1061,7 +1065,7 @@
;
Program:
- /* not in spec */ { parser().didFinishParsing(0, 0, 0, false, false, @0.last_line); }
+ /* not in spec */ { parser().didFinishParsing(new SourceElements, 0, 0, false, false, @0.last_line); }
| SourceElements { parser().didFinishParsing($1.m_node, $1.m_varDeclarations, $1.m_funcDeclarations,
($1.m_featureInfo & EvalFeature) != 0, ($1.m_featureInfo & ClosureFeature) != 0,
@1.last_line); }
@@ -1121,7 +1125,7 @@
return new LessNode(left, right);
}
-static ExpressionNode* makeAssignNode(ExpressionNode* loc, Operator op, ExpressionNode* expr)
+static ExpressionNode* makeAssignNode(ExpressionNode* loc, Operator op, ExpressionNode* expr, bool locHasAssignments, bool exprHasAssignments)
{
if (!loc->isLocation())
return new AssignErrorNode(loc, op, expr);
@@ -1129,22 +1133,22 @@
if (loc->isResolveNode()) {
ResolveNode* resolve = static_cast<ResolveNode*>(loc);
if (op == OpEqual)
- return new AssignResolveNode(resolve->identifier(), expr);
+ return new AssignResolveNode(resolve->identifier(), expr, exprHasAssignments);
else
- return new ReadModifyResolveNode(resolve->identifier(), op, expr);
+ return new ReadModifyResolveNode(resolve->identifier(), op, expr, exprHasAssignments);
}
if (loc->isBracketAccessorNode()) {
BracketAccessorNode* bracket = static_cast<BracketAccessorNode*>(loc);
if (op == OpEqual)
- return new AssignBracketNode(bracket->base(), bracket->subscript(), expr);
+ return new AssignBracketNode(bracket->base(), bracket->subscript(), expr, locHasAssignments, exprHasAssignments);
else
- return new ReadModifyBracketNode(bracket->base(), bracket->subscript(), op, expr);
+ return new ReadModifyBracketNode(bracket->base(), bracket->subscript(), op, expr, locHasAssignments, exprHasAssignments);
}
ASSERT(loc->isDotAccessorNode());
DotAccessorNode* dot = static_cast<DotAccessorNode*>(loc);
if (op == OpEqual)
- return new AssignDotNode(dot->base(), dot->identifier(), expr);
- return new ReadModifyDotNode(dot->base(), dot->identifier(), op, expr);
+ return new AssignDotNode(dot->base(), dot->identifier(), expr, exprHasAssignments);
+ return new ReadModifyDotNode(dot->base(), dot->identifier(), op, expr, exprHasAssignments);
}
static ExpressionNode* makePrefixNode(ExpressionNode* expr, Operator op)
@@ -1247,7 +1251,7 @@
return new DeleteDotNode(dot->base(), dot->identifier());
}
-static PropertyNode* makeGetterOrSetterPropertyNode(const Identifier& getOrSet, const Identifier& name, ParameterNode* params, FunctionBodyNode* body)
+static PropertyNode* makeGetterOrSetterPropertyNode(const Identifier& getOrSet, const Identifier& name, ParameterNode* params, FunctionBodyNode* body, const SourceRange& source)
{
PropertyNode::Type type;
if (getOrSet == "get")
@@ -1256,7 +1260,7 @@
type = PropertyNode::Setter;
else
return 0;
- return new PropertyNode(name, new FuncExprNode(CommonIdentifiers::shared()->nullIdentifier, body, params), type);
+ return new PropertyNode(name, new FuncExprNode(CommonIdentifiers::shared()->nullIdentifier, body, source, params), type);
}
static ExpressionNode* makeNegateNode(ExpressionNode* n)
@@ -1290,7 +1294,7 @@
/* may we automatically insert a semicolon ? */
static bool allowAutomaticSemicolon(Lexer& lexer, int yychar)
{
- return yychar == '}' || yychar == 0 || lexer.prevTerminator();
+ return yychar == CLOSEBRACE || yychar == 0 || lexer.prevTerminator();
}
static ExpressionNode* combineVarInitializers(ExpressionNode* list, AssignResolveNode* init)
diff --git a/JavaScriptCore/kjs/internal.cpp b/JavaScriptCore/kjs/internal.cpp
index 4155418..fe23e26 100644
--- a/JavaScriptCore/kjs/internal.cpp
+++ b/JavaScriptCore/kjs/internal.cpp
@@ -85,6 +85,11 @@
// ------------------------------ NumberImp ------------------------------------
+JSType NumberImp::type() const
+{
+ return NumberType;
+}
+
JSValue* NumberImp::toPrimitive(ExecState*, JSType) const
{
return const_cast<NumberImp*>(this);
@@ -232,9 +237,9 @@
{
}
-bool InternalFunctionImp::implementsCall() const
+CallType InternalFunctionImp::getCallData(CallData&)
{
- return true;
+ return CallTypeNative;
}
bool InternalFunctionImp::implementsHasInstance() const
diff --git a/JavaScriptCore/kjs/internal.h b/JavaScriptCore/kjs/internal.h
index f8a2dc6..b41f10e0 100644
--- a/JavaScriptCore/kjs/internal.h
+++ b/JavaScriptCore/kjs/internal.h
@@ -63,51 +63,10 @@
UString val;
};
- class NumberImp : public JSCell {
- friend class ConstantValues;
- friend JSValue *jsNumberCell(double);
- public:
- double value() const { return val; }
-
- virtual JSType type() const { return NumberType; }
-
- virtual JSValue* toPrimitive(ExecState*, JSType preferred = UnspecifiedType) const;
- virtual bool getPrimitiveNumber(ExecState*, double& number, JSValue*& value);
- virtual bool toBoolean(ExecState *exec) const;
- virtual double toNumber(ExecState *exec) const;
- virtual UString toString(ExecState *exec) const;
- virtual JSObject *toObject(ExecState *exec) const;
-
- void* operator new(size_t size)
- {
- return Collector::allocateNumber(size);
- }
- private:
- NumberImp(double v) : val(v) { }
-
- virtual bool getUInt32(uint32_t&) const;
- virtual bool getTruncatedInt32(int32_t&) const;
- virtual bool getTruncatedUInt32(uint32_t&) const;
-
- double val;
- };
-
-
// ---------------------------------------------------------------------------
// Evaluation
// ---------------------------------------------------------------------------
- struct AttachedGlobalObject;
- class DebuggerImp {
- public:
-
- DebuggerImp() {
- globalObjects = 0;
- }
-
- AttachedGlobalObject* globalObjects;
- };
-
} // namespace
#endif // INTERNAL_H
diff --git a/JavaScriptCore/kjs/interpreter.cpp b/JavaScriptCore/kjs/interpreter.cpp
index e0e1f18..ebf614e 100644
--- a/JavaScriptCore/kjs/interpreter.cpp
+++ b/JavaScriptCore/kjs/interpreter.cpp
@@ -25,6 +25,7 @@
#include "ExecState.h"
#include "JSGlobalObject.h"
+#include "Machine.h"
#include "Parser.h"
#include "debugger.h"
#include <profiler/Profiler.h>
@@ -38,35 +39,31 @@
Completion Interpreter::checkSyntax(ExecState* exec, const UString& sourceURL, int startingLineNumber, const UString& code)
{
- return checkSyntax(exec, sourceURL, startingLineNumber, code.data(), code.size());
+ return checkSyntax(exec, sourceURL, startingLineNumber, UStringSourceProvider::create(code));
}
-Completion Interpreter::checkSyntax(ExecState* exec, const UString& sourceURL, int startingLineNumber, const UChar* code, int codeLength)
+Completion Interpreter::checkSyntax(ExecState* exec, const UString& sourceURL, int startingLineNumber, PassRefPtr<SourceProvider> source)
{
JSLock lock;
int errLine;
UString errMsg;
- RefPtr<ProgramNode> progNode = parser().parse<ProgramNode>(sourceURL, startingLineNumber, code, codeLength, 0, &errLine, &errMsg);
+
+ RefPtr<ProgramNode> progNode = parser().parse<ProgramNode>(exec, sourceURL, startingLineNumber, source, 0, &errLine, &errMsg);
if (!progNode)
return Completion(Throw, Error::create(exec, SyntaxError, errMsg, errLine, 0, sourceURL));
return Completion(Normal);
}
-Completion Interpreter::evaluate(ExecState* exec, const UString& sourceURL, int startingLineNumber, const UString& code, JSValue* thisV)
+Completion Interpreter::evaluate(ExecState* exec, ScopeChain& scopeChain, const UString& sourceURL, int startingLineNumber, const UString& code, JSValue* thisV)
{
- return evaluate(exec, sourceURL, startingLineNumber, code.data(), code.size(), thisV);
+ return evaluate(exec, scopeChain, sourceURL, startingLineNumber, UStringSourceProvider::create(code), thisV);
}
-Completion Interpreter::evaluate(ExecState* exec, const UString& sourceURL, int startingLineNumber, const UChar* code, int codeLength, JSValue* thisV)
+Completion Interpreter::evaluate(ExecState* exec, ScopeChain& scopeChain, const UString& sourceURL, int startingLineNumber, PassRefPtr<SourceProvider> source, JSValue* thisValue)
{
JSLock lock;
- JSGlobalObject* globalObject = exec->dynamicGlobalObject();
-
- if (globalObject->recursion() >= 20)
- return Completion(Throw, Error::create(exec, GeneralError, "Recursion too deep"));
-
// parse the source code
int sourceId;
int errLine;
@@ -76,60 +73,22 @@
Profiler::profiler()->willExecute(exec, sourceURL, startingLineNumber);
#endif
- RefPtr<ProgramNode> progNode = parser().parse<ProgramNode>(sourceURL, startingLineNumber, code, codeLength, &sourceId, &errLine, &errMsg);
-
- // notify debugger that source has been parsed
- if (globalObject->debugger()) {
- bool cont = globalObject->debugger()->sourceParsed(exec, sourceId, sourceURL, UString(code, codeLength), startingLineNumber, errLine, errMsg);
- if (!cont)
- return Completion(Break);
- }
-
+ RefPtr<ProgramNode> programNode = parser().parse<ProgramNode>(exec, sourceURL, startingLineNumber, source, &sourceId, &errLine, &errMsg);
+
// no program node means a syntax error occurred
- if (!progNode)
+ if (!programNode)
return Completion(Throw, Error::create(exec, SyntaxError, errMsg, errLine, sourceId, sourceURL));
-
- exec->clearException();
-
- globalObject->incRecursion();
-
- JSObject* thisObj = globalObject;
-
- // "this" must be an object... use same rules as Function.prototype.apply()
- if (thisV && !thisV->isUndefinedOrNull())
- thisObj = thisV->toObject(exec);
-
- Completion res;
- if (exec->hadException())
- // the thisV->toObject() conversion above might have thrown an exception - if so, propagate it
- res = Completion(Throw, exec->exception());
- else {
- // execute the code
- InterpreterExecState newExec(globalObject, thisObj, progNode.get());
- JSValue* value = progNode->execute(&newExec);
- res = Completion(newExec.completionType(), value);
- }
+
+ JSObject* thisObj = (!thisValue || thisValue->isUndefinedOrNull()) ? exec->dynamicGlobalObject() : thisValue->toObject(exec);
+
+ JSValue* exception = 0;
+ JSValue* result = machine().execute(programNode.get(), exec, scopeChain.node(), thisObj, &exec->dynamicGlobalObject()->registerFileStack(), &exception);
#if JAVASCRIPT_PROFILING
- Profiler::profiler()->didExecute(exec, sourceURL, startingLineNumber);
+ Profiler::profiler()->didExecute(exec, sourceURL, startingLineNumber);
#endif
- globalObject->decRecursion();
-
- if (shouldPrintExceptions() && res.complType() == Throw) {
- JSLock lock;
- ExecState* exec = globalObject->globalExec();
- CString f = sourceURL.UTF8String();
- CString message = res.value()->toObject(exec)->toString(exec).UTF8String();
- int line = res.value()->toObject(exec)->get(exec, "line")->toUInt32(exec);
-#if PLATFORM(WIN_OS)
- printf("%s line %d: %s\n", f.c_str(), line, message.c_str());
-#else
- printf("[%d] %s line %d: %s\n", getpid(), f.c_str(), line, message.c_str());
-#endif
- }
-
- return res;
+ return exception ? Completion(Throw, exception) : Completion(Normal, result);
}
static bool printExceptions = false;
diff --git a/JavaScriptCore/kjs/interpreter.h b/JavaScriptCore/kjs/interpreter.h
index 5b52d8c..a8dbd6e 100644
--- a/JavaScriptCore/kjs/interpreter.h
+++ b/JavaScriptCore/kjs/interpreter.h
@@ -23,6 +23,7 @@
#ifndef KJS_Interpreter_h
#define KJS_Interpreter_h
+#include <wtf/PassRefPtr.h>
#include <wtf/unicode/Unicode.h>
namespace KJS {
@@ -30,6 +31,8 @@
class Completion;
class ExecState;
class JSValue;
+ class ScopeChain;
+ class SourceProvider;
class UString;
class Interpreter {
@@ -42,7 +45,7 @@
* otherwise a throw completion with the syntax error as its value.
*/
static Completion checkSyntax(ExecState*, const UString& sourceURL, int startingLineNumber, const UString& code);
- static Completion checkSyntax(ExecState*, const UString& sourceURL, int startingLineNumber, const UChar* code, int codeLength);
+ static Completion checkSyntax(ExecState*, const UString& sourceURL, int startingLineNumber, PassRefPtr<SourceProvider> source);
/**
* Evaluates the supplied ECMAScript code.
@@ -59,8 +62,8 @@
* execution. This should either be jsNull() or an Object.
* @return A completion object representing the result of the execution.
*/
- static Completion evaluate(ExecState*, const UString& sourceURL, int startingLineNumber, const UString& code, JSValue* thisV = 0);
- static Completion evaluate(ExecState*, const UString& sourceURL, int startingLineNumber, const UChar* code, int codeLength, JSValue* thisV = 0);
+ static Completion evaluate(ExecState*, ScopeChain&, const UString& sourceURL, int startingLineNumber, const UString& code, JSValue* thisV = 0);
+ static Completion evaluate(ExecState*, ScopeChain&, const UString& sourceURL, int startingLineNumber, PassRefPtr<SourceProvider>, JSValue* thisV = 0);
static bool shouldPrintExceptions();
static void setShouldPrintExceptions(bool);
diff --git a/JavaScriptCore/kjs/lexer.cpp b/JavaScriptCore/kjs/lexer.cpp
index 090c5dc..05f25f2 100644
--- a/JavaScriptCore/kjs/lexer.cpp
+++ b/JavaScriptCore/kjs/lexer.cpp
@@ -101,7 +101,7 @@
delete[] mainTable.table;
}
-void Lexer::setCode(int startingLineNumber, const UChar* c, unsigned int len)
+void Lexer::setCode(int startingLineNumber, PassRefPtr<SourceProvider> source)
{
yylineno = 1 + startingLineNumber;
restrKeyword = false;
@@ -109,9 +109,11 @@
eatNextIdentifier = false;
stackToken = -1;
lastToken = -1;
+
pos = 0;
- code = c;
- length = len;
+ m_source = source;
+ code = m_source->data();
+ length = m_source->length();
skipLF = false;
skipCR = false;
error = false;
@@ -132,6 +134,7 @@
next2 = next3;
do {
if (pos >= length) {
+ pos++;
next3 = -1;
break;
}
@@ -238,7 +241,7 @@
shift(2);
state = InSingleLineComment;
} else {
- token = matchPunctuator(current, next1, next2, next3);
+ token = matchPunctuator(lvalp->intValue, current, next1, next2, next3);
if (token != -1) {
setDone(Other);
} else {
@@ -642,7 +645,7 @@
return (c >= '0' && c <= '7');
}
-int Lexer::matchPunctuator(int c1, int c2, int c3, int c4)
+int Lexer::matchPunctuator(int& charPos, int c1, int c2, int c3, int c4)
{
if (c1 == '>' && c2 == '>' && c3 == '>' && c4 == '=') {
shift(4);
@@ -744,13 +747,19 @@
case '%':
case '(':
case ')':
- case '{':
- case '}':
case '[':
case ']':
case ';':
shift(1);
return static_cast<int>(c1);
+ case '{':
+ charPos = pos - 4;
+ shift(1);
+ return OPENBRACE;
+ case '}':
+ charPos = pos - 4;
+ shift(1);
+ return CLOSEBRACE;
default:
return -1;
}
diff --git a/JavaScriptCore/kjs/lexer.h b/JavaScriptCore/kjs/lexer.h
index cd3085a..673e787 100644
--- a/JavaScriptCore/kjs/lexer.h
+++ b/JavaScriptCore/kjs/lexer.h
@@ -27,6 +27,7 @@
#include "lookup.h"
#include "ustring.h"
#include <wtf/Vector.h>
+#include "SourceRange.h"
namespace WTF {
template<typename T> class ThreadSpecific;
@@ -39,7 +40,7 @@
class Lexer : Noncopyable {
public:
- void setCode(int startingLineNumber, const UChar *c, unsigned int len);
+ void setCode(int startingLineNumber, PassRefPtr<SourceProvider> source);
int lex(void* lvalp, void* llocp);
int lineNo() const { return yylineno; }
@@ -90,6 +91,7 @@
bool sawError() const { return error; }
void clear();
+ SourceRange sourceRange(int openBrace, int closeBrace) { return SourceRange(m_source, openBrace + 1, closeBrace); }
private:
friend Lexer& lexer();
@@ -122,7 +124,7 @@
bool isLineTerminator();
static bool isOctalDigit(int);
- int matchPunctuator(int c1, int c2, int c3, int c4);
+ int matchPunctuator(int& charPos, int c1, int c2, int c3, int c4);
static unsigned short singleEscape(unsigned short);
static unsigned short convertOctal(int c1, int c2, int c3);
@@ -133,6 +135,7 @@
KJS::Identifier* makeIdentifier(const Vector<UChar>& buffer);
UString* makeUString(const Vector<UChar>& buffer);
+ RefPtr<SourceProvider> m_source;
const UChar* code;
unsigned int length;
int yycolumn;
diff --git a/JavaScriptCore/kjs/list.cpp b/JavaScriptCore/kjs/list.cpp
index 5cc7cc2..6cc28c3 100644
--- a/JavaScriptCore/kjs/list.cpp
+++ b/JavaScriptCore/kjs/list.cpp
@@ -27,8 +27,12 @@
void List::getSlice(int startIndex, List& result) const
{
+ ASSERT(!result.m_isReadOnly);
+
const_iterator start = min(begin() + startIndex, end());
result.m_vector.appendRange(start, end());
+ result.m_size = result.m_vector.size();
+ result.m_buffer = result.m_vector.data();
}
List::ListSet& List::markSet()
diff --git a/JavaScriptCore/kjs/list.h b/JavaScriptCore/kjs/list.h
index 6a43e08..2b6d8a9 100644
--- a/JavaScriptCore/kjs/list.h
+++ b/JavaScriptCore/kjs/list.h
@@ -41,8 +41,26 @@
typedef VectorType::iterator iterator;
typedef VectorType::const_iterator const_iterator;
+ // Constructor for a read-write list, to which you may append values.
+ // FIXME: Remove all clients of this API, then remove this API.
List()
: m_isInMarkSet(false)
+#ifndef NDEBUG
+ , m_isReadOnly(false)
+#endif
+ {
+ m_buffer = m_vector.data();
+ m_size = m_vector.size();
+ }
+
+ // Constructor for a read-only list whose data has already been allocated elsewhere.
+ List(JSValue** buffer, size_t size)
+ : m_buffer(buffer)
+ , m_size(size)
+ , m_isInMarkSet(false)
+#ifndef NDEBUG
+ , m_isReadOnly(true)
+#endif
{
}
@@ -52,38 +70,48 @@
markSet().remove(this);
}
- size_t size() const { return m_vector.size(); }
- bool isEmpty() const { return m_vector.isEmpty(); }
+ size_t size() const { return m_size; }
+ bool isEmpty() const { return !m_size; }
JSValue* at(size_t i) const
{
- if (i < m_vector.size())
- return m_vector.at(i);
+ if (i < m_size)
+ return m_buffer[i];
return jsUndefined();
}
JSValue* operator[](int i) const { return at(i); }
- void clear() { m_vector.clear(); }
+ void clear()
+ {
+ m_vector.clear();
+ m_size = 0;
+ }
void append(JSValue* v)
{
- if (m_vector.size() < m_vector.capacity())
+ ASSERT(!m_isReadOnly);
+
+ if (m_vector.size() < m_vector.capacity()) {
m_vector.uncheckedAppend(v);
- else
+ ++m_size;
+ } else {
// Putting the slow "expand and append" case all in one
// function measurably improves the performance of the fast
// "just append" case.
expandAndAppend(v);
+ m_buffer = m_vector.data();
+ ++m_size;
+ }
}
void getSlice(int startIndex, List& result) const;
- iterator begin() { return m_vector.begin(); }
- iterator end() { return m_vector.end(); }
+ iterator begin() { return m_buffer; }
+ iterator end() { return m_buffer + m_size; }
- const_iterator begin() const { return m_vector.begin(); }
- const_iterator end() const { return m_vector.end(); }
+ const_iterator begin() const { return m_buffer; }
+ const_iterator end() const { return m_buffer + m_size; }
static void markProtectedLists()
{
@@ -97,9 +125,15 @@
static void markProtectedListsSlowCase();
void expandAndAppend(JSValue*);
+
+ JSValue** m_buffer;
+ size_t m_size;
VectorType m_vector;
bool m_isInMarkSet;
+#ifndef NDEBUG
+ bool m_isReadOnly;
+#endif
private:
// Prohibits new / delete, which would break GC.
diff --git a/JavaScriptCore/kjs/nodes.cpp b/JavaScriptCore/kjs/nodes.cpp
index 291223b..3371de6 100644
--- a/JavaScriptCore/kjs/nodes.cpp
+++ b/JavaScriptCore/kjs/nodes.cpp
@@ -26,6 +26,7 @@
#include "config.h"
#include "nodes.h"
+#include "CodeGenerator.h"
#include "ExecState.h"
#include "JSGlobalObject.h"
#include "Parser.h"
@@ -47,7 +48,7 @@
class FunctionBodyNodeWithDebuggerHooks : public FunctionBodyNode {
public:
FunctionBodyNodeWithDebuggerHooks(SourceElements*, VarStack*, FunctionStack*, bool usesEval, bool needsClosure) KJS_FAST_CALL;
- virtual JSValue* execute(ExecState*) KJS_FAST_CALL;
+ virtual JSValue* execute(OldInterpreterExecState*) KJS_FAST_CALL;
};
#if COMPILER(GCC)
@@ -86,7 +87,7 @@
}
#if !ASSERT_DISABLED
-static inline bool canSkipLookup(ExecState* exec, const Identifier& ident)
+static inline bool canSkipLookup(OldInterpreterExecState* exec, const Identifier& ident)
{
// Static lookup in EvalCode is impossible because variables aren't DontDelete.
// Static lookup in GlobalCode may be possible, but we haven't implemented support for it yet.
@@ -111,6 +112,11 @@
return localStorage[index].attributes & ReadOnly;
}
+static inline UString::Rep* rep(const Identifier& ident)
+{
+ return ident.ustring().rep();
+}
+
// ------------------------------ Node -----------------------------------------
#ifndef NDEBUG
@@ -229,28 +235,28 @@
m_line = lexer().lineNo();
}
-double ExpressionNode::evaluateToNumber(ExecState* exec)
+double ExpressionNode::evaluateToNumber(OldInterpreterExecState* exec)
{
JSValue* value = evaluate(exec);
KJS_CHECKEXCEPTIONNUMBER
return value->toNumber(exec);
}
-bool ExpressionNode::evaluateToBoolean(ExecState* exec)
+bool ExpressionNode::evaluateToBoolean(OldInterpreterExecState* exec)
{
JSValue* value = evaluate(exec);
KJS_CHECKEXCEPTIONBOOLEAN
return value->toBoolean(exec);
}
-int32_t ExpressionNode::evaluateToInt32(ExecState* exec)
+int32_t ExpressionNode::evaluateToInt32(OldInterpreterExecState* exec)
{
JSValue* value = evaluate(exec);
KJS_CHECKEXCEPTIONNUMBER
return value->toInt32(exec);
}
-uint32_t ExpressionNode::evaluateToUInt32(ExecState* exec)
+uint32_t ExpressionNode::evaluateToUInt32(OldInterpreterExecState* exec)
{
JSValue* value = evaluate(exec);
KJS_CHECKEXCEPTIONNUMBER
@@ -269,42 +275,44 @@
}
static inline int currentSourceId(ExecState* exec) KJS_FAST_CALL;
-static inline int currentSourceId(ExecState* exec)
+static inline int currentSourceId(ExecState*)
{
- return exec->scopeNode()->sourceId();
+ ASSERT_NOT_REACHED();
+ return 0;
}
-static inline const UString& currentSourceURL(ExecState* exec) KJS_FAST_CALL;
-static inline const UString& currentSourceURL(ExecState* exec)
+static inline const UString currentSourceURL(ExecState* exec) KJS_FAST_CALL;
+static inline const UString currentSourceURL(ExecState*)
{
- return exec->scopeNode()->sourceURL();
+ ASSERT_NOT_REACHED();
+ return UString();
}
-JSValue* Node::setErrorCompletion(ExecState* exec, ErrorType e, const char* msg)
+JSValue* Node::setErrorCompletion(OldInterpreterExecState* exec, ErrorType e, const char* msg)
{
return exec->setThrowCompletion(Error::create(exec, e, msg, lineNo(), currentSourceId(exec), currentSourceURL(exec)));
}
-JSValue* Node::setErrorCompletion(ExecState* exec, ErrorType e, const char* msg, const Identifier& ident)
+JSValue* Node::setErrorCompletion(OldInterpreterExecState* exec, ErrorType e, const char* msg, const Identifier& ident)
{
UString message = msg;
substitute(message, ident.ustring());
return exec->setThrowCompletion(Error::create(exec, e, message, lineNo(), currentSourceId(exec), currentSourceURL(exec)));
}
-JSValue* Node::throwError(ExecState* exec, ErrorType e, const char* msg)
+JSValue* Node::throwError(OldInterpreterExecState* exec, ErrorType e, const char* msg)
{
return KJS::throwError(exec, e, msg, lineNo(), currentSourceId(exec), currentSourceURL(exec));
}
-JSValue* Node::throwError(ExecState* exec, ErrorType e, const char* msg, const char* string)
+JSValue* Node::throwError(OldInterpreterExecState* exec, ErrorType e, const char* msg, const char* string)
{
UString message = msg;
substitute(message, string);
return KJS::throwError(exec, e, message, lineNo(), currentSourceId(exec), currentSourceURL(exec));
}
-JSValue* Node::throwError(ExecState* exec, ErrorType e, const char* msg, JSValue* v, Node* expr)
+JSValue* Node::throwError(OldInterpreterExecState* exec, ErrorType e, const char* msg, JSValue* v, Node* expr)
{
UString message = msg;
substitute(message, v->toString(exec));
@@ -312,14 +320,14 @@
return KJS::throwError(exec, e, message, lineNo(), currentSourceId(exec), currentSourceURL(exec));
}
-JSValue* Node::throwError(ExecState* exec, ErrorType e, const char* msg, const Identifier& label)
+JSValue* Node::throwError(OldInterpreterExecState* exec, ErrorType e, const char* msg, const Identifier& label)
{
UString message = msg;
substitute(message, label.ustring());
return KJS::throwError(exec, e, message, lineNo(), currentSourceId(exec), currentSourceURL(exec));
}
-JSValue* Node::throwError(ExecState* exec, ErrorType e, const char* msg, JSValue* v, Node* e1, Node* e2)
+JSValue* Node::throwError(OldInterpreterExecState* exec, ErrorType e, const char* msg, JSValue* v, Node* e1, Node* e2)
{
UString message = msg;
substitute(message, v->toString(exec));
@@ -328,7 +336,7 @@
return KJS::throwError(exec, e, message, lineNo(), currentSourceId(exec), currentSourceURL(exec));
}
-JSValue* Node::throwError(ExecState* exec, ErrorType e, const char* msg, JSValue* v, Node* expr, const Identifier& label)
+JSValue* Node::throwError(OldInterpreterExecState* exec, ErrorType e, const char* msg, JSValue* v, Node* expr, const Identifier& label)
{
UString message = msg;
substitute(message, v->toString(exec));
@@ -337,7 +345,7 @@
return KJS::throwError(exec, e, message, lineNo(), currentSourceId(exec), currentSourceURL(exec));
}
-JSValue* Node::throwError(ExecState* exec, ErrorType e, const char* msg, JSValue* v, const Identifier& label)
+JSValue* Node::throwError(OldInterpreterExecState* exec, ErrorType e, const char* msg, JSValue* v, const Identifier& label)
{
UString message = msg;
substitute(message, v->toString(exec));
@@ -345,17 +353,17 @@
return KJS::throwError(exec, e, message, lineNo(), currentSourceId(exec), currentSourceURL(exec));
}
-JSValue* Node::throwUndefinedVariableError(ExecState* exec, const Identifier& ident)
+JSValue* Node::throwUndefinedVariableError(OldInterpreterExecState* exec, const Identifier& ident)
{
return throwError(exec, ReferenceError, "Can't find variable: %s", ident);
}
-void Node::handleException(ExecState* exec)
+void Node::handleException(OldInterpreterExecState* exec)
{
handleException(exec, exec->exception());
}
-void Node::handleException(ExecState* exec, JSValue* exceptionValue)
+void Node::handleException(OldInterpreterExecState* exec, JSValue* exceptionValue)
{
if (exceptionValue->isObject()) {
JSObject* exception = static_cast<JSObject*>(exceptionValue);
@@ -364,12 +372,14 @@
exception->put(exec, "sourceURL", jsString(currentSourceURL(exec)));
}
}
+#if 0
Debugger* dbg = exec->dynamicGlobalObject()->debugger();
if (dbg && !dbg->hasHandledException(exec, exceptionValue))
dbg->exception(exec, currentSourceId(exec), m_line, exceptionValue);
+#endif
}
-NEVER_INLINE JSValue* Node::rethrowException(ExecState* exec)
+NEVER_INLINE JSValue* Node::rethrowException(OldInterpreterExecState* exec)
{
JSValue* exception = exec->exception();
exec->clearException();
@@ -377,6 +387,22 @@
return exec->setThrowCompletion(exception);
}
+RegisterID* Node::emitThrowError(CodeGenerator& generator, ErrorType e, const char* msg)
+{
+ RegisterID* exception = generator.emitNewError(generator.newTemporary(), e, jsString(msg));
+ generator.emitThrow(exception);
+ return exception;
+}
+
+RegisterID* Node::emitThrowError(CodeGenerator& generator, ErrorType e, const char* msg, const Identifier& label)
+{
+ UString message = msg;
+ substitute(message, label.ustring());
+ RegisterID* exception = generator.emitNewError(generator.newTemporary(), e, jsString(message));
+ generator.emitThrow(exception);
+ return exception;
+}
+
// ------------------------------ StatementNode --------------------------------
StatementNode::StatementNode()
@@ -398,10 +424,7 @@
if (statement->isEmptyStatement())
return;
- if (Debugger::debuggersPresent)
- m_statements.append(new BreakpointCheckStatement(statement));
- else
- m_statements.append(statement);
+ m_statements.append(statement);
}
// ------------------------------ BreakpointCheckStatement --------------------------------
@@ -412,11 +435,8 @@
ASSERT(m_statement);
}
-JSValue* BreakpointCheckStatement::execute(ExecState* exec)
+JSValue* BreakpointCheckStatement::execute(OldInterpreterExecState* exec)
{
- if (Debugger* debugger = exec->dynamicGlobalObject()->debugger())
- if (!debugger->atStatement(exec, currentSourceId(exec), m_statement->firstLine(), m_statement->lastLine()))
- return exec->setNormalCompletion();
return m_statement->execute(exec);
}
@@ -425,73 +445,93 @@
m_statement->streamTo(stream);
}
-void BreakpointCheckStatement::optimizeVariableAccess(ExecState*, const SymbolTable&, const LocalStorage&, NodeStack& nodeStack)
+void BreakpointCheckStatement::optimizeVariableAccess(OldInterpreterExecState*, const SymbolTable&, const LocalStorage&, NodeStack& nodeStack)
{
nodeStack.append(m_statement.get());
}
// ------------------------------ NullNode -------------------------------------
-JSValue* NullNode::evaluate(ExecState* )
+RegisterID* NullNode::emitCode(CodeGenerator& generator, RegisterID* dst)
+{
+ return generator.emitLoad(generator.finalDestination(dst), jsNull());
+}
+
+JSValue* NullNode::evaluate(OldInterpreterExecState* )
{
return jsNull();
}
// ------------------------------ FalseNode ----------------------------------
-JSValue* FalseNode::evaluate(ExecState*)
+RegisterID* FalseNode::emitCode(CodeGenerator& generator, RegisterID* dst)
+{
+ return generator.emitLoad(generator.finalDestination(dst), false);
+}
+
+JSValue* FalseNode::evaluate(OldInterpreterExecState*)
{
return jsBoolean(false);
}
// ------------------------------ TrueNode ----------------------------------
-JSValue* TrueNode::evaluate(ExecState*)
+RegisterID* TrueNode::emitCode(CodeGenerator& generator, RegisterID* dst)
+{
+ return generator.emitLoad(generator.finalDestination(dst), true);
+}
+
+JSValue* TrueNode::evaluate(OldInterpreterExecState*)
{
return jsBoolean(true);
}
// ------------------------------ NumberNode -----------------------------------
-JSValue* NumberNode::evaluate(ExecState*)
+RegisterID* NumberNode::emitCode(CodeGenerator& generator, RegisterID* dst)
+{
+ return generator.emitLoad(generator.finalDestination(dst), m_double);
+}
+
+JSValue* NumberNode::evaluate(OldInterpreterExecState*)
{
// Number nodes are only created when the number can't fit in a JSImmediate, so no need to check again.
return jsNumberCell(m_double);
}
-double NumberNode::evaluateToNumber(ExecState*)
+double NumberNode::evaluateToNumber(OldInterpreterExecState*)
{
return m_double;
}
-bool NumberNode::evaluateToBoolean(ExecState*)
+bool NumberNode::evaluateToBoolean(OldInterpreterExecState*)
{
return m_double < 0.0 || m_double > 0.0; // false for NaN as well as 0
}
-int32_t NumberNode::evaluateToInt32(ExecState*)
+int32_t NumberNode::evaluateToInt32(OldInterpreterExecState*)
{
return JSValue::toInt32(m_double);
}
-uint32_t NumberNode::evaluateToUInt32(ExecState*)
+uint32_t NumberNode::evaluateToUInt32(OldInterpreterExecState*)
{
return JSValue::toUInt32(m_double);
}
// ------------------------------ ImmediateNumberNode -----------------------------------
-JSValue* ImmediateNumberNode::evaluate(ExecState*)
+JSValue* ImmediateNumberNode::evaluate(OldInterpreterExecState*)
{
return m_value;
}
-int32_t ImmediateNumberNode::evaluateToInt32(ExecState*)
+int32_t ImmediateNumberNode::evaluateToInt32(OldInterpreterExecState*)
{
return JSImmediate::getTruncatedInt32(m_value);
}
-uint32_t ImmediateNumberNode::evaluateToUInt32(ExecState*)
+uint32_t ImmediateNumberNode::evaluateToUInt32(OldInterpreterExecState*)
{
uint32_t i;
if (JSImmediate::getTruncatedUInt32(m_value, i))
@@ -502,40 +542,67 @@
// ------------------------------ StringNode -----------------------------------
-JSValue* StringNode::evaluate(ExecState*)
+RegisterID* StringNode::emitCode(CodeGenerator& generator, RegisterID* dst)
+{
+ // FIXME: should we try to atomize constant strings?
+ return generator.emitLoad(generator.finalDestination(dst), jsOwnedString(m_value));
+}
+
+JSValue* StringNode::evaluate(OldInterpreterExecState*)
{
return jsOwnedString(m_value);
}
-double StringNode::evaluateToNumber(ExecState*)
+double StringNode::evaluateToNumber(OldInterpreterExecState*)
{
return m_value.toDouble();
}
-bool StringNode::evaluateToBoolean(ExecState*)
+bool StringNode::evaluateToBoolean(OldInterpreterExecState*)
{
return !m_value.isEmpty();
}
// ------------------------------ RegExpNode -----------------------------------
-JSValue* RegExpNode::evaluate(ExecState* exec)
+RegisterID* RegExpNode::emitCode(CodeGenerator& generator, RegisterID* dst)
{
- return exec->lexicalGlobalObject()->regExpConstructor()->createRegExpImp(exec, m_regExp);
+ if (!m_regExp->isValid())
+ return emitThrowError(generator, SyntaxError, "Invalid regular expression: %s", m_regExp->errorMessage());
+ return generator.emitNewRegExp(generator.finalDestination(dst), m_regExp.get());
+}
+
+JSValue* RegExpNode::evaluate(OldInterpreterExecState*)
+{
+ ASSERT_NOT_REACHED();
+ return 0;
}
// ------------------------------ ThisNode -------------------------------------
+RegisterID* ThisNode::emitCode(CodeGenerator& generator, RegisterID* dst)
+{
+ return generator.moveToDestinationIfNeeded(dst, generator.thisRegister());
+}
+
// ECMA 11.1.1
-JSValue* ThisNode::evaluate(ExecState* exec)
+JSValue* ThisNode::evaluate(OldInterpreterExecState* exec)
{
return exec->thisValue();
}
// ------------------------------ ResolveNode ----------------------------------
+RegisterID* ResolveNode::emitCode(CodeGenerator& generator, RegisterID* dst)
+{
+ if (RegisterID* local = generator.registerForLocal(m_ident))
+ return generator.moveToDestinationIfNeeded(dst, local);
+
+ return generator.emitResolve(generator.finalDestination(dst), m_ident);
+}
+
// ECMA 11.1.2 & 10.1.4
-JSValue* ResolveNode::inlineEvaluate(ExecState* exec)
+JSValue* ResolveNode::inlineEvaluate(OldInterpreterExecState* exec)
{
// Check for missed optimization opportunity.
ASSERT(!canSkipLookup(exec, m_ident));
@@ -560,42 +627,42 @@
return throwUndefinedVariableError(exec, m_ident);
}
-JSValue* ResolveNode::evaluate(ExecState* exec)
+JSValue* ResolveNode::evaluate(OldInterpreterExecState* exec)
{
return inlineEvaluate(exec);
}
-double ResolveNode::evaluateToNumber(ExecState* exec)
+double ResolveNode::evaluateToNumber(OldInterpreterExecState* exec)
{
JSValue* v = inlineEvaluate(exec);
KJS_CHECKEXCEPTIONNUMBER
return v->toNumber(exec);
}
-bool ResolveNode::evaluateToBoolean(ExecState* exec)
+bool ResolveNode::evaluateToBoolean(OldInterpreterExecState* exec)
{
JSValue* v = inlineEvaluate(exec);
KJS_CHECKEXCEPTIONBOOLEAN
return v->toBoolean(exec);
}
-int32_t ResolveNode::evaluateToInt32(ExecState* exec)
+int32_t ResolveNode::evaluateToInt32(OldInterpreterExecState* exec)
{
JSValue* v = inlineEvaluate(exec);
KJS_CHECKEXCEPTIONNUMBER
return v->toInt32(exec);
}
-uint32_t ResolveNode::evaluateToUInt32(ExecState* exec)
+uint32_t ResolveNode::evaluateToUInt32(OldInterpreterExecState* exec)
{
JSValue* v = inlineEvaluate(exec);
KJS_CHECKEXCEPTIONNUMBER
return v->toUInt32(exec);
}
-static size_t getSymbolTableEntry(ExecState* exec, const Identifier& ident, const SymbolTable& symbolTable, size_t& stackDepth)
+static size_t getSymbolTableEntry(OldInterpreterExecState* exec, const Identifier& ident, const SymbolTable& symbolTable, size_t& stackDepth)
{
- size_t index = symbolTable.get(ident.ustring().rep());
+ int index = symbolTable.get(ident.ustring().rep()).getIndex();
if (index != missingSymbolMarker()) {
stackDepth = 0;
return index;
@@ -615,7 +682,7 @@
if (!currentScope->isVariableObject())
break;
JSVariableObject* currentVariableObject = static_cast<JSVariableObject*>(currentScope);
- index = currentVariableObject->symbolTable().get(ident.ustring().rep());
+ index = currentVariableObject->symbolTable().get(ident.ustring().rep()).getIndex();
if (index != missingSymbolMarker()) {
stackDepth = depth;
return index;
@@ -627,10 +694,10 @@
return missingSymbolMarker();
}
-void ResolveNode::optimizeVariableAccess(ExecState* exec, const SymbolTable& symbolTable, const LocalStorage&, NodeStack&)
+void ResolveNode::optimizeVariableAccess(OldInterpreterExecState* exec, const SymbolTable& symbolTable, const LocalStorage&, NodeStack&)
{
size_t depth = 0;
- size_t index = getSymbolTableEntry(exec, m_ident, symbolTable, depth);
+ int index = getSymbolTableEntry(exec, m_ident, symbolTable, depth);
if (index != missingSymbolMarker()) {
if (!depth)
new (this) LocalVarAccessNode(index);
@@ -645,80 +712,82 @@
new (this) NonLocalVarAccessNode(depth);
}
-JSValue* LocalVarAccessNode::inlineEvaluate(ExecState* exec)
+JSValue* LocalVarAccessNode::inlineEvaluate(OldInterpreterExecState* exec)
{
ASSERT(exec->variableObject() == exec->scopeChain().top());
return exec->localStorage()[m_index].value;
}
-JSValue* LocalVarAccessNode::evaluate(ExecState* exec)
+JSValue* LocalVarAccessNode::evaluate(OldInterpreterExecState* exec)
{
return inlineEvaluate(exec);
}
-double LocalVarAccessNode::evaluateToNumber(ExecState* exec)
+double LocalVarAccessNode::evaluateToNumber(OldInterpreterExecState* exec)
{
return inlineEvaluate(exec)->toNumber(exec);
}
-bool LocalVarAccessNode::evaluateToBoolean(ExecState* exec)
+bool LocalVarAccessNode::evaluateToBoolean(OldInterpreterExecState* exec)
{
return inlineEvaluate(exec)->toBoolean(exec);
}
-int32_t LocalVarAccessNode::evaluateToInt32(ExecState* exec)
+int32_t LocalVarAccessNode::evaluateToInt32(OldInterpreterExecState* exec)
{
return inlineEvaluate(exec)->toInt32(exec);
}
-uint32_t LocalVarAccessNode::evaluateToUInt32(ExecState* exec)
+uint32_t LocalVarAccessNode::evaluateToUInt32(OldInterpreterExecState* exec)
{
return inlineEvaluate(exec)->toUInt32(exec);
}
-static inline JSValue* getNonLocalSymbol(ExecState* exec, size_t index, size_t scopeDepth)
+static inline JSValue* getNonLocalSymbol(OldInterpreterExecState* exec, size_t, size_t scopeDepth)
{
const ScopeChain& chain = exec->scopeChain();
ScopeChainIterator iter = chain.begin();
for (size_t i = 0; i < scopeDepth; ++iter, ++i)
ASSERT(iter != chain.end());
+#ifndef NDEBUG
JSObject* scope = *iter;
+#endif
ASSERT(scope->isVariableObject());
- JSVariableObject* variableObject = static_cast<JSVariableObject*>(scope);
- return variableObject->localStorage()[index].value;
+ ASSERT_NOT_REACHED();
+ return 0;
}
-JSValue* ScopedVarAccessNode::inlineEvaluate(ExecState* exec)
+JSValue* ScopedVarAccessNode::inlineEvaluate(OldInterpreterExecState* exec)
{
return getNonLocalSymbol(exec, m_index, m_scopeDepth);
}
-JSValue* ScopedVarAccessNode::evaluate(ExecState* exec)
+JSValue* ScopedVarAccessNode::evaluate(OldInterpreterExecState* exec)
{
return inlineEvaluate(exec);
}
-double ScopedVarAccessNode::evaluateToNumber(ExecState* exec)
+double ScopedVarAccessNode::evaluateToNumber(OldInterpreterExecState* exec)
{
return inlineEvaluate(exec)->toNumber(exec);
}
-bool ScopedVarAccessNode::evaluateToBoolean(ExecState* exec)
+bool ScopedVarAccessNode::evaluateToBoolean(OldInterpreterExecState* exec)
{
return inlineEvaluate(exec)->toBoolean(exec);
}
-int32_t ScopedVarAccessNode::evaluateToInt32(ExecState* exec)
+int32_t ScopedVarAccessNode::evaluateToInt32(OldInterpreterExecState* exec)
{
return inlineEvaluate(exec)->toInt32(exec);
}
-uint32_t ScopedVarAccessNode::evaluateToUInt32(ExecState* exec)
+uint32_t ScopedVarAccessNode::evaluateToUInt32(OldInterpreterExecState* exec)
{
return inlineEvaluate(exec)->toUInt32(exec);
}
-JSValue* NonLocalVarAccessNode::inlineEvaluate(ExecState* exec)
+JSValue* NonLocalVarAccessNode::inlineEvaluate(OldInterpreterExecState* exec)
{
// Check for missed optimization opportunity.
ASSERT(!canSkipLookup(exec, m_ident));
@@ -745,34 +814,34 @@
return throwUndefinedVariableError(exec, m_ident);
}
-JSValue* NonLocalVarAccessNode::evaluate(ExecState* exec)
+JSValue* NonLocalVarAccessNode::evaluate(OldInterpreterExecState* exec)
{
return inlineEvaluate(exec);
}
-double NonLocalVarAccessNode::evaluateToNumber(ExecState* exec)
+double NonLocalVarAccessNode::evaluateToNumber(OldInterpreterExecState* exec)
{
return inlineEvaluate(exec)->toNumber(exec);
}
-bool NonLocalVarAccessNode::evaluateToBoolean(ExecState* exec)
+bool NonLocalVarAccessNode::evaluateToBoolean(OldInterpreterExecState* exec)
{
return inlineEvaluate(exec)->toBoolean(exec);
}
-int32_t NonLocalVarAccessNode::evaluateToInt32(ExecState* exec)
+int32_t NonLocalVarAccessNode::evaluateToInt32(OldInterpreterExecState* exec)
{
return inlineEvaluate(exec)->toInt32(exec);
}
-uint32_t NonLocalVarAccessNode::evaluateToUInt32(ExecState* exec)
+uint32_t NonLocalVarAccessNode::evaluateToUInt32(OldInterpreterExecState* exec)
{
return inlineEvaluate(exec)->toUInt32(exec);
}
// ------------------------------ ElementNode ----------------------------------
-void ElementNode::optimizeVariableAccess(ExecState*, const SymbolTable&, const LocalStorage&, NodeStack& nodeStack)
+void ElementNode::optimizeVariableAccess(OldInterpreterExecState*, const SymbolTable&, const LocalStorage&, NodeStack& nodeStack)
{
if (m_next)
nodeStack.append(m_next.get());
@@ -781,7 +850,7 @@
}
// ECMA 11.1.4
-JSValue* ElementNode::evaluate(ExecState* exec)
+JSValue* ElementNode::evaluate(OldInterpreterExecState* exec)
{
JSObject* array = exec->lexicalGlobalObject()->arrayConstructor()->construct(exec, exec->emptyList());
int length = 0;
@@ -796,14 +865,33 @@
// ------------------------------ ArrayNode ------------------------------------
-void ArrayNode::optimizeVariableAccess(ExecState*, const SymbolTable&, const LocalStorage&, NodeStack& nodeStack)
+
+RegisterID* ArrayNode::emitCode(CodeGenerator& generator, RegisterID* dst)
+{
+ RefPtr<RegisterID> newArray = generator.emitNewArray(generator.tempDestination(dst));
+ unsigned length = 0;
+
+ RegisterID* value;
+ for (ElementNode* n = m_element.get(); n; n = n->m_next.get()) {
+ value = generator.emitNode(n->m_node.get());
+ length += n->m_elision;
+ generator.emitPutByIndex(newArray.get(), length++, value);
+ }
+
+ value = generator.emitLoad(generator.newTemporary(), jsNumber(m_elision + length));
+ generator.emitPutById(newArray.get(), generator.propertyNames().length, value);
+
+ return generator.moveToDestinationIfNeeded(dst, newArray.get());
+}
+
+void ArrayNode::optimizeVariableAccess(OldInterpreterExecState*, const SymbolTable&, const LocalStorage&, NodeStack& nodeStack)
{
if (m_element)
nodeStack.append(m_element.get());
}
// ECMA 11.1.4
-JSValue* ArrayNode::evaluate(ExecState* exec)
+JSValue* ArrayNode::evaluate(OldInterpreterExecState* exec)
{
JSObject* array;
int length;
@@ -826,14 +914,22 @@
// ------------------------------ ObjectLiteralNode ----------------------------
-void ObjectLiteralNode::optimizeVariableAccess(ExecState*, const SymbolTable&, const LocalStorage&, NodeStack& nodeStack)
+RegisterID* ObjectLiteralNode::emitCode(CodeGenerator& generator, RegisterID* dst)
+{
+ if (m_list)
+ return generator.emitNode(dst, m_list.get());
+ else
+ return generator.emitNewObject(generator.finalDestination(dst));
+}
+
+void ObjectLiteralNode::optimizeVariableAccess(OldInterpreterExecState*, const SymbolTable&, const LocalStorage&, NodeStack& nodeStack)
{
if (m_list)
nodeStack.append(m_list.get());
}
// ECMA 11.1.5
-JSValue* ObjectLiteralNode::evaluate(ExecState* exec)
+JSValue* ObjectLiteralNode::evaluate(OldInterpreterExecState* exec)
{
if (m_list)
return m_list->evaluate(exec);
@@ -843,7 +939,37 @@
// ------------------------------ PropertyListNode -----------------------------
-void PropertyListNode::optimizeVariableAccess(ExecState*, const SymbolTable&, const LocalStorage&, NodeStack& nodeStack)
+RegisterID* PropertyListNode::emitCode(CodeGenerator& generator, RegisterID* dst)
+{
+ RefPtr<RegisterID> newObj = generator.tempDestination(dst);
+
+ generator.emitNewObject(newObj.get());
+
+ for (PropertyListNode* p = this; p; p = p->m_next.get()) {
+ RegisterID* value = generator.emitNode(p->m_node->m_assign.get());
+
+ switch (p->m_node->m_type) {
+ case PropertyNode::Constant: {
+ generator.emitPutById(newObj.get(), p->m_node->name(), value);
+ break;
+ }
+ case PropertyNode::Getter: {
+ generator.emitPutGetter(newObj.get(), p->m_node->name(), value);
+ break;
+ }
+ case PropertyNode::Setter: {
+ generator.emitPutSetter(newObj.get(), p->m_node->name(), value);
+ break;
+ }
+ default:
+ ASSERT_NOT_REACHED();
+ }
+ }
+
+ return generator.moveToDestinationIfNeeded(dst, newObj.get());
+}
+
+void PropertyListNode::optimizeVariableAccess(OldInterpreterExecState*, const SymbolTable&, const LocalStorage&, NodeStack& nodeStack)
{
if (m_next)
nodeStack.append(m_next.get());
@@ -851,7 +977,7 @@
}
// ECMA 11.1.5
-JSValue* PropertyListNode::evaluate(ExecState* exec)
+JSValue* PropertyListNode::evaluate(OldInterpreterExecState* exec)
{
JSObject* obj = exec->lexicalGlobalObject()->objectConstructor()->construct(exec, exec->emptyList());
@@ -879,13 +1005,13 @@
// ------------------------------ PropertyNode -----------------------------
-void PropertyNode::optimizeVariableAccess(ExecState*, const SymbolTable&, const LocalStorage&, NodeStack& nodeStack)
+void PropertyNode::optimizeVariableAccess(OldInterpreterExecState*, const SymbolTable&, const LocalStorage&, NodeStack& nodeStack)
{
nodeStack.append(m_assign.get());
}
// ECMA 11.1.5
-JSValue* PropertyNode::evaluate(ExecState*)
+JSValue* PropertyNode::evaluate(OldInterpreterExecState*)
{
ASSERT(false);
return jsNull();
@@ -893,14 +1019,22 @@
// ------------------------------ BracketAccessorNode --------------------------------
-void BracketAccessorNode::optimizeVariableAccess(ExecState*, const SymbolTable&, const LocalStorage&, NodeStack& nodeStack)
+RegisterID* BracketAccessorNode::emitCode(CodeGenerator& generator, RegisterID* dst)
+{
+ RefPtr<RegisterID> base = generator.emitNode(m_base.get());
+ RegisterID* property = generator.emitNode(m_subscript.get());
+
+ return generator.emitGetByVal(generator.finalDestination(dst), base.get(), property);
+}
+
+void BracketAccessorNode::optimizeVariableAccess(OldInterpreterExecState*, const SymbolTable&, const LocalStorage&, NodeStack& nodeStack)
{
nodeStack.append(m_subscript.get());
nodeStack.append(m_base.get());
}
// ECMA 11.2.1a
-JSValue* BracketAccessorNode::inlineEvaluate(ExecState* exec)
+JSValue* BracketAccessorNode::inlineEvaluate(OldInterpreterExecState* exec)
{
JSValue* v1 = m_base->evaluate(exec);
KJS_CHECKEXCEPTIONVALUE
@@ -913,33 +1047,33 @@
return o->get(exec, Identifier(v2->toString(exec)));
}
-JSValue* BracketAccessorNode::evaluate(ExecState* exec)
+JSValue* BracketAccessorNode::evaluate(OldInterpreterExecState* exec)
{
return inlineEvaluate(exec);
}
-double BracketAccessorNode::evaluateToNumber(ExecState* exec)
+double BracketAccessorNode::evaluateToNumber(OldInterpreterExecState* exec)
{
JSValue* v = inlineEvaluate(exec);
KJS_CHECKEXCEPTIONNUMBER
return v->toNumber(exec);
}
-bool BracketAccessorNode::evaluateToBoolean(ExecState* exec)
+bool BracketAccessorNode::evaluateToBoolean(OldInterpreterExecState* exec)
{
JSValue* v = inlineEvaluate(exec);
KJS_CHECKEXCEPTIONBOOLEAN
return v->toBoolean(exec);
}
-int32_t BracketAccessorNode::evaluateToInt32(ExecState* exec)
+int32_t BracketAccessorNode::evaluateToInt32(OldInterpreterExecState* exec)
{
JSValue* v = inlineEvaluate(exec);
KJS_CHECKEXCEPTIONNUMBER
return v->toInt32(exec);
}
-uint32_t BracketAccessorNode::evaluateToUInt32(ExecState* exec)
+uint32_t BracketAccessorNode::evaluateToUInt32(OldInterpreterExecState* exec)
{
JSValue* v = inlineEvaluate(exec);
KJS_CHECKEXCEPTIONNUMBER
@@ -948,46 +1082,52 @@
// ------------------------------ DotAccessorNode --------------------------------
-void DotAccessorNode::optimizeVariableAccess(ExecState*, const SymbolTable&, const LocalStorage&, NodeStack& nodeStack)
+RegisterID* DotAccessorNode::emitCode(CodeGenerator& generator, RegisterID* dst)
+{
+ RegisterID* base = generator.emitNode(m_base.get());
+ return generator.emitGetById(generator.finalDestination(dst), base, m_ident);
+}
+
+void DotAccessorNode::optimizeVariableAccess(OldInterpreterExecState*, const SymbolTable&, const LocalStorage&, NodeStack& nodeStack)
{
nodeStack.append(m_base.get());
}
// ECMA 11.2.1b
-JSValue* DotAccessorNode::inlineEvaluate(ExecState* exec)
+JSValue* DotAccessorNode::inlineEvaluate(OldInterpreterExecState* exec)
{
JSValue* v = m_base->evaluate(exec);
KJS_CHECKEXCEPTIONVALUE
return v->toObject(exec)->get(exec, m_ident);
}
-JSValue* DotAccessorNode::evaluate(ExecState* exec)
+JSValue* DotAccessorNode::evaluate(OldInterpreterExecState* exec)
{
return inlineEvaluate(exec);
}
-double DotAccessorNode::evaluateToNumber(ExecState* exec)
+double DotAccessorNode::evaluateToNumber(OldInterpreterExecState* exec)
{
JSValue* v = inlineEvaluate(exec);
KJS_CHECKEXCEPTIONNUMBER
return v->toNumber(exec);
}
-bool DotAccessorNode::evaluateToBoolean(ExecState* exec)
+bool DotAccessorNode::evaluateToBoolean(OldInterpreterExecState* exec)
{
JSValue* v = inlineEvaluate(exec);
KJS_CHECKEXCEPTIONBOOLEAN
return v->toBoolean(exec);
}
-int32_t DotAccessorNode::evaluateToInt32(ExecState* exec)
+int32_t DotAccessorNode::evaluateToInt32(OldInterpreterExecState* exec)
{
JSValue* v = inlineEvaluate(exec);
KJS_CHECKEXCEPTIONNUMBER
return v->toInt32(exec);
}
-uint32_t DotAccessorNode::evaluateToUInt32(ExecState* exec)
+uint32_t DotAccessorNode::evaluateToUInt32(OldInterpreterExecState* exec)
{
JSValue* v = inlineEvaluate(exec);
KJS_CHECKEXCEPTIONNUMBER
@@ -996,7 +1136,13 @@
// ------------------------------ ArgumentListNode -----------------------------
-void ArgumentListNode::optimizeVariableAccess(ExecState*, const SymbolTable&, const LocalStorage&, NodeStack& nodeStack)
+RegisterID* ArgumentListNode::emitCode(CodeGenerator& generator, RegisterID* dst)
+{
+ ASSERT(m_expr);
+ return generator.emitNode(dst, m_expr.get());
+}
+
+void ArgumentListNode::optimizeVariableAccess(OldInterpreterExecState*, const SymbolTable&, const LocalStorage&, NodeStack& nodeStack)
{
if (m_next)
nodeStack.append(m_next.get());
@@ -1005,7 +1151,7 @@
}
// ECMA 11.2.4
-void ArgumentListNode::evaluateList(ExecState* exec, List& list)
+void ArgumentListNode::evaluateList(OldInterpreterExecState* exec, List& list)
{
for (ArgumentListNode* n = this; n; n = n->m_next.get()) {
JSValue* v = n->m_expr->evaluate(exec);
@@ -1016,7 +1162,7 @@
// ------------------------------ ArgumentsNode --------------------------------
-void ArgumentsNode::optimizeVariableAccess(ExecState*, const SymbolTable&, const LocalStorage&, NodeStack& nodeStack)
+void ArgumentsNode::optimizeVariableAccess(OldInterpreterExecState*, const SymbolTable&, const LocalStorage&, NodeStack& nodeStack)
{
if (m_listNode)
nodeStack.append(m_listNode.get());
@@ -1024,7 +1170,13 @@
// ------------------------------ NewExprNode ----------------------------------
-void NewExprNode::optimizeVariableAccess(ExecState*, const SymbolTable&, const LocalStorage&, NodeStack& nodeStack)
+RegisterID* NewExprNode::emitCode(CodeGenerator& generator, RegisterID* dst)
+{
+ RefPtr<RegisterID> r0 = generator.emitNode(m_expr.get());
+ return generator.emitConstruct(generator.finalDestination(dst), r0.get(), m_args.get());
+}
+
+void NewExprNode::optimizeVariableAccess(OldInterpreterExecState*, const SymbolTable&, const LocalStorage&, NodeStack& nodeStack)
{
if (m_args)
nodeStack.append(m_args.get());
@@ -1033,7 +1185,7 @@
// ECMA 11.2.2
-JSValue* NewExprNode::inlineEvaluate(ExecState* exec)
+JSValue* NewExprNode::inlineEvaluate(OldInterpreterExecState* exec)
{
JSValue* v = m_expr->evaluate(exec);
KJS_CHECKEXCEPTIONVALUE
@@ -1047,40 +1199,40 @@
if (!v->isObject())
return throwError(exec, TypeError, "Value %s (result of expression %s) is not an object. Cannot be used with new.", v, m_expr.get());
- JSObject* constr = static_cast<JSObject*>(v);
- if (!constr->implementsConstruct())
+ ConstructData constructData;
+ if (v->getConstructData(constructData) == ConstructTypeNone)
return throwError(exec, TypeError, "Value %s (result of expression %s) is not a constructor. Cannot be used with new.", v, m_expr.get());
- return constr->construct(exec, argList);
+ return static_cast<JSObject*>(v)->construct(exec, argList);
}
-JSValue* NewExprNode::evaluate(ExecState* exec)
+JSValue* NewExprNode::evaluate(OldInterpreterExecState* exec)
{
return inlineEvaluate(exec);
}
-double NewExprNode::evaluateToNumber(ExecState* exec)
+double NewExprNode::evaluateToNumber(OldInterpreterExecState* exec)
{
JSValue* v = inlineEvaluate(exec);
KJS_CHECKEXCEPTIONNUMBER
return v->toNumber(exec);
}
-bool NewExprNode::evaluateToBoolean(ExecState* exec)
+bool NewExprNode::evaluateToBoolean(OldInterpreterExecState* exec)
{
JSValue* v = inlineEvaluate(exec);
KJS_CHECKEXCEPTIONBOOLEAN
return v->toBoolean(exec);
}
-int32_t NewExprNode::evaluateToInt32(ExecState* exec)
+int32_t NewExprNode::evaluateToInt32(OldInterpreterExecState* exec)
{
JSValue* v = inlineEvaluate(exec);
KJS_CHECKEXCEPTIONNUMBER
return v->toInt32(exec);
}
-uint32_t NewExprNode::evaluateToUInt32(ExecState* exec)
+uint32_t NewExprNode::evaluateToUInt32(OldInterpreterExecState* exec)
{
JSValue* v = inlineEvaluate(exec);
KJS_CHECKEXCEPTIONNUMBER
@@ -1088,7 +1240,7 @@
}
template <ExpressionNode::CallerType callerType, bool scopeDepthIsZero>
-inline JSValue* ExpressionNode::resolveAndCall(ExecState* exec, const Identifier& ident, ArgumentsNode* args, size_t scopeDepth)
+inline JSValue* ExpressionNode::resolveAndCall(OldInterpreterExecState* exec, const Identifier& ident, ArgumentsNode* args, size_t scopeDepth)
{
const ScopeChain& chain = exec->scopeChain();
ScopeChainIterator iter = chain.begin();
@@ -1124,8 +1276,7 @@
if (callerType == EvalOperator) {
if (base == exec->lexicalGlobalObject() && func == exec->lexicalGlobalObject()->evalFunction()) {
- exec->dynamicGlobalObject()->tearOffActivation(exec);
- return eval(exec, exec->scopeChain(), exec->variableObject(), exec->dynamicGlobalObject(), exec->thisValue(), argList);
+ ASSERT_NOT_REACHED();
}
}
@@ -1138,24 +1289,38 @@
return throwUndefinedVariableError(exec, ident);
}
-void EvalFunctionCallNode::optimizeVariableAccess(ExecState*, const SymbolTable&, const LocalStorage&, NodeStack& nodeStack)
+RegisterID* EvalFunctionCallNode::emitCode(CodeGenerator& generator, RegisterID* dst)
+{
+ RefPtr<RegisterID> base = generator.tempDestination(dst);
+ RegisterID* func = generator.newTemporary();
+ generator.emitResolveWithBase(base.get(), func, CommonIdentifiers::shared()->eval);
+ return generator.emitCallEval(generator.finalDestination(dst, base.get()), func, base.get(), m_args.get());
+}
+
+void EvalFunctionCallNode::optimizeVariableAccess(OldInterpreterExecState*, const SymbolTable&, const LocalStorage&, NodeStack& nodeStack)
{
nodeStack.append(m_args.get());
}
-JSValue* EvalFunctionCallNode::evaluate(ExecState* exec)
+JSValue* EvalFunctionCallNode::evaluate(OldInterpreterExecState* exec)
{
return resolveAndCall<EvalOperator, true>(exec, exec->propertyNames().eval, m_args.get());
}
-void FunctionCallValueNode::optimizeVariableAccess(ExecState*, const SymbolTable&, const LocalStorage&, NodeStack& nodeStack)
+RegisterID* FunctionCallValueNode::emitCode(CodeGenerator& generator, RegisterID* dst)
+{
+ RegisterID* r0 = generator.emitNode(m_expr.get());
+ return generator.emitCall(generator.finalDestination(dst), r0, 0, m_args.get());
+}
+
+void FunctionCallValueNode::optimizeVariableAccess(OldInterpreterExecState*, const SymbolTable&, const LocalStorage&, NodeStack& nodeStack)
{
nodeStack.append(m_args.get());
nodeStack.append(m_expr.get());
}
// ECMA 11.2.3
-JSValue* FunctionCallValueNode::evaluate(ExecState* exec)
+JSValue* FunctionCallValueNode::evaluate(OldInterpreterExecState* exec)
{
JSValue* v = m_expr->evaluate(exec);
KJS_CHECKEXCEPTIONVALUE
@@ -1178,12 +1343,30 @@
return func->call(exec, thisObj, argList);
}
-void FunctionCallResolveNode::optimizeVariableAccess(ExecState* exec, const SymbolTable& symbolTable, const LocalStorage&, NodeStack& nodeStack)
+RegisterID* FunctionCallResolveNode::emitCode(CodeGenerator& generator, RegisterID* dst)
+{
+ if (RegisterID* local = generator.registerForLocal(m_ident))
+ return generator.emitCall(generator.finalDestination(dst), local, 0, m_args.get());
+
+ int index = 0;
+ size_t depth = 0;
+ if (generator.findScopedProperty(m_ident, index, depth) && index != missingSymbolMarker()) {
+ RegisterID* func = generator.emitGetScopedVar(generator.newTemporary(), depth, index);
+ return generator.emitCall(generator.finalDestination(dst), func, 0, m_args.get());
+ }
+
+ RefPtr<RegisterID> base = generator.tempDestination(dst);
+ RegisterID* func = generator.newTemporary();
+ generator.emitResolveFunction(base.get(), func, m_ident);
+ return generator.emitCall(generator.finalDestination(dst, base.get()), func, base.get(), m_args.get());
+}
+
+void FunctionCallResolveNode::optimizeVariableAccess(OldInterpreterExecState* exec, const SymbolTable& symbolTable, const LocalStorage&, NodeStack& nodeStack)
{
nodeStack.append(m_args.get());
size_t depth = 0;
- size_t index = getSymbolTableEntry(exec, m_ident, symbolTable, depth);
+ int index = getSymbolTableEntry(exec, m_ident, symbolTable, depth);
if (index != missingSymbolMarker()) {
if (!depth)
new (this) LocalVarFunctionCallNode(index);
@@ -1199,7 +1382,7 @@
}
// ECMA 11.2.3
-JSValue* FunctionCallResolveNode::inlineEvaluate(ExecState* exec)
+JSValue* FunctionCallResolveNode::inlineEvaluate(OldInterpreterExecState* exec)
{
// Check for missed optimization opportunity.
ASSERT(!canSkipLookup(exec, m_ident));
@@ -1207,40 +1390,40 @@
return resolveAndCall<FunctionCall, true>(exec, m_ident, m_args.get());
}
-JSValue* FunctionCallResolveNode::evaluate(ExecState* exec)
+JSValue* FunctionCallResolveNode::evaluate(OldInterpreterExecState* exec)
{
return inlineEvaluate(exec);
}
-double FunctionCallResolveNode::evaluateToNumber(ExecState* exec)
+double FunctionCallResolveNode::evaluateToNumber(OldInterpreterExecState* exec)
{
JSValue* v = inlineEvaluate(exec);
KJS_CHECKEXCEPTIONNUMBER
return v->toNumber(exec);
}
-bool FunctionCallResolveNode::evaluateToBoolean(ExecState* exec)
+bool FunctionCallResolveNode::evaluateToBoolean(OldInterpreterExecState* exec)
{
JSValue* v = inlineEvaluate(exec);
KJS_CHECKEXCEPTIONBOOLEAN
return v->toBoolean(exec);
}
-int32_t FunctionCallResolveNode::evaluateToInt32(ExecState* exec)
+int32_t FunctionCallResolveNode::evaluateToInt32(OldInterpreterExecState* exec)
{
JSValue* v = inlineEvaluate(exec);
KJS_CHECKEXCEPTIONNUMBER
return v->toInt32(exec);
}
-uint32_t FunctionCallResolveNode::evaluateToUInt32(ExecState* exec)
+uint32_t FunctionCallResolveNode::evaluateToUInt32(OldInterpreterExecState* exec)
{
JSValue* v = inlineEvaluate(exec);
KJS_CHECKEXCEPTIONNUMBER
return v->toUInt32(exec);
}
-JSValue* LocalVarFunctionCallNode::inlineEvaluate(ExecState* exec)
+JSValue* LocalVarFunctionCallNode::inlineEvaluate(OldInterpreterExecState* exec)
{
ASSERT(exec->variableObject() == exec->scopeChain().top());
@@ -1261,40 +1444,40 @@
return func->call(exec, thisObj, argList);
}
-JSValue* LocalVarFunctionCallNode::evaluate(ExecState* exec)
+JSValue* LocalVarFunctionCallNode::evaluate(OldInterpreterExecState* exec)
{
return inlineEvaluate(exec);
}
-double LocalVarFunctionCallNode::evaluateToNumber(ExecState* exec)
+double LocalVarFunctionCallNode::evaluateToNumber(OldInterpreterExecState* exec)
{
JSValue* v = inlineEvaluate(exec);
KJS_CHECKEXCEPTIONNUMBER
return v->toNumber(exec);
}
-bool LocalVarFunctionCallNode::evaluateToBoolean(ExecState* exec)
+bool LocalVarFunctionCallNode::evaluateToBoolean(OldInterpreterExecState* exec)
{
JSValue* v = inlineEvaluate(exec);
KJS_CHECKEXCEPTIONBOOLEAN
return v->toBoolean(exec);
}
-int32_t LocalVarFunctionCallNode::evaluateToInt32(ExecState* exec)
+int32_t LocalVarFunctionCallNode::evaluateToInt32(OldInterpreterExecState* exec)
{
JSValue* v = inlineEvaluate(exec);
KJS_CHECKEXCEPTIONNUMBER
return v->toInt32(exec);
}
-uint32_t LocalVarFunctionCallNode::evaluateToUInt32(ExecState* exec)
+uint32_t LocalVarFunctionCallNode::evaluateToUInt32(OldInterpreterExecState* exec)
{
JSValue* v = inlineEvaluate(exec);
KJS_CHECKEXCEPTIONNUMBER
return v->toUInt32(exec);
}
-JSValue* ScopedVarFunctionCallNode::inlineEvaluate(ExecState* exec)
+JSValue* ScopedVarFunctionCallNode::inlineEvaluate(OldInterpreterExecState* exec)
{
ASSERT(exec->variableObject() == exec->scopeChain().top());
@@ -1315,40 +1498,40 @@
return func->call(exec, thisObj, argList);
}
-JSValue* ScopedVarFunctionCallNode::evaluate(ExecState* exec)
+JSValue* ScopedVarFunctionCallNode::evaluate(OldInterpreterExecState* exec)
{
return inlineEvaluate(exec);
}
-double ScopedVarFunctionCallNode::evaluateToNumber(ExecState* exec)
+double ScopedVarFunctionCallNode::evaluateToNumber(OldInterpreterExecState* exec)
{
JSValue* v = inlineEvaluate(exec);
KJS_CHECKEXCEPTIONNUMBER
return v->toNumber(exec);
}
-bool ScopedVarFunctionCallNode::evaluateToBoolean(ExecState* exec)
+bool ScopedVarFunctionCallNode::evaluateToBoolean(OldInterpreterExecState* exec)
{
JSValue* v = inlineEvaluate(exec);
KJS_CHECKEXCEPTIONBOOLEAN
return v->toBoolean(exec);
}
-int32_t ScopedVarFunctionCallNode::evaluateToInt32(ExecState* exec)
+int32_t ScopedVarFunctionCallNode::evaluateToInt32(OldInterpreterExecState* exec)
{
JSValue* v = inlineEvaluate(exec);
KJS_CHECKEXCEPTIONNUMBER
return v->toInt32(exec);
}
-uint32_t ScopedVarFunctionCallNode::evaluateToUInt32(ExecState* exec)
+uint32_t ScopedVarFunctionCallNode::evaluateToUInt32(OldInterpreterExecState* exec)
{
JSValue* v = inlineEvaluate(exec);
KJS_CHECKEXCEPTIONNUMBER
return v->toUInt32(exec);
}
-JSValue* NonLocalVarFunctionCallNode::inlineEvaluate(ExecState* exec)
+JSValue* NonLocalVarFunctionCallNode::inlineEvaluate(OldInterpreterExecState* exec)
{
// Check for missed optimization opportunity.
ASSERT(!canSkipLookup(exec, m_ident));
@@ -1356,40 +1539,48 @@
return resolveAndCall<FunctionCall, false>(exec, m_ident, m_args.get(), m_scopeDepth);
}
-JSValue* NonLocalVarFunctionCallNode::evaluate(ExecState* exec)
+JSValue* NonLocalVarFunctionCallNode::evaluate(OldInterpreterExecState* exec)
{
return inlineEvaluate(exec);
}
-double NonLocalVarFunctionCallNode::evaluateToNumber(ExecState* exec)
+double NonLocalVarFunctionCallNode::evaluateToNumber(OldInterpreterExecState* exec)
{
JSValue* v = inlineEvaluate(exec);
KJS_CHECKEXCEPTIONNUMBER
return v->toNumber(exec);
}
-bool NonLocalVarFunctionCallNode::evaluateToBoolean(ExecState* exec)
+bool NonLocalVarFunctionCallNode::evaluateToBoolean(OldInterpreterExecState* exec)
{
JSValue* v = inlineEvaluate(exec);
KJS_CHECKEXCEPTIONBOOLEAN
return v->toBoolean(exec);
}
-int32_t NonLocalVarFunctionCallNode::evaluateToInt32(ExecState* exec)
+int32_t NonLocalVarFunctionCallNode::evaluateToInt32(OldInterpreterExecState* exec)
{
JSValue* v = inlineEvaluate(exec);
KJS_CHECKEXCEPTIONNUMBER
return v->toInt32(exec);
}
-uint32_t NonLocalVarFunctionCallNode::evaluateToUInt32(ExecState* exec)
+uint32_t NonLocalVarFunctionCallNode::evaluateToUInt32(OldInterpreterExecState* exec)
{
JSValue* v = inlineEvaluate(exec);
KJS_CHECKEXCEPTIONNUMBER
return v->toUInt32(exec);
}
-void FunctionCallBracketNode::optimizeVariableAccess(ExecState*, const SymbolTable&, const LocalStorage&, NodeStack& nodeStack)
+RegisterID* FunctionCallBracketNode::emitCode(CodeGenerator& generator, RegisterID* dst)
+{
+ RefPtr<RegisterID> base = generator.emitNode(m_base.get());
+ RegisterID* property = generator.emitNode(m_subscript.get());
+ RegisterID* function = generator.emitGetByVal(generator.newTemporary(), base.get(), property);
+ return generator.emitCall(generator.finalDestination(dst, base.get()), function, base.get(), m_args.get());
+}
+
+void FunctionCallBracketNode::optimizeVariableAccess(OldInterpreterExecState*, const SymbolTable&, const LocalStorage&, NodeStack& nodeStack)
{
nodeStack.append(m_args.get());
nodeStack.append(m_subscript.get());
@@ -1397,7 +1588,7 @@
}
// ECMA 11.2.3
-JSValue* FunctionCallBracketNode::evaluate(ExecState* exec)
+JSValue* FunctionCallBracketNode::evaluate(OldInterpreterExecState* exec)
{
JSValue* baseVal = m_base->evaluate(exec);
KJS_CHECKEXCEPTIONVALUE
@@ -1457,14 +1648,21 @@
return "Object %s (result of expression %s.%s) does not allow calls.";
}
-void FunctionCallDotNode::optimizeVariableAccess(ExecState*, const SymbolTable&, const LocalStorage&, NodeStack& nodeStack)
+RegisterID* FunctionCallDotNode::emitCode(CodeGenerator& generator, RegisterID* dst)
+{
+ RefPtr<RegisterID> base = generator.emitNode(m_base.get());
+ RegisterID* function = generator.emitGetById(generator.newTemporary(), base.get(), m_ident);
+ return generator.emitCall(generator.finalDestination(dst, base.get()), function, base.get(), m_args.get());
+}
+
+void FunctionCallDotNode::optimizeVariableAccess(OldInterpreterExecState*, const SymbolTable&, const LocalStorage&, NodeStack& nodeStack)
{
nodeStack.append(m_args.get());
nodeStack.append(m_base.get());
}
// ECMA 11.2.3
-JSValue* FunctionCallDotNode::inlineEvaluate(ExecState* exec)
+JSValue* FunctionCallDotNode::inlineEvaluate(OldInterpreterExecState* exec)
{
JSValue* baseVal = m_base->evaluate(exec);
KJS_CHECKEXCEPTIONVALUE
@@ -1495,33 +1693,33 @@
return func->call(exec, thisObj, argList);
}
-JSValue* FunctionCallDotNode::evaluate(ExecState* exec)
+JSValue* FunctionCallDotNode::evaluate(OldInterpreterExecState* exec)
{
return inlineEvaluate(exec);
}
-double FunctionCallDotNode::evaluateToNumber(ExecState* exec)
+double FunctionCallDotNode::evaluateToNumber(OldInterpreterExecState* exec)
{
JSValue* v = inlineEvaluate(exec);
KJS_CHECKEXCEPTIONNUMBER
return v->toNumber(exec);
}
-bool FunctionCallDotNode::evaluateToBoolean(ExecState* exec)
+bool FunctionCallDotNode::evaluateToBoolean(OldInterpreterExecState* exec)
{
JSValue* v = inlineEvaluate(exec);
KJS_CHECKEXCEPTIONBOOLEAN
return v->toBoolean(exec);
}
-int32_t FunctionCallDotNode::evaluateToInt32(ExecState* exec)
+int32_t FunctionCallDotNode::evaluateToInt32(OldInterpreterExecState* exec)
{
JSValue* v = inlineEvaluate(exec);
KJS_CHECKEXCEPTIONNUMBER
return v->toInt32(exec);
}
-uint32_t FunctionCallDotNode::evaluateToUInt32(ExecState* exec)
+uint32_t FunctionCallDotNode::evaluateToUInt32(OldInterpreterExecState* exec)
{
JSValue* v = inlineEvaluate(exec);
KJS_CHECKEXCEPTIONNUMBER
@@ -1532,10 +1730,29 @@
// ------------------------------ PostfixResolveNode ----------------------------------
-// Increment
-void PostIncResolveNode::optimizeVariableAccess(ExecState*, const SymbolTable& symbolTable, const LocalStorage& localStorage, NodeStack&)
+RegisterID* PostIncResolveNode::emitCode(CodeGenerator& generator, RegisterID* dst)
{
- size_t index = symbolTable.get(m_ident.ustring().rep());
+ // FIXME: I think we can detect the absense of dependent expressions here,
+ // and emit a PreInc instead of a PostInc. A post-pass to eliminate dead
+ // code would work, too.
+ if (RegisterID* local = generator.registerForLocal(m_ident)) {
+ if (generator.isLocalConstant(m_ident))
+ return generator.emitToJSNumber(generator.finalDestination(dst), local);
+
+ return generator.emitPostInc(generator.finalDestination(dst), local);
+ }
+
+ RefPtr<RegisterID> value = generator.newTemporary();
+ RefPtr<RegisterID> base = generator.emitResolveWithBase(generator.newTemporary(), value.get(), m_ident);
+ RegisterID* oldValue = generator.emitPostInc(generator.finalDestination(dst), value.get());
+ generator.emitPutById(base.get(), m_ident, value.get());
+ return oldValue;
+}
+
+// Increment
+void PostIncResolveNode::optimizeVariableAccess(OldInterpreterExecState*, const SymbolTable& symbolTable, const LocalStorage& localStorage, NodeStack&)
+{
+ int index = symbolTable.get(m_ident.ustring().rep()).getIndex();
if (index != missingSymbolMarker()) {
if (isConstant(localStorage, index))
new (this) PostIncConstNode(index);
@@ -1544,7 +1761,7 @@
}
}
-JSValue* PostIncResolveNode::evaluate(ExecState* exec)
+JSValue* PostIncResolveNode::evaluate(OldInterpreterExecState* exec)
{
// Check for missed optimization opportunity.
ASSERT(!canSkipLookup(exec, m_ident));
@@ -1581,7 +1798,7 @@
new (this) PreIncResolveNode(PlacementNewAdopt);
}
-JSValue* PostIncLocalVarNode::evaluate(ExecState* exec)
+JSValue* PostIncLocalVarNode::evaluate(OldInterpreterExecState* exec)
{
ASSERT(exec->variableObject() == exec->scopeChain().top());
@@ -1597,9 +1814,28 @@
}
// Decrement
-void PostDecResolveNode::optimizeVariableAccess(ExecState*, const SymbolTable& symbolTable, const LocalStorage& localStorage, NodeStack&)
+RegisterID* PostDecResolveNode::emitCode(CodeGenerator& generator, RegisterID* dst)
{
- size_t index = symbolTable.get(m_ident.ustring().rep());
+ // FIXME: I think we can detect the absense of dependent expressions here,
+ // and emit a PreDec instead of a PostDec. A post-pass to eliminate dead
+ // code would work, too.
+ if (RegisterID* local = generator.registerForLocal(m_ident)) {
+ if (generator.isLocalConstant(m_ident))
+ return generator.emitToJSNumber(generator.finalDestination(dst), local);
+
+ return generator.emitPostDec(generator.finalDestination(dst), local);
+ }
+
+ RefPtr<RegisterID> value = generator.newTemporary();
+ RefPtr<RegisterID> base = generator.emitResolveWithBase(generator.newTemporary(), value.get(), m_ident);
+ RegisterID* oldValue = generator.emitPostDec(generator.finalDestination(dst), value.get());
+ generator.emitPutById(base.get(), m_ident, value.get());
+ return oldValue;
+}
+
+void PostDecResolveNode::optimizeVariableAccess(OldInterpreterExecState*, const SymbolTable& symbolTable, const LocalStorage& localStorage, NodeStack&)
+{
+ int index = symbolTable.get(m_ident.ustring().rep()).getIndex();
if (index != missingSymbolMarker()) {
if (isConstant(localStorage, index))
new (this) PostDecConstNode(index);
@@ -1608,7 +1844,7 @@
}
}
-JSValue* PostDecResolveNode::evaluate(ExecState* exec)
+JSValue* PostDecResolveNode::evaluate(OldInterpreterExecState* exec)
{
// Check for missed optimization opportunity.
ASSERT(!canSkipLookup(exec, m_ident));
@@ -1642,7 +1878,7 @@
new (this) PreDecResolveNode(PlacementNewAdopt);
}
-JSValue* PostDecLocalVarNode::evaluate(ExecState* exec)
+JSValue* PostDecLocalVarNode::evaluate(OldInterpreterExecState* exec)
{
ASSERT(exec->variableObject() == exec->scopeChain().top());
@@ -1652,7 +1888,7 @@
return v;
}
-double PostDecLocalVarNode::inlineEvaluateToNumber(ExecState* exec)
+double PostDecLocalVarNode::inlineEvaluateToNumber(OldInterpreterExecState* exec)
{
ASSERT(exec->variableObject() == exec->scopeChain().top());
@@ -1662,23 +1898,23 @@
return n;
}
-double PostDecLocalVarNode::evaluateToNumber(ExecState* exec)
+double PostDecLocalVarNode::evaluateToNumber(OldInterpreterExecState* exec)
{
return inlineEvaluateToNumber(exec);
}
-bool PostDecLocalVarNode::evaluateToBoolean(ExecState* exec)
+bool PostDecLocalVarNode::evaluateToBoolean(OldInterpreterExecState* exec)
{
double result = inlineEvaluateToNumber(exec);
return result > 0.0 || 0.0 > result; // NaN produces false as well
}
-int32_t PostDecLocalVarNode::evaluateToInt32(ExecState* exec)
+int32_t PostDecLocalVarNode::evaluateToInt32(OldInterpreterExecState* exec)
{
return JSValue::toInt32(inlineEvaluateToNumber(exec));
}
-uint32_t PostDecLocalVarNode::evaluateToUInt32(ExecState* exec)
+uint32_t PostDecLocalVarNode::evaluateToUInt32(OldInterpreterExecState* exec)
{
return JSValue::toUInt32(inlineEvaluateToNumber(exec));
}
@@ -1690,13 +1926,23 @@
// ------------------------------ PostfixBracketNode ----------------------------------
-void PostfixBracketNode::optimizeVariableAccess(ExecState*, const SymbolTable&, const LocalStorage&, NodeStack& nodeStack)
+void PostfixBracketNode::optimizeVariableAccess(OldInterpreterExecState*, const SymbolTable&, const LocalStorage&, NodeStack& nodeStack)
{
nodeStack.append(m_subscript.get());
nodeStack.append(m_base.get());
}
-JSValue* PostIncBracketNode::evaluate(ExecState* exec)
+RegisterID* PostIncBracketNode::emitCode(CodeGenerator& generator, RegisterID* dst)
+{
+ RefPtr<RegisterID> base = generator.emitNode(m_base.get());
+ RefPtr<RegisterID> property = generator.emitNode(m_subscript.get());
+ RefPtr<RegisterID> value = generator.emitGetByVal(generator.newTemporary(), base.get(), property.get());
+ RegisterID* oldValue = generator.emitPostInc(generator.finalDestination(dst), value.get());
+ generator.emitPutByVal(base.get(), property.get(), value.get());
+ return oldValue;
+}
+
+JSValue* PostIncBracketNode::evaluate(OldInterpreterExecState* exec)
{
JSValue* baseValue = m_base->evaluate(exec);
KJS_CHECKEXCEPTIONVALUE
@@ -1727,7 +1973,17 @@
return v2;
}
-JSValue* PostDecBracketNode::evaluate(ExecState* exec)
+RegisterID* PostDecBracketNode::emitCode(CodeGenerator& generator, RegisterID* dst)
+{
+ RefPtr<RegisterID> base = generator.emitNode(m_base.get());
+ RefPtr<RegisterID> property = generator.emitNode(m_subscript.get());
+ RefPtr<RegisterID> value = generator.emitGetByVal(generator.newTemporary(), base.get(), property.get());
+ RegisterID* oldValue = generator.emitPostDec(generator.finalDestination(dst), value.get());
+ generator.emitPutByVal(base.get(), property.get(), value.get());
+ return oldValue;
+}
+
+JSValue* PostDecBracketNode::evaluate(OldInterpreterExecState* exec)
{
JSValue* baseValue = m_base->evaluate(exec);
KJS_CHECKEXCEPTIONVALUE
@@ -1759,12 +2015,21 @@
// ------------------------------ PostfixDotNode ----------------------------------
-void PostfixDotNode::optimizeVariableAccess(ExecState*, const SymbolTable&, const LocalStorage&, NodeStack& nodeStack)
+void PostfixDotNode::optimizeVariableAccess(OldInterpreterExecState*, const SymbolTable&, const LocalStorage&, NodeStack& nodeStack)
{
nodeStack.append(m_base.get());
}
-JSValue* PostIncDotNode::evaluate(ExecState* exec)
+RegisterID* PostIncDotNode::emitCode(CodeGenerator& generator, RegisterID* dst)
+{
+ RefPtr<RegisterID> base = generator.emitNode(m_base.get());
+ RefPtr<RegisterID> value = generator.emitGetById(generator.newTemporary(), base.get(), m_ident);
+ RegisterID* oldValue = generator.emitPostInc(generator.finalDestination(dst), value.get());
+ generator.emitPutById(base.get(), m_ident, value.get());
+ return oldValue;
+}
+
+JSValue* PostIncDotNode::evaluate(OldInterpreterExecState* exec)
{
JSValue* baseValue = m_base->evaluate(exec);
KJS_CHECKEXCEPTIONVALUE
@@ -1779,7 +2044,16 @@
return v2;
}
-JSValue* PostDecDotNode::evaluate(ExecState* exec)
+RegisterID* PostDecDotNode::emitCode(CodeGenerator& generator, RegisterID* dst)
+{
+ RefPtr<RegisterID> base = generator.emitNode(m_base.get());
+ RefPtr<RegisterID> value = generator.emitGetById(generator.newTemporary(), base.get(), m_ident);
+ RegisterID* oldValue = generator.emitPostDec(generator.finalDestination(dst), value.get());
+ generator.emitPutById(base.get(), m_ident, value.get());
+ return oldValue;
+}
+
+JSValue* PostDecDotNode::evaluate(OldInterpreterExecState* exec)
{
JSValue* baseValue = m_base->evaluate(exec);
KJS_CHECKEXCEPTIONVALUE
@@ -1796,7 +2070,12 @@
// ------------------------------ PostfixErrorNode -----------------------------------
-JSValue* PostfixErrorNode::evaluate(ExecState* exec)
+RegisterID* PostfixErrorNode::emitCode(CodeGenerator& generator, RegisterID*)
+{
+ return emitThrowError(generator, ReferenceError, m_operator == OpPlusPlus ? "Postfix ++ operator applied to value that is not a reference." : "Postfix -- operator applied to value that is not a reference.");
+}
+
+JSValue* PostfixErrorNode::evaluate(OldInterpreterExecState* exec)
{
throwError(exec, ReferenceError, "Postfix %s operator applied to value that is not a reference.",
m_operator == OpPlusPlus ? "++" : "--");
@@ -1806,16 +2085,25 @@
// ------------------------------ DeleteResolveNode -----------------------------------
-void DeleteResolveNode::optimizeVariableAccess(ExecState*, const SymbolTable& symbolTable, const LocalStorage&, NodeStack&)
+RegisterID* DeleteResolveNode::emitCode(CodeGenerator& generator, RegisterID* dst)
{
- size_t index = symbolTable.get(m_ident.ustring().rep());
+ if (generator.registerForLocal(m_ident))
+ return generator.emitLoad(generator.finalDestination(dst), false);
+
+ RegisterID* base = generator.emitResolveBase(generator.tempDestination(dst), m_ident);
+ return generator.emitDeleteById(generator.finalDestination(dst, base), base, m_ident);
+}
+
+void DeleteResolveNode::optimizeVariableAccess(OldInterpreterExecState*, const SymbolTable& symbolTable, const LocalStorage&, NodeStack&)
+{
+ int index = symbolTable.get(m_ident.ustring().rep()).getIndex();
if (index != missingSymbolMarker())
new (this) LocalVarDeleteNode();
}
// ECMA 11.4.1
-JSValue* DeleteResolveNode::evaluate(ExecState* exec)
+JSValue* DeleteResolveNode::evaluate(OldInterpreterExecState* exec)
{
// Check for missed optimization opportunity.
ASSERT(!canSkipLookup(exec, m_ident));
@@ -1840,20 +2128,27 @@
return jsBoolean(true);
}
-JSValue* LocalVarDeleteNode::evaluate(ExecState*)
+JSValue* LocalVarDeleteNode::evaluate(OldInterpreterExecState*)
{
return jsBoolean(false);
}
// ------------------------------ DeleteBracketNode -----------------------------------
-void DeleteBracketNode::optimizeVariableAccess(ExecState*, const SymbolTable&, const LocalStorage&, NodeStack& nodeStack)
+RegisterID* DeleteBracketNode::emitCode(CodeGenerator& generator, RegisterID* dst)
+{
+ RefPtr<RegisterID> r0 = generator.emitNode(m_base.get());
+ RefPtr<RegisterID> r1 = generator.emitNode(m_subscript.get());
+ return generator.emitDeleteByVal(generator.finalDestination(dst), r0.get(), r1.get());
+}
+
+void DeleteBracketNode::optimizeVariableAccess(OldInterpreterExecState*, const SymbolTable&, const LocalStorage&, NodeStack& nodeStack)
{
nodeStack.append(m_subscript.get());
nodeStack.append(m_base.get());
}
-JSValue* DeleteBracketNode::evaluate(ExecState* exec)
+JSValue* DeleteBracketNode::evaluate(OldInterpreterExecState* exec)
{
JSValue* baseValue = m_base->evaluate(exec);
KJS_CHECKEXCEPTIONVALUE
@@ -1872,12 +2167,18 @@
// ------------------------------ DeleteDotNode -----------------------------------
-void DeleteDotNode::optimizeVariableAccess(ExecState*, const SymbolTable&, const LocalStorage&, NodeStack& nodeStack)
+RegisterID* DeleteDotNode::emitCode(CodeGenerator& generator, RegisterID* dst)
+{
+ RegisterID* r0 = generator.emitNode(m_base.get());
+ return generator.emitDeleteById(generator.finalDestination(dst), r0, m_ident);
+}
+
+void DeleteDotNode::optimizeVariableAccess(OldInterpreterExecState*, const SymbolTable&, const LocalStorage&, NodeStack& nodeStack)
{
nodeStack.append(m_base.get());
}
-JSValue* DeleteDotNode::evaluate(ExecState* exec)
+JSValue* DeleteDotNode::evaluate(OldInterpreterExecState* exec)
{
JSValue* baseValue = m_base->evaluate(exec);
JSObject* base = baseValue->toObject(exec);
@@ -1888,12 +2189,20 @@
// ------------------------------ DeleteValueNode -----------------------------------
-void DeleteValueNode::optimizeVariableAccess(ExecState*, const SymbolTable&, const LocalStorage&, NodeStack& nodeStack)
+RegisterID* DeleteValueNode::emitCode(CodeGenerator& generator, RegisterID* dst)
+{
+ generator.emitNode(m_expr.get());
+
+ // delete on a non-location expression ignores the value and returns true
+ return generator.emitLoad(generator.finalDestination(dst), true);
+}
+
+void DeleteValueNode::optimizeVariableAccess(OldInterpreterExecState*, const SymbolTable&, const LocalStorage&, NodeStack& nodeStack)
{
nodeStack.append(m_expr.get());
}
-JSValue* DeleteValueNode::evaluate(ExecState* exec)
+JSValue* DeleteValueNode::evaluate(OldInterpreterExecState* exec)
{
m_expr->evaluate(exec);
KJS_CHECKEXCEPTIONVALUE
@@ -1904,13 +2213,19 @@
// ------------------------------ VoidNode -------------------------------------
-void VoidNode::optimizeVariableAccess(ExecState*, const SymbolTable&, const LocalStorage&, NodeStack& nodeStack)
+RegisterID* VoidNode::emitCode(CodeGenerator& generator, RegisterID* dst)
+{
+ RefPtr<RegisterID> r0 = generator.emitNode(m_expr.get());
+ return generator.emitLoad(generator.finalDestination(dst, r0.get()), jsUndefined());
+}
+
+void VoidNode::optimizeVariableAccess(OldInterpreterExecState*, const SymbolTable&, const LocalStorage&, NodeStack& nodeStack)
{
nodeStack.append(m_expr.get());
}
// ECMA 11.4.2
-JSValue* VoidNode::evaluate(ExecState* exec)
+JSValue* VoidNode::evaluate(OldInterpreterExecState* exec)
{
m_expr->evaluate(exec);
KJS_CHECKEXCEPTIONVALUE
@@ -1922,7 +2237,7 @@
// ------------------------------ TypeOfValueNode -----------------------------------
-void TypeOfValueNode::optimizeVariableAccess(ExecState*, const SymbolTable&, const LocalStorage&, NodeStack& nodeStack)
+void TypeOfValueNode::optimizeVariableAccess(OldInterpreterExecState*, const SymbolTable&, const LocalStorage&, NodeStack& nodeStack)
{
nodeStack.append(m_expr.get());
}
@@ -1955,21 +2270,31 @@
}
}
-void TypeOfResolveNode::optimizeVariableAccess(ExecState*, const SymbolTable& symbolTable, const LocalStorage&, NodeStack&)
+void TypeOfResolveNode::optimizeVariableAccess(OldInterpreterExecState*, const SymbolTable& symbolTable, const LocalStorage&, NodeStack&)
{
- size_t index = symbolTable.get(m_ident.ustring().rep());
+ int index = symbolTable.get(m_ident.ustring().rep()).getIndex();
if (index != missingSymbolMarker())
new (this) LocalVarTypeOfNode(index);
}
-JSValue* LocalVarTypeOfNode::evaluate(ExecState* exec)
+JSValue* LocalVarTypeOfNode::evaluate(OldInterpreterExecState* exec)
{
ASSERT(exec->variableObject() == exec->scopeChain().top());
return typeStringForValue(exec->localStorage()[m_index].value);
}
-JSValue* TypeOfResolveNode::evaluate(ExecState* exec)
+RegisterID* TypeOfResolveNode::emitCode(CodeGenerator& generator, RegisterID* dst)
+{
+ if (RegisterID* local = generator.registerForLocal(m_ident))
+ return generator.emitTypeOf(generator.finalDestination(dst), local);
+
+ RefPtr<RegisterID> scratch = generator.emitResolveBase(generator.tempDestination(dst), m_ident);
+ generator.emitGetById(scratch.get(), scratch.get(), m_ident);
+ return generator.emitTypeOf(generator.finalDestination(dst, scratch.get()), scratch.get());
+}
+
+JSValue* TypeOfResolveNode::evaluate(OldInterpreterExecState* exec)
{
const ScopeChain& chain = exec->scopeChain();
ScopeChainIterator iter = chain.begin();
@@ -1995,7 +2320,13 @@
// ------------------------------ TypeOfValueNode -----------------------------------
-JSValue* TypeOfValueNode::evaluate(ExecState* exec)
+RegisterID* TypeOfValueNode::emitCode(CodeGenerator& generator, RegisterID* dst)
+{
+ RefPtr<RegisterID> src = generator.emitNode(m_expr.get());
+ return generator.emitTypeOf(generator.finalDestination(dst), src.get());
+}
+
+JSValue* TypeOfValueNode::evaluate(OldInterpreterExecState* exec)
{
JSValue* v = m_expr->evaluate(exec);
KJS_CHECKEXCEPTIONVALUE
@@ -2007,9 +2338,28 @@
// ------------------------------ PrefixResolveNode ----------------------------------
-void PreIncResolveNode::optimizeVariableAccess(ExecState*, const SymbolTable& symbolTable, const LocalStorage& localStorage, NodeStack&)
+RegisterID* PreIncResolveNode::emitCode(CodeGenerator& generator, RegisterID* dst)
{
- size_t index = symbolTable.get(m_ident.ustring().rep());
+ if (RegisterID* local = generator.registerForLocal(m_ident)) {
+ if (generator.isLocalConstant(m_ident)) {
+ RefPtr<RegisterID> r0 = generator.emitLoad(generator.finalDestination(dst), 1.0);
+ return generator.emitAdd(r0.get(), local, r0.get());
+ }
+
+ generator.emitPreInc(local);
+ return generator.moveToDestinationIfNeeded(dst, local);
+ }
+
+ RefPtr<RegisterID> propDst = generator.tempDestination(dst);
+ RefPtr<RegisterID> base = generator.emitResolveWithBase(generator.newTemporary(), propDst.get(), m_ident);
+ generator.emitPreInc(propDst.get());
+ generator.emitPutById(base.get(), m_ident, propDst.get());
+ return generator.moveToDestinationIfNeeded(dst, propDst.get());
+}
+
+void PreIncResolveNode::optimizeVariableAccess(OldInterpreterExecState*, const SymbolTable& symbolTable, const LocalStorage& localStorage, NodeStack&)
+{
+ int index = symbolTable.get(m_ident.ustring().rep()).getIndex();
if (index != missingSymbolMarker()) {
if (isConstant(localStorage, index))
new (this) PreIncConstNode(index);
@@ -2018,7 +2368,7 @@
}
}
-JSValue* PreIncLocalVarNode::evaluate(ExecState* exec)
+JSValue* PreIncLocalVarNode::evaluate(OldInterpreterExecState* exec)
{
ASSERT(exec->variableObject() == exec->scopeChain().top());
JSValue** slot = &exec->localStorage()[m_index].value;
@@ -2029,7 +2379,7 @@
return n2;
}
-JSValue* PreIncResolveNode::evaluate(ExecState* exec)
+JSValue* PreIncResolveNode::evaluate(OldInterpreterExecState* exec)
{
const ScopeChain& chain = exec->scopeChain();
ScopeChainIterator iter = chain.begin();
@@ -2059,9 +2409,28 @@
return throwUndefinedVariableError(exec, m_ident);
}
-void PreDecResolveNode::optimizeVariableAccess(ExecState*, const SymbolTable& symbolTable, const LocalStorage& localStorage, NodeStack&)
+RegisterID* PreDecResolveNode::emitCode(CodeGenerator& generator, RegisterID* dst)
{
- size_t index = symbolTable.get(m_ident.ustring().rep());
+ if (RegisterID* local = generator.registerForLocal(m_ident)) {
+ if (generator.isLocalConstant(m_ident)) {
+ RefPtr<RegisterID> r0 = generator.emitLoad(generator.finalDestination(dst), -1.0);
+ return generator.emitAdd(r0.get(), local, r0.get());
+ }
+
+ generator.emitPreDec(local);
+ return generator.moveToDestinationIfNeeded(dst, local);
+ }
+
+ RefPtr<RegisterID> propDst = generator.tempDestination(dst);
+ RefPtr<RegisterID> base = generator.emitResolveWithBase(generator.newTemporary(), propDst.get(), m_ident);
+ generator.emitPreDec(propDst.get());
+ generator.emitPutById(base.get(), m_ident, propDst.get());
+ return generator.moveToDestinationIfNeeded(dst, propDst.get());
+}
+
+void PreDecResolveNode::optimizeVariableAccess(OldInterpreterExecState*, const SymbolTable& symbolTable, const LocalStorage& localStorage, NodeStack&)
+{
+ int index = symbolTable.get(m_ident.ustring().rep()).getIndex();
if (index != missingSymbolMarker()) {
if (isConstant(localStorage, index))
new (this) PreDecConstNode(index);
@@ -2070,7 +2439,7 @@
}
}
-JSValue* PreDecLocalVarNode::evaluate(ExecState* exec)
+JSValue* PreDecLocalVarNode::evaluate(OldInterpreterExecState* exec)
{
ASSERT(exec->variableObject() == exec->scopeChain().top());
JSValue** slot = &exec->localStorage()[m_index].value;
@@ -2081,7 +2450,7 @@
return n2;
}
-JSValue* PreDecResolveNode::evaluate(ExecState* exec)
+JSValue* PreDecResolveNode::evaluate(OldInterpreterExecState* exec)
{
const ScopeChain& chain = exec->scopeChain();
ScopeChainIterator iter = chain.begin();
@@ -2113,7 +2482,7 @@
// ------------------------------ PreIncConstNode ----------------------------------
-JSValue* PreIncConstNode::evaluate(ExecState* exec)
+JSValue* PreIncConstNode::evaluate(OldInterpreterExecState* exec)
{
ASSERT(exec->variableObject() == exec->scopeChain().top());
return jsNumber(exec->localStorage()[m_index].value->toNumber(exec) + 1);
@@ -2121,7 +2490,7 @@
// ------------------------------ PreDecConstNode ----------------------------------
-JSValue* PreDecConstNode::evaluate(ExecState* exec)
+JSValue* PreDecConstNode::evaluate(OldInterpreterExecState* exec)
{
ASSERT(exec->variableObject() == exec->scopeChain().top());
return jsNumber(exec->localStorage()[m_index].value->toNumber(exec) - 1);
@@ -2129,7 +2498,7 @@
// ------------------------------ PostIncConstNode ----------------------------------
-JSValue* PostIncConstNode::evaluate(ExecState* exec)
+JSValue* PostIncConstNode::evaluate(OldInterpreterExecState* exec)
{
ASSERT(exec->variableObject() == exec->scopeChain().top());
return jsNumber(exec->localStorage()[m_index].value->toNumber(exec));
@@ -2137,7 +2506,7 @@
// ------------------------------ PostDecConstNode ----------------------------------
-JSValue* PostDecConstNode::evaluate(ExecState* exec)
+JSValue* PostDecConstNode::evaluate(OldInterpreterExecState* exec)
{
ASSERT(exec->variableObject() == exec->scopeChain().top());
return jsNumber(exec->localStorage()[m_index].value->toNumber(exec));
@@ -2145,13 +2514,24 @@
// ------------------------------ PrefixBracketNode ----------------------------------
-void PrefixBracketNode::optimizeVariableAccess(ExecState*, const SymbolTable&, const LocalStorage&, NodeStack& nodeStack)
+void PrefixBracketNode::optimizeVariableAccess(OldInterpreterExecState*, const SymbolTable&, const LocalStorage&, NodeStack& nodeStack)
{
nodeStack.append(m_subscript.get());
nodeStack.append(m_base.get());
}
-JSValue* PreIncBracketNode::evaluate(ExecState* exec)
+RegisterID* PreIncBracketNode::emitCode(CodeGenerator& generator, RegisterID* dst)
+{
+ RefPtr<RegisterID> base = generator.emitNode(m_base.get());
+ RefPtr<RegisterID> property = generator.emitNode(m_subscript.get());
+ RefPtr<RegisterID> propDst = generator.tempDestination(dst);
+ RegisterID* value = generator.emitGetByVal(propDst.get(), base.get(), property.get());
+ generator.emitPreInc(value);
+ generator.emitPutByVal(base.get(), property.get(), value);
+ return generator.moveToDestinationIfNeeded(dst, propDst.get());
+}
+
+JSValue* PreIncBracketNode::evaluate(OldInterpreterExecState* exec)
{
JSValue* baseValue = m_base->evaluate(exec);
KJS_CHECKEXCEPTIONVALUE
@@ -2183,7 +2563,19 @@
return n2;
}
-JSValue* PreDecBracketNode::evaluate(ExecState* exec)
+RegisterID* PreDecBracketNode::emitCode(CodeGenerator& generator, RegisterID* dst)
+{
+
+ RefPtr<RegisterID> base = generator.emitNode(m_base.get());
+ RefPtr<RegisterID> property = generator.emitNode(m_subscript.get());
+ RefPtr<RegisterID> propDst = generator.tempDestination(dst);
+ RegisterID* value = generator.emitGetByVal(propDst.get(), base.get(), property.get());
+ generator.emitPreDec(value);
+ generator.emitPutByVal(base.get(), property.get(), value);
+ return generator.moveToDestinationIfNeeded(dst, propDst.get());
+}
+
+JSValue* PreDecBracketNode::evaluate(OldInterpreterExecState* exec)
{
JSValue* baseValue = m_base->evaluate(exec);
KJS_CHECKEXCEPTIONVALUE
@@ -2217,12 +2609,22 @@
// ------------------------------ PrefixDotNode ----------------------------------
-void PrefixDotNode::optimizeVariableAccess(ExecState*, const SymbolTable&, const LocalStorage&, NodeStack& nodeStack)
+void PrefixDotNode::optimizeVariableAccess(OldInterpreterExecState*, const SymbolTable&, const LocalStorage&, NodeStack& nodeStack)
{
nodeStack.append(m_base.get());
}
-JSValue* PreIncDotNode::evaluate(ExecState* exec)
+RegisterID* PreIncDotNode::emitCode(CodeGenerator& generator, RegisterID* dst)
+{
+ RefPtr<RegisterID> base = generator.emitNode(m_base.get());
+ RefPtr<RegisterID> propDst = generator.tempDestination(dst);
+ RegisterID* value = generator.emitGetById(propDst.get(), base.get(), m_ident);
+ generator.emitPreInc(value);
+ generator.emitPutById(base.get(), m_ident, value);
+ return generator.moveToDestinationIfNeeded(dst, propDst.get());
+}
+
+JSValue* PreIncDotNode::evaluate(OldInterpreterExecState* exec)
{
JSValue* baseValue = m_base->evaluate(exec);
KJS_CHECKEXCEPTIONVALUE
@@ -2239,7 +2641,17 @@
return n2;
}
-JSValue* PreDecDotNode::evaluate(ExecState* exec)
+RegisterID* PreDecDotNode::emitCode(CodeGenerator& generator, RegisterID* dst)
+{
+ RefPtr<RegisterID> base = generator.emitNode(m_base.get());
+ RefPtr<RegisterID> propDst = generator.tempDestination(dst);
+ RegisterID* value = generator.emitGetById(propDst.get(), base.get(), m_ident);
+ generator.emitPreDec(value);
+ generator.emitPutById(base.get(), m_ident, value);
+ return generator.moveToDestinationIfNeeded(dst, propDst.get());
+}
+
+JSValue* PreDecDotNode::evaluate(OldInterpreterExecState* exec)
{
JSValue* baseValue = m_base->evaluate(exec);
KJS_CHECKEXCEPTIONVALUE
@@ -2258,7 +2670,12 @@
// ------------------------------ PrefixErrorNode -----------------------------------
-JSValue* PrefixErrorNode::evaluate(ExecState* exec)
+RegisterID* PrefixErrorNode::emitCode(CodeGenerator& generator, RegisterID*)
+{
+ return emitThrowError(generator, ReferenceError, m_operator == OpPlusPlus ? "Prefix ++ operator applied to value that is not a reference." : "Prefix -- operator applied to value that is not a reference.");
+}
+
+JSValue* PrefixErrorNode::evaluate(OldInterpreterExecState* exec)
{
throwError(exec, ReferenceError, "Prefix %s operator applied to value that is not a reference.",
m_operator == OpPlusPlus ? "++" : "--");
@@ -2268,54 +2685,66 @@
// ------------------------------ UnaryPlusNode --------------------------------
-void UnaryPlusNode::optimizeVariableAccess(ExecState*, const SymbolTable&, const LocalStorage&, NodeStack& nodeStack)
+RegisterID* UnaryPlusNode::emitCode(CodeGenerator& generator, RegisterID* dst)
+{
+ RegisterID* src = generator.emitNode(m_expr.get());
+ return generator.emitToJSNumber(generator.finalDestination(dst), src);
+}
+
+void UnaryPlusNode::optimizeVariableAccess(OldInterpreterExecState*, const SymbolTable&, const LocalStorage&, NodeStack& nodeStack)
{
nodeStack.append(m_expr.get());
}
// ECMA 11.4.6
-JSValue* UnaryPlusNode::evaluate(ExecState* exec)
+JSValue* UnaryPlusNode::evaluate(OldInterpreterExecState* exec)
{
JSValue* v = m_expr->evaluate(exec);
KJS_CHECKEXCEPTIONVALUE
return v->toJSNumber(exec);
}
-bool UnaryPlusNode::evaluateToBoolean(ExecState* exec)
+bool UnaryPlusNode::evaluateToBoolean(OldInterpreterExecState* exec)
{
return m_expr->evaluateToBoolean(exec);
}
-double UnaryPlusNode::evaluateToNumber(ExecState* exec)
+double UnaryPlusNode::evaluateToNumber(OldInterpreterExecState* exec)
{
return m_expr->evaluateToNumber(exec);
}
-int32_t UnaryPlusNode::evaluateToInt32(ExecState* exec)
+int32_t UnaryPlusNode::evaluateToInt32(OldInterpreterExecState* exec)
{
return m_expr->evaluateToInt32(exec);
}
-uint32_t UnaryPlusNode::evaluateToUInt32(ExecState* exec)
+uint32_t UnaryPlusNode::evaluateToUInt32(OldInterpreterExecState* exec)
{
return m_expr->evaluateToInt32(exec);
}
// ------------------------------ NegateNode -----------------------------------
-void NegateNode::optimizeVariableAccess(ExecState*, const SymbolTable&, const LocalStorage&, NodeStack& nodeStack)
+RegisterID* NegateNode::emitCode(CodeGenerator& generator, RegisterID* dst)
+{
+ RegisterID* src = generator.emitNode(m_expr.get());
+ return generator.emitNegate(generator.finalDestination(dst), src);
+}
+
+void NegateNode::optimizeVariableAccess(OldInterpreterExecState*, const SymbolTable&, const LocalStorage&, NodeStack& nodeStack)
{
nodeStack.append(m_expr.get());
}
// ECMA 11.4.7
-JSValue* NegateNode::evaluate(ExecState* exec)
+JSValue* NegateNode::evaluate(OldInterpreterExecState* exec)
{
// No need to check exception, caller will do so right after evaluate()
return jsNumber(-m_expr->evaluateToNumber(exec));
}
-double NegateNode::evaluateToNumber(ExecState* exec)
+double NegateNode::evaluateToNumber(OldInterpreterExecState* exec)
{
// No need to check exception, caller will do so right after evaluateToNumber()
return -m_expr->evaluateToNumber(exec);
@@ -2323,70 +2752,89 @@
// ------------------------------ BitwiseNotNode -------------------------------
-void BitwiseNotNode::optimizeVariableAccess(ExecState*, const SymbolTable&, const LocalStorage&, NodeStack& nodeStack)
+RegisterID* BitwiseNotNode::emitCode(CodeGenerator& generator, RegisterID* dst)
+{
+ RegisterID* src = generator.emitNode(m_expr.get());
+ return generator.emitBitNot(generator.finalDestination(dst), src);
+}
+
+void BitwiseNotNode::optimizeVariableAccess(OldInterpreterExecState*, const SymbolTable&, const LocalStorage&, NodeStack& nodeStack)
{
nodeStack.append(m_expr.get());
}
// ECMA 11.4.8
-int32_t BitwiseNotNode::inlineEvaluateToInt32(ExecState* exec)
+int32_t BitwiseNotNode::inlineEvaluateToInt32(OldInterpreterExecState* exec)
{
return ~m_expr->evaluateToInt32(exec);
}
-JSValue* BitwiseNotNode::evaluate(ExecState* exec)
+JSValue* BitwiseNotNode::evaluate(OldInterpreterExecState* exec)
{
return jsNumber(inlineEvaluateToInt32(exec));
}
-double BitwiseNotNode::evaluateToNumber(ExecState* exec)
+double BitwiseNotNode::evaluateToNumber(OldInterpreterExecState* exec)
{
return inlineEvaluateToInt32(exec);
}
-bool BitwiseNotNode::evaluateToBoolean(ExecState* exec)
+bool BitwiseNotNode::evaluateToBoolean(OldInterpreterExecState* exec)
{
return inlineEvaluateToInt32(exec);
}
-int32_t BitwiseNotNode::evaluateToInt32(ExecState* exec)
+int32_t BitwiseNotNode::evaluateToInt32(OldInterpreterExecState* exec)
{
return inlineEvaluateToInt32(exec);
}
-uint32_t BitwiseNotNode::evaluateToUInt32(ExecState* exec)
+uint32_t BitwiseNotNode::evaluateToUInt32(OldInterpreterExecState* exec)
{
return inlineEvaluateToInt32(exec);
}
// ------------------------------ LogicalNotNode -------------------------------
-void LogicalNotNode::optimizeVariableAccess(ExecState*, const SymbolTable&, const LocalStorage&, NodeStack& nodeStack)
+RegisterID* LogicalNotNode::emitCode(CodeGenerator& generator, RegisterID* dst)
+{
+ RegisterID* src = generator.emitNode(m_expr.get());
+ return generator.emitNot(generator.finalDestination(dst), src);
+}
+
+void LogicalNotNode::optimizeVariableAccess(OldInterpreterExecState*, const SymbolTable&, const LocalStorage&, NodeStack& nodeStack)
{
nodeStack.append(m_expr.get());
}
// ECMA 11.4.9
-JSValue* LogicalNotNode::evaluate(ExecState* exec)
+JSValue* LogicalNotNode::evaluate(OldInterpreterExecState* exec)
{
return jsBoolean(!m_expr->evaluateToBoolean(exec));
}
-bool LogicalNotNode::evaluateToBoolean(ExecState* exec)
+bool LogicalNotNode::evaluateToBoolean(OldInterpreterExecState* exec)
{
return !m_expr->evaluateToBoolean(exec);
}
// ------------------------------ Multiplicative Nodes -----------------------------------
-void MultNode::optimizeVariableAccess(ExecState*, const SymbolTable&, const LocalStorage&, NodeStack& nodeStack)
+RegisterID* MultNode::emitCode(CodeGenerator& generator, RegisterID* dst)
+{
+ RefPtr<RegisterID> src1 = generator.emitNode(m_term1.get());
+ RegisterID* src2 = generator.emitNode(m_term2.get());
+ return generator.emitMul(generator.finalDestination(dst, src1.get()), src1.get(), src2);
+}
+
+void MultNode::optimizeVariableAccess(OldInterpreterExecState*, const SymbolTable&, const LocalStorage&, NodeStack& nodeStack)
{
nodeStack.append(m_term1.get());
nodeStack.append(m_term2.get());
}
// ECMA 11.5.1
-double MultNode::inlineEvaluateToNumber(ExecState* exec)
+double MultNode::inlineEvaluateToNumber(OldInterpreterExecState* exec)
{
double n1 = m_term1->evaluateToNumber(exec);
KJS_CHECKEXCEPTIONNUMBER
@@ -2394,40 +2842,47 @@
return n1 * n2;
}
-JSValue* MultNode::evaluate(ExecState* exec)
+JSValue* MultNode::evaluate(OldInterpreterExecState* exec)
{
return jsNumber(inlineEvaluateToNumber(exec));
}
-double MultNode::evaluateToNumber(ExecState* exec)
+double MultNode::evaluateToNumber(OldInterpreterExecState* exec)
{
return inlineEvaluateToNumber(exec);
}
-bool MultNode::evaluateToBoolean(ExecState* exec)
+bool MultNode::evaluateToBoolean(OldInterpreterExecState* exec)
{
double result = inlineEvaluateToNumber(exec);
return result > 0.0 || 0.0 > result; // NaN produces false as well
}
-int32_t MultNode::evaluateToInt32(ExecState* exec)
+int32_t MultNode::evaluateToInt32(OldInterpreterExecState* exec)
{
return JSValue::toInt32(inlineEvaluateToNumber(exec));
}
-uint32_t MultNode::evaluateToUInt32(ExecState* exec)
+uint32_t MultNode::evaluateToUInt32(OldInterpreterExecState* exec)
{
return JSValue::toUInt32(inlineEvaluateToNumber(exec));
}
-void DivNode::optimizeVariableAccess(ExecState*, const SymbolTable&, const LocalStorage&, NodeStack& nodeStack)
+RegisterID* DivNode::emitCode(CodeGenerator& generator, RegisterID* dst)
+{
+ RefPtr<RegisterID> dividend = generator.emitNode(m_term1.get());
+ RegisterID* divisor = generator.emitNode(m_term2.get());
+ return generator.emitDiv(generator.finalDestination(dst, dividend.get()), dividend.get(), divisor);
+}
+
+void DivNode::optimizeVariableAccess(OldInterpreterExecState*, const SymbolTable&, const LocalStorage&, NodeStack& nodeStack)
{
nodeStack.append(m_term1.get());
nodeStack.append(m_term2.get());
}
// ECMA 11.5.2
-double DivNode::inlineEvaluateToNumber(ExecState* exec)
+double DivNode::inlineEvaluateToNumber(OldInterpreterExecState* exec)
{
double n1 = m_term1->evaluateToNumber(exec);
KJS_CHECKEXCEPTIONNUMBER
@@ -2435,34 +2890,41 @@
return n1 / n2;
}
-JSValue* DivNode::evaluate(ExecState* exec)
+JSValue* DivNode::evaluate(OldInterpreterExecState* exec)
{
return jsNumber(inlineEvaluateToNumber(exec));
}
-double DivNode::evaluateToNumber(ExecState* exec)
+double DivNode::evaluateToNumber(OldInterpreterExecState* exec)
{
return inlineEvaluateToNumber(exec);
}
-int32_t DivNode::evaluateToInt32(ExecState* exec)
+int32_t DivNode::evaluateToInt32(OldInterpreterExecState* exec)
{
return JSValue::toInt32(inlineEvaluateToNumber(exec));
}
-uint32_t DivNode::evaluateToUInt32(ExecState* exec)
+uint32_t DivNode::evaluateToUInt32(OldInterpreterExecState* exec)
{
return JSValue::toUInt32(inlineEvaluateToNumber(exec));
}
-void ModNode::optimizeVariableAccess(ExecState*, const SymbolTable&, const LocalStorage&, NodeStack& nodeStack)
+RegisterID* ModNode::emitCode(CodeGenerator& generator, RegisterID* dst)
+{
+ RefPtr<RegisterID> dividend = generator.emitNode(m_term1.get());
+ RegisterID* divisor = generator.emitNode(m_term2.get());
+ return generator.emitMod(generator.finalDestination(dst, dividend.get()), dividend.get(), divisor);
+}
+
+void ModNode::optimizeVariableAccess(OldInterpreterExecState*, const SymbolTable&, const LocalStorage&, NodeStack& nodeStack)
{
nodeStack.append(m_term1.get());
nodeStack.append(m_term2.get());
}
// ECMA 11.5.3
-double ModNode::inlineEvaluateToNumber(ExecState* exec)
+double ModNode::inlineEvaluateToNumber(OldInterpreterExecState* exec)
{
double n1 = m_term1->evaluateToNumber(exec);
KJS_CHECKEXCEPTIONNUMBER
@@ -2470,42 +2932,35 @@
return fmod(n1, n2);
}
-JSValue* ModNode::evaluate(ExecState* exec)
+JSValue* ModNode::evaluate(OldInterpreterExecState* exec)
{
return jsNumber(inlineEvaluateToNumber(exec));
}
-double ModNode::evaluateToNumber(ExecState* exec)
+double ModNode::evaluateToNumber(OldInterpreterExecState* exec)
{
return inlineEvaluateToNumber(exec);
}
-bool ModNode::evaluateToBoolean(ExecState* exec)
+bool ModNode::evaluateToBoolean(OldInterpreterExecState* exec)
{
double result = inlineEvaluateToNumber(exec);
return result > 0.0 || 0.0 > result; // NaN produces false as well
}
-int32_t ModNode::evaluateToInt32(ExecState* exec)
+int32_t ModNode::evaluateToInt32(OldInterpreterExecState* exec)
{
return JSValue::toInt32(inlineEvaluateToNumber(exec));
}
-uint32_t ModNode::evaluateToUInt32(ExecState* exec)
+uint32_t ModNode::evaluateToUInt32(OldInterpreterExecState* exec)
{
return JSValue::toUInt32(inlineEvaluateToNumber(exec));
}
// ------------------------------ Additive Nodes --------------------------------------
-static JSValue* throwOutOfMemoryError(ExecState* exec)
-{
- JSObject* error = Error::create(exec, GeneralError, "Out of memory");
- exec->setException(error);
- return error;
-}
-
-static double throwOutOfMemoryErrorToNumber(ExecState* exec)
+static double throwOutOfMemoryErrorToNumber(OldInterpreterExecState* exec)
{
JSObject* error = Error::create(exec, GeneralError, "Out of memory");
exec->setException(error);
@@ -2513,7 +2968,7 @@
}
// ECMA 11.6
-static JSValue* addSlowCase(ExecState* exec, JSValue* v1, JSValue* v2)
+static JSValue* addSlowCase(OldInterpreterExecState* exec, JSValue* v1, JSValue* v2)
{
// exception for the Date exception in defaultValue()
JSValue* p1 = v1->toPrimitive(exec, UnspecifiedType);
@@ -2529,7 +2984,7 @@
return jsNumber(p1->toNumber(exec) + p2->toNumber(exec));
}
-static double addSlowCaseToNumber(ExecState* exec, JSValue* v1, JSValue* v2)
+static double addSlowCaseToNumber(OldInterpreterExecState* exec, JSValue* v1, JSValue* v2)
{
// exception for the Date exception in defaultValue()
JSValue* p1 = v1->toPrimitive(exec, UnspecifiedType);
@@ -2555,7 +3010,7 @@
// 4000 Add case: 1 5
// 1 Add case: 3 5
-static inline JSValue* add(ExecState* exec, JSValue* v1, JSValue* v2)
+static inline JSValue* add(OldInterpreterExecState* exec, JSValue* v1, JSValue* v2)
{
JSType t1 = v1->type();
JSType t2 = v2->type();
@@ -2574,7 +3029,7 @@
return addSlowCase(exec, v1, v2);
}
-static inline double addToNumber(ExecState* exec, JSValue* v1, JSValue* v2)
+static inline double addToNumber(OldInterpreterExecState* exec, JSValue* v1, JSValue* v2)
{
JSType t1 = v1->type();
JSType t2 = v2->type();
@@ -2593,14 +3048,21 @@
return addSlowCaseToNumber(exec, v1, v2);
}
-void AddNode::optimizeVariableAccess(ExecState*, const SymbolTable&, const LocalStorage&, NodeStack& nodeStack)
+RegisterID* AddNode::emitCode(CodeGenerator& generator, RegisterID* dst)
+{
+ RefPtr<RegisterID> src1 = generator.emitNode(m_term1.get());
+ RegisterID* src2 = generator.emitNode(m_term2.get());
+ return generator.emitAdd(generator.finalDestination(dst, src1.get()), src1.get(), src2);
+}
+
+void AddNode::optimizeVariableAccess(OldInterpreterExecState*, const SymbolTable&, const LocalStorage&, NodeStack& nodeStack)
{
nodeStack.append(m_term1.get());
nodeStack.append(m_term2.get());
}
// ECMA 11.6.1
-JSValue* AddNode::evaluate(ExecState* exec)
+JSValue* AddNode::evaluate(OldInterpreterExecState* exec)
{
JSValue* v1 = m_term1->evaluate(exec);
KJS_CHECKEXCEPTIONVALUE
@@ -2611,7 +3073,7 @@
return add(exec, v1, v2);
}
-double AddNode::inlineEvaluateToNumber(ExecState* exec)
+double AddNode::inlineEvaluateToNumber(OldInterpreterExecState* exec)
{
JSValue* v1 = m_term1->evaluate(exec);
KJS_CHECKEXCEPTIONNUMBER
@@ -2622,22 +3084,22 @@
return addToNumber(exec, v1, v2);
}
-double AddNode::evaluateToNumber(ExecState* exec)
+double AddNode::evaluateToNumber(OldInterpreterExecState* exec)
{
return inlineEvaluateToNumber(exec);
}
-int32_t AddNode::evaluateToInt32(ExecState* exec)
+int32_t AddNode::evaluateToInt32(OldInterpreterExecState* exec)
{
return JSValue::toInt32(inlineEvaluateToNumber(exec));
}
-uint32_t AddNode::evaluateToUInt32(ExecState* exec)
+uint32_t AddNode::evaluateToUInt32(OldInterpreterExecState* exec)
{
return JSValue::toUInt32(inlineEvaluateToNumber(exec));
}
-double AddNumbersNode::inlineEvaluateToNumber(ExecState* exec)
+double AddNumbersNode::inlineEvaluateToNumber(OldInterpreterExecState* exec)
{
double n1 = m_term1->evaluateToNumber(exec);
KJS_CHECKEXCEPTIONNUMBER
@@ -2645,27 +3107,27 @@
return n1 + n2;
}
-JSValue* AddNumbersNode::evaluate(ExecState* exec)
+JSValue* AddNumbersNode::evaluate(OldInterpreterExecState* exec)
{
return jsNumber(inlineEvaluateToNumber(exec));
}
-double AddNumbersNode::evaluateToNumber(ExecState* exec)
+double AddNumbersNode::evaluateToNumber(OldInterpreterExecState* exec)
{
return inlineEvaluateToNumber(exec);
}
-int32_t AddNumbersNode::evaluateToInt32(ExecState* exec)
+int32_t AddNumbersNode::evaluateToInt32(OldInterpreterExecState* exec)
{
return JSValue::toInt32(inlineEvaluateToNumber(exec));
}
-uint32_t AddNumbersNode::evaluateToUInt32(ExecState* exec)
+uint32_t AddNumbersNode::evaluateToUInt32(OldInterpreterExecState* exec)
{
return JSValue::toUInt32(inlineEvaluateToNumber(exec));
}
-JSValue* AddStringsNode::evaluate(ExecState* exec)
+JSValue* AddStringsNode::evaluate(OldInterpreterExecState* exec)
{
JSValue* v1 = m_term1->evaluate(exec);
KJS_CHECKEXCEPTIONVALUE
@@ -2676,7 +3138,7 @@
return jsString(static_cast<StringImp*>(v1)->value() + static_cast<StringImp*>(v2)->value());
}
-JSValue* AddStringLeftNode::evaluate(ExecState* exec)
+JSValue* AddStringLeftNode::evaluate(OldInterpreterExecState* exec)
{
JSValue* v1 = m_term1->evaluate(exec);
KJS_CHECKEXCEPTIONVALUE
@@ -2688,7 +3150,7 @@
return jsString(static_cast<StringImp*>(v1)->value() + p2->toString(exec));
}
-JSValue* AddStringRightNode::evaluate(ExecState* exec)
+JSValue* AddStringRightNode::evaluate(OldInterpreterExecState* exec)
{
JSValue* v1 = m_term1->evaluate(exec);
KJS_CHECKEXCEPTIONVALUE
@@ -2700,14 +3162,21 @@
return jsString(p1->toString(exec) + static_cast<StringImp*>(v2)->value());
}
-void SubNode::optimizeVariableAccess(ExecState*, const SymbolTable&, const LocalStorage&, NodeStack& nodeStack)
+RegisterID* SubNode::emitCode(CodeGenerator& generator, RegisterID* dst)
+{
+ RefPtr<RegisterID> src1 = generator.emitNode(m_term1.get());
+ RegisterID* src2 = generator.emitNode(m_term2.get());
+ return generator.emitSub(generator.finalDestination(dst, src1.get()), src1.get(), src2);
+}
+
+void SubNode::optimizeVariableAccess(OldInterpreterExecState*, const SymbolTable&, const LocalStorage&, NodeStack& nodeStack)
{
nodeStack.append(m_term1.get());
nodeStack.append(m_term2.get());
}
// ECMA 11.6.2
-double SubNode::inlineEvaluateToNumber(ExecState* exec)
+double SubNode::inlineEvaluateToNumber(OldInterpreterExecState* exec)
{
double n1 = m_term1->evaluateToNumber(exec);
KJS_CHECKEXCEPTIONNUMBER
@@ -2715,36 +3184,43 @@
return n1 - n2;
}
-JSValue* SubNode::evaluate(ExecState* exec)
+JSValue* SubNode::evaluate(OldInterpreterExecState* exec)
{
return jsNumber(inlineEvaluateToNumber(exec));
}
-double SubNode::evaluateToNumber(ExecState* exec)
+double SubNode::evaluateToNumber(OldInterpreterExecState* exec)
{
return inlineEvaluateToNumber(exec);
}
-int32_t SubNode::evaluateToInt32(ExecState* exec)
+int32_t SubNode::evaluateToInt32(OldInterpreterExecState* exec)
{
return JSValue::toInt32(inlineEvaluateToNumber(exec));
}
-uint32_t SubNode::evaluateToUInt32(ExecState* exec)
+uint32_t SubNode::evaluateToUInt32(OldInterpreterExecState* exec)
{
return JSValue::toUInt32(inlineEvaluateToNumber(exec));
}
// ------------------------------ Shift Nodes ------------------------------------
-void LeftShiftNode::optimizeVariableAccess(ExecState*, const SymbolTable&, const LocalStorage&, NodeStack& nodeStack)
+RegisterID* LeftShiftNode::emitCode(CodeGenerator& generator, RegisterID* dst)
+{
+ RefPtr<RegisterID> val = generator.emitNode(m_term1.get());
+ RegisterID* shift = generator.emitNode(m_term2.get());
+ return generator.emitLeftShift(generator.finalDestination(dst, val.get()), val.get(), shift);
+}
+
+void LeftShiftNode::optimizeVariableAccess(OldInterpreterExecState*, const SymbolTable&, const LocalStorage&, NodeStack& nodeStack)
{
nodeStack.append(m_term1.get());
nodeStack.append(m_term2.get());
}
// ECMA 11.7.1
-int32_t LeftShiftNode::inlineEvaluateToInt32(ExecState* exec)
+int32_t LeftShiftNode::inlineEvaluateToInt32(OldInterpreterExecState* exec)
{
int i1 = m_term1->evaluateToInt32(exec);
KJS_CHECKEXCEPTIONNUMBER
@@ -2752,34 +3228,41 @@
return (i1 << i2);
}
-JSValue* LeftShiftNode::evaluate(ExecState* exec)
+JSValue* LeftShiftNode::evaluate(OldInterpreterExecState* exec)
{
return jsNumber(inlineEvaluateToInt32(exec));
}
-double LeftShiftNode::evaluateToNumber(ExecState* exec)
+double LeftShiftNode::evaluateToNumber(OldInterpreterExecState* exec)
{
return inlineEvaluateToInt32(exec);
}
-int32_t LeftShiftNode::evaluateToInt32(ExecState* exec)
+int32_t LeftShiftNode::evaluateToInt32(OldInterpreterExecState* exec)
{
return inlineEvaluateToInt32(exec);
}
-uint32_t LeftShiftNode::evaluateToUInt32(ExecState* exec)
+uint32_t LeftShiftNode::evaluateToUInt32(OldInterpreterExecState* exec)
{
return inlineEvaluateToInt32(exec);
}
-void RightShiftNode::optimizeVariableAccess(ExecState*, const SymbolTable&, const LocalStorage&, NodeStack& nodeStack)
+RegisterID* RightShiftNode::emitCode(CodeGenerator& generator, RegisterID* dst)
+{
+ RefPtr<RegisterID> val = generator.emitNode(m_term1.get());
+ RegisterID* shift = generator.emitNode(m_term2.get());
+ return generator.emitRightShift(generator.finalDestination(dst, val.get()), val.get(), shift);
+}
+
+void RightShiftNode::optimizeVariableAccess(OldInterpreterExecState*, const SymbolTable&, const LocalStorage&, NodeStack& nodeStack)
{
nodeStack.append(m_term1.get());
nodeStack.append(m_term2.get());
}
// ECMA 11.7.2
-int32_t RightShiftNode::inlineEvaluateToInt32(ExecState* exec)
+int32_t RightShiftNode::inlineEvaluateToInt32(OldInterpreterExecState* exec)
{
int i1 = m_term1->evaluateToInt32(exec);
KJS_CHECKEXCEPTIONNUMBER
@@ -2787,34 +3270,41 @@
return (i1 >> i2);
}
-JSValue* RightShiftNode::evaluate(ExecState* exec)
+JSValue* RightShiftNode::evaluate(OldInterpreterExecState* exec)
{
return jsNumber(inlineEvaluateToInt32(exec));
}
-double RightShiftNode::evaluateToNumber(ExecState* exec)
+double RightShiftNode::evaluateToNumber(OldInterpreterExecState* exec)
{
return inlineEvaluateToInt32(exec);
}
-int32_t RightShiftNode::evaluateToInt32(ExecState* exec)
+int32_t RightShiftNode::evaluateToInt32(OldInterpreterExecState* exec)
{
return inlineEvaluateToInt32(exec);
}
-uint32_t RightShiftNode::evaluateToUInt32(ExecState* exec)
+uint32_t RightShiftNode::evaluateToUInt32(OldInterpreterExecState* exec)
{
return inlineEvaluateToInt32(exec);
}
-void UnsignedRightShiftNode::optimizeVariableAccess(ExecState*, const SymbolTable&, const LocalStorage&, NodeStack& nodeStack)
+RegisterID* UnsignedRightShiftNode::emitCode(CodeGenerator& generator, RegisterID* dst)
+{
+ RefPtr<RegisterID> val = generator.emitNode(m_term1.get());
+ RegisterID* shift = generator.emitNode(m_term2.get());
+ return generator.emitUnsignedRightShift(generator.finalDestination(dst, val.get()), val.get(), shift);
+}
+
+void UnsignedRightShiftNode::optimizeVariableAccess(OldInterpreterExecState*, const SymbolTable&, const LocalStorage&, NodeStack& nodeStack)
{
nodeStack.append(m_term1.get());
nodeStack.append(m_term2.get());
}
// ECMA 11.7.3
-uint32_t UnsignedRightShiftNode::inlineEvaluateToUInt32(ExecState* exec)
+uint32_t UnsignedRightShiftNode::inlineEvaluateToUInt32(OldInterpreterExecState* exec)
{
unsigned int i1 = m_term1->evaluateToUInt32(exec);
KJS_CHECKEXCEPTIONNUMBER
@@ -2822,29 +3312,29 @@
return (i1 >> i2);
}
-JSValue* UnsignedRightShiftNode::evaluate(ExecState* exec)
+JSValue* UnsignedRightShiftNode::evaluate(OldInterpreterExecState* exec)
{
return jsNumber(inlineEvaluateToUInt32(exec));
}
-double UnsignedRightShiftNode::evaluateToNumber(ExecState* exec)
+double UnsignedRightShiftNode::evaluateToNumber(OldInterpreterExecState* exec)
{
return inlineEvaluateToUInt32(exec);
}
-int32_t UnsignedRightShiftNode::evaluateToInt32(ExecState* exec)
+int32_t UnsignedRightShiftNode::evaluateToInt32(OldInterpreterExecState* exec)
{
return inlineEvaluateToUInt32(exec);
}
-uint32_t UnsignedRightShiftNode::evaluateToUInt32(ExecState* exec)
+uint32_t UnsignedRightShiftNode::evaluateToUInt32(OldInterpreterExecState* exec)
{
return inlineEvaluateToUInt32(exec);
}
// ------------------------------ Relational Nodes -------------------------------
-static inline bool lessThan(ExecState* exec, JSValue* v1, JSValue* v2)
+static inline bool lessThan(OldInterpreterExecState* exec, JSValue* v1, JSValue* v2)
{
double n1;
double n2;
@@ -2859,7 +3349,7 @@
return static_cast<const StringImp*>(p1)->value() < static_cast<const StringImp*>(p2)->value();
}
-static inline bool lessThanEq(ExecState* exec, JSValue* v1, JSValue* v2)
+static inline bool lessThanEq(OldInterpreterExecState* exec, JSValue* v1, JSValue* v2)
{
double n1;
double n2;
@@ -2874,14 +3364,21 @@
return !(static_cast<const StringImp*>(p2)->value() < static_cast<const StringImp*>(p1)->value());
}
-void LessNode::optimizeVariableAccess(ExecState*, const SymbolTable&, const LocalStorage&, NodeStack& nodeStack)
+RegisterID* LessNode::emitCode(CodeGenerator& generator, RegisterID* dst)
+{
+ RefPtr<RegisterID> src1 = generator.emitNode(m_expr1.get());
+ RegisterID* src2 = generator.emitNode(m_expr2.get());
+ return generator.emitLess(generator.finalDestination(dst, src1.get()), src1.get(), src2);
+}
+
+void LessNode::optimizeVariableAccess(OldInterpreterExecState*, const SymbolTable&, const LocalStorage&, NodeStack& nodeStack)
{
nodeStack.append(m_expr2.get());
nodeStack.append(m_expr1.get());
}
// ECMA 11.8.1
-bool LessNode::inlineEvaluateToBoolean(ExecState* exec)
+bool LessNode::inlineEvaluateToBoolean(OldInterpreterExecState* exec)
{
JSValue* v1 = m_expr1->evaluate(exec);
KJS_CHECKEXCEPTIONBOOLEAN
@@ -2890,17 +3387,17 @@
return lessThan(exec, v1, v2);
}
-JSValue* LessNode::evaluate(ExecState* exec)
+JSValue* LessNode::evaluate(OldInterpreterExecState* exec)
{
return jsBoolean(inlineEvaluateToBoolean(exec));
}
-bool LessNode::evaluateToBoolean(ExecState* exec)
+bool LessNode::evaluateToBoolean(OldInterpreterExecState* exec)
{
return inlineEvaluateToBoolean(exec);
}
-bool LessNumbersNode::inlineEvaluateToBoolean(ExecState* exec)
+bool LessNumbersNode::inlineEvaluateToBoolean(OldInterpreterExecState* exec)
{
double n1 = m_expr1->evaluateToNumber(exec);
KJS_CHECKEXCEPTIONVALUE
@@ -2908,17 +3405,17 @@
return n1 < n2;
}
-JSValue* LessNumbersNode::evaluate(ExecState* exec)
+JSValue* LessNumbersNode::evaluate(OldInterpreterExecState* exec)
{
return jsBoolean(inlineEvaluateToBoolean(exec));
}
-bool LessNumbersNode::evaluateToBoolean(ExecState* exec)
+bool LessNumbersNode::evaluateToBoolean(OldInterpreterExecState* exec)
{
return inlineEvaluateToBoolean(exec);
}
-bool LessStringsNode::inlineEvaluateToBoolean(ExecState* exec)
+bool LessStringsNode::inlineEvaluateToBoolean(OldInterpreterExecState* exec)
{
JSValue* v1 = m_expr1->evaluate(exec);
KJS_CHECKEXCEPTIONVALUE
@@ -2926,24 +3423,31 @@
return static_cast<StringImp*>(v1)->value() < static_cast<StringImp*>(v2)->value();
}
-JSValue* LessStringsNode::evaluate(ExecState* exec)
+JSValue* LessStringsNode::evaluate(OldInterpreterExecState* exec)
{
return jsBoolean(inlineEvaluateToBoolean(exec));
}
-bool LessStringsNode::evaluateToBoolean(ExecState* exec)
+bool LessStringsNode::evaluateToBoolean(OldInterpreterExecState* exec)
{
return inlineEvaluateToBoolean(exec);
}
-void GreaterNode::optimizeVariableAccess(ExecState*, const SymbolTable&, const LocalStorage&, NodeStack& nodeStack)
+RegisterID* GreaterNode::emitCode(CodeGenerator& generator, RegisterID* dst)
+{
+ RefPtr<RegisterID> src1 = generator.emitNode(m_expr2.get());
+ RegisterID* src2 = generator.emitNode(m_expr1.get());
+ return generator.emitLess(generator.finalDestination(dst, src1.get()), src1.get(), src2);
+}
+
+void GreaterNode::optimizeVariableAccess(OldInterpreterExecState*, const SymbolTable&, const LocalStorage&, NodeStack& nodeStack)
{
nodeStack.append(m_expr2.get());
nodeStack.append(m_expr1.get());
}
// ECMA 11.8.2
-bool GreaterNode::inlineEvaluateToBoolean(ExecState* exec)
+bool GreaterNode::inlineEvaluateToBoolean(OldInterpreterExecState* exec)
{
JSValue* v1 = m_expr1->evaluate(exec);
KJS_CHECKEXCEPTIONBOOLEAN
@@ -2952,24 +3456,31 @@
return lessThan(exec, v2, v1);
}
-JSValue* GreaterNode::evaluate(ExecState* exec)
+JSValue* GreaterNode::evaluate(OldInterpreterExecState* exec)
{
return jsBoolean(inlineEvaluateToBoolean(exec));
}
-bool GreaterNode::evaluateToBoolean(ExecState* exec)
+bool GreaterNode::evaluateToBoolean(OldInterpreterExecState* exec)
{
return inlineEvaluateToBoolean(exec);
}
-void LessEqNode::optimizeVariableAccess(ExecState*, const SymbolTable&, const LocalStorage&, NodeStack& nodeStack)
+RegisterID* LessEqNode::emitCode(CodeGenerator& generator, RegisterID* dst)
+{
+ RefPtr<RegisterID> src1 = generator.emitNode(m_expr1.get());
+ RegisterID* src2 = generator.emitNode(m_expr2.get());
+ return generator.emitLessEq(generator.finalDestination(dst, src1.get()), src1.get(), src2);
+}
+
+void LessEqNode::optimizeVariableAccess(OldInterpreterExecState*, const SymbolTable&, const LocalStorage&, NodeStack& nodeStack)
{
nodeStack.append(m_expr2.get());
nodeStack.append(m_expr1.get());
}
// ECMA 11.8.3
-bool LessEqNode::inlineEvaluateToBoolean(ExecState* exec)
+bool LessEqNode::inlineEvaluateToBoolean(OldInterpreterExecState* exec)
{
JSValue* v1 = m_expr1->evaluate(exec);
KJS_CHECKEXCEPTIONBOOLEAN
@@ -2978,24 +3489,31 @@
return lessThanEq(exec, v1, v2);
}
-JSValue* LessEqNode::evaluate(ExecState* exec)
+JSValue* LessEqNode::evaluate(OldInterpreterExecState* exec)
{
return jsBoolean(inlineEvaluateToBoolean(exec));
}
-bool LessEqNode::evaluateToBoolean(ExecState* exec)
+bool LessEqNode::evaluateToBoolean(OldInterpreterExecState* exec)
{
return inlineEvaluateToBoolean(exec);
}
-void GreaterEqNode::optimizeVariableAccess(ExecState*, const SymbolTable&, const LocalStorage&, NodeStack& nodeStack)
+RegisterID* GreaterEqNode::emitCode(CodeGenerator& generator, RegisterID* dst)
+{
+ RefPtr<RegisterID> src1 = generator.emitNode(m_expr2.get());
+ RegisterID* src2 = generator.emitNode(m_expr1.get());
+ return generator.emitLessEq(generator.finalDestination(dst, src1.get()), src1.get(), src2);
+}
+
+void GreaterEqNode::optimizeVariableAccess(OldInterpreterExecState*, const SymbolTable&, const LocalStorage&, NodeStack& nodeStack)
{
nodeStack.append(m_expr2.get());
nodeStack.append(m_expr1.get());
}
// ECMA 11.8.4
-bool GreaterEqNode::inlineEvaluateToBoolean(ExecState* exec)
+bool GreaterEqNode::inlineEvaluateToBoolean(OldInterpreterExecState* exec)
{
JSValue* v1 = m_expr1->evaluate(exec);
KJS_CHECKEXCEPTIONBOOLEAN
@@ -3004,24 +3522,31 @@
return lessThanEq(exec, v2, v1);
}
-JSValue* GreaterEqNode::evaluate(ExecState* exec)
+JSValue* GreaterEqNode::evaluate(OldInterpreterExecState* exec)
{
return jsBoolean(inlineEvaluateToBoolean(exec));
}
-bool GreaterEqNode::evaluateToBoolean(ExecState* exec)
+bool GreaterEqNode::evaluateToBoolean(OldInterpreterExecState* exec)
{
return inlineEvaluateToBoolean(exec);
}
-void InstanceOfNode::optimizeVariableAccess(ExecState*, const SymbolTable&, const LocalStorage&, NodeStack& nodeStack)
+RegisterID* InstanceOfNode::emitCode(CodeGenerator& generator, RegisterID* dst)
+{
+ RefPtr<RegisterID> value = generator.emitNode(m_expr1.get());
+ RegisterID* base = generator.emitNode(m_expr2.get());
+ return generator.emitInstanceOf(generator.finalDestination(dst, value.get()), value.get(), base);
+}
+
+void InstanceOfNode::optimizeVariableAccess(OldInterpreterExecState*, const SymbolTable&, const LocalStorage&, NodeStack& nodeStack)
{
nodeStack.append(m_expr2.get());
nodeStack.append(m_expr1.get());
}
// ECMA 11.8.6
-JSValue* InstanceOfNode::evaluate(ExecState* exec)
+JSValue* InstanceOfNode::evaluate(OldInterpreterExecState* exec)
{
JSValue* v1 = m_expr1->evaluate(exec);
KJS_CHECKEXCEPTIONVALUE
@@ -3043,7 +3568,7 @@
return jsBoolean(o2->hasInstance(exec, v1));
}
-bool InstanceOfNode::evaluateToBoolean(ExecState* exec)
+bool InstanceOfNode::evaluateToBoolean(OldInterpreterExecState* exec)
{
JSValue* v1 = m_expr1->evaluate(exec);
KJS_CHECKEXCEPTIONBOOLEAN
@@ -3067,14 +3592,21 @@
return o2->hasInstance(exec, v1);
}
-void InNode::optimizeVariableAccess(ExecState*, const SymbolTable&, const LocalStorage&, NodeStack& nodeStack)
+RegisterID* InNode::emitCode(CodeGenerator& generator, RegisterID* dst)
+{
+ RefPtr<RegisterID> property = generator.emitNode(m_expr1.get());
+ RegisterID* base = generator.emitNode(m_expr2.get());
+ return generator.emitIn(generator.finalDestination(dst, property.get()), property.get(), base);
+}
+
+void InNode::optimizeVariableAccess(OldInterpreterExecState*, const SymbolTable&, const LocalStorage&, NodeStack& nodeStack)
{
nodeStack.append(m_expr2.get());
nodeStack.append(m_expr1.get());
}
// ECMA 11.8.7
-JSValue* InNode::evaluate(ExecState* exec)
+JSValue* InNode::evaluate(OldInterpreterExecState* exec)
{
JSValue* v1 = m_expr1->evaluate(exec);
KJS_CHECKEXCEPTIONVALUE
@@ -3087,7 +3619,7 @@
return jsBoolean(static_cast<JSObject*>(v2)->hasProperty(exec, Identifier(v1->toString(exec))));
}
-bool InNode::evaluateToBoolean(ExecState* exec)
+bool InNode::evaluateToBoolean(OldInterpreterExecState* exec)
{
JSValue* v1 = m_expr1->evaluate(exec);
KJS_CHECKEXCEPTIONBOOLEAN
@@ -3104,14 +3636,21 @@
// ------------------------------ Equality Nodes ------------------------------------
-void EqualNode::optimizeVariableAccess(ExecState*, const SymbolTable&, const LocalStorage&, NodeStack& nodeStack)
+RegisterID* EqualNode::emitCode(CodeGenerator& generator, RegisterID* dst)
+{
+ RefPtr<RegisterID> src1 = generator.emitNode(m_expr1.get());
+ RegisterID* src2 = generator.emitNode(m_expr2.get());
+ return generator.emitEqual(generator.finalDestination(dst, src1.get()), src1.get(), src2);
+}
+
+void EqualNode::optimizeVariableAccess(OldInterpreterExecState*, const SymbolTable&, const LocalStorage&, NodeStack& nodeStack)
{
nodeStack.append(m_expr2.get());
nodeStack.append(m_expr1.get());
}
// ECMA 11.9.1
-bool EqualNode::inlineEvaluateToBoolean(ExecState* exec)
+bool EqualNode::inlineEvaluateToBoolean(OldInterpreterExecState* exec)
{
JSValue* v1 = m_expr1->evaluate(exec);
KJS_CHECKEXCEPTIONBOOLEAN
@@ -3121,24 +3660,31 @@
return equal(exec, v1, v2);
}
-JSValue* EqualNode::evaluate(ExecState* exec)
+JSValue* EqualNode::evaluate(OldInterpreterExecState* exec)
{
return jsBoolean(inlineEvaluateToBoolean(exec));
}
-bool EqualNode::evaluateToBoolean(ExecState* exec)
+bool EqualNode::evaluateToBoolean(OldInterpreterExecState* exec)
{
return inlineEvaluateToBoolean(exec);
}
-void NotEqualNode::optimizeVariableAccess(ExecState*, const SymbolTable&, const LocalStorage&, NodeStack& nodeStack)
+RegisterID* NotEqualNode::emitCode(CodeGenerator& generator, RegisterID* dst)
+{
+ RefPtr<RegisterID> src1 = generator.emitNode(m_expr1.get());
+ RegisterID* src2 = generator.emitNode(m_expr2.get());
+ return generator.emitNotEqual(generator.finalDestination(dst, src1.get()), src1.get(), src2);
+}
+
+void NotEqualNode::optimizeVariableAccess(OldInterpreterExecState*, const SymbolTable&, const LocalStorage&, NodeStack& nodeStack)
{
nodeStack.append(m_expr2.get());
nodeStack.append(m_expr1.get());
}
// ECMA 11.9.2
-bool NotEqualNode::inlineEvaluateToBoolean(ExecState* exec)
+bool NotEqualNode::inlineEvaluateToBoolean(OldInterpreterExecState* exec)
{
JSValue* v1 = m_expr1->evaluate(exec);
KJS_CHECKEXCEPTIONBOOLEAN
@@ -3148,80 +3694,101 @@
return !equal(exec,v1, v2);
}
-JSValue* NotEqualNode::evaluate(ExecState* exec)
+JSValue* NotEqualNode::evaluate(OldInterpreterExecState* exec)
{
return jsBoolean(inlineEvaluateToBoolean(exec));
}
-bool NotEqualNode::evaluateToBoolean(ExecState* exec)
+bool NotEqualNode::evaluateToBoolean(OldInterpreterExecState* exec)
{
return inlineEvaluateToBoolean(exec);
}
-void StrictEqualNode::optimizeVariableAccess(ExecState*, const SymbolTable&, const LocalStorage&, NodeStack& nodeStack)
+RegisterID* StrictEqualNode::emitCode(CodeGenerator& generator, RegisterID* dst)
+{
+ RefPtr<RegisterID> src1 = generator.emitNode(m_expr1.get());
+ RegisterID* src2 = generator.emitNode(m_expr2.get());
+ return generator.emitStrictEqual(generator.finalDestination(dst, src1.get()), src1.get(), src2);
+}
+
+void StrictEqualNode::optimizeVariableAccess(OldInterpreterExecState*, const SymbolTable&, const LocalStorage&, NodeStack& nodeStack)
{
nodeStack.append(m_expr2.get());
nodeStack.append(m_expr1.get());
}
// ECMA 11.9.4
-bool StrictEqualNode::inlineEvaluateToBoolean(ExecState* exec)
+bool StrictEqualNode::inlineEvaluateToBoolean(OldInterpreterExecState* exec)
{
JSValue* v1 = m_expr1->evaluate(exec);
KJS_CHECKEXCEPTIONBOOLEAN
JSValue* v2 = m_expr2->evaluate(exec);
KJS_CHECKEXCEPTIONBOOLEAN
- return strictEqual(exec,v1, v2);
+ return strictEqual(v1, v2);
}
-JSValue* StrictEqualNode::evaluate(ExecState* exec)
+JSValue* StrictEqualNode::evaluate(OldInterpreterExecState* exec)
{
return jsBoolean(inlineEvaluateToBoolean(exec));
}
-bool StrictEqualNode::evaluateToBoolean(ExecState* exec)
+bool StrictEqualNode::evaluateToBoolean(OldInterpreterExecState* exec)
{
return inlineEvaluateToBoolean(exec);
}
-void NotStrictEqualNode::optimizeVariableAccess(ExecState*, const SymbolTable&, const LocalStorage&, NodeStack& nodeStack)
+RegisterID* NotStrictEqualNode::emitCode(CodeGenerator& generator, RegisterID* dst)
+{
+ RefPtr<RegisterID> src1 = generator.emitNode(m_expr1.get());
+ RegisterID* src2 = generator.emitNode(m_expr2.get());
+ return generator.emitNotStrictEqual(generator.finalDestination(dst, src1.get()), src1.get(), src2);
+}
+
+void NotStrictEqualNode::optimizeVariableAccess(OldInterpreterExecState*, const SymbolTable&, const LocalStorage&, NodeStack& nodeStack)
{
nodeStack.append(m_expr2.get());
nodeStack.append(m_expr1.get());
}
// ECMA 11.9.5
-bool NotStrictEqualNode::inlineEvaluateToBoolean(ExecState* exec)
+bool NotStrictEqualNode::inlineEvaluateToBoolean(OldInterpreterExecState* exec)
{
JSValue* v1 = m_expr1->evaluate(exec);
KJS_CHECKEXCEPTIONBOOLEAN
JSValue* v2 = m_expr2->evaluate(exec);
KJS_CHECKEXCEPTIONBOOLEAN
- return !strictEqual(exec,v1, v2);
+ return !strictEqual(v1, v2);
}
-JSValue* NotStrictEqualNode::evaluate(ExecState* exec)
+JSValue* NotStrictEqualNode::evaluate(OldInterpreterExecState* exec)
{
return jsBoolean(inlineEvaluateToBoolean(exec));
}
-bool NotStrictEqualNode::evaluateToBoolean(ExecState* exec)
+bool NotStrictEqualNode::evaluateToBoolean(OldInterpreterExecState* exec)
{
return inlineEvaluateToBoolean(exec);
}
// ------------------------------ Bit Operation Nodes ----------------------------------
-void BitAndNode::optimizeVariableAccess(ExecState*, const SymbolTable&, const LocalStorage&, NodeStack& nodeStack)
+RegisterID* BitAndNode::emitCode(CodeGenerator& generator, RegisterID* dst)
+{
+ RefPtr<RegisterID> src1 = generator.emitNode(m_expr1.get());
+ RegisterID* src2 = generator.emitNode(m_expr2.get());
+ return generator.emitBitAnd(generator.finalDestination(dst, src1.get()), src1.get(), src2);
+}
+
+void BitAndNode::optimizeVariableAccess(OldInterpreterExecState*, const SymbolTable&, const LocalStorage&, NodeStack& nodeStack)
{
nodeStack.append(m_expr2.get());
nodeStack.append(m_expr1.get());
}
// ECMA 11.10
-JSValue* BitAndNode::evaluate(ExecState* exec)
+JSValue* BitAndNode::evaluate(OldInterpreterExecState* exec)
{
JSValue* v1 = m_expr1->evaluate(exec);
KJS_CHECKEXCEPTIONVALUE
@@ -3231,7 +3798,7 @@
return jsNumberFromAnd(exec, v1, v2);
}
-int32_t BitAndNode::inlineEvaluateToInt32(ExecState* exec)
+int32_t BitAndNode::inlineEvaluateToInt32(OldInterpreterExecState* exec)
{
int32_t i1 = m_expr1->evaluateToInt32(exec);
KJS_CHECKEXCEPTIONNUMBER
@@ -3239,33 +3806,40 @@
return (i1 & i2);
}
-double BitAndNode::evaluateToNumber(ExecState* exec)
+double BitAndNode::evaluateToNumber(OldInterpreterExecState* exec)
{
return inlineEvaluateToInt32(exec);
}
-bool BitAndNode::evaluateToBoolean(ExecState* exec)
+bool BitAndNode::evaluateToBoolean(OldInterpreterExecState* exec)
{
return inlineEvaluateToInt32(exec);
}
-int32_t BitAndNode::evaluateToInt32(ExecState* exec)
+int32_t BitAndNode::evaluateToInt32(OldInterpreterExecState* exec)
{
return inlineEvaluateToInt32(exec);
}
-uint32_t BitAndNode::evaluateToUInt32(ExecState* exec)
+uint32_t BitAndNode::evaluateToUInt32(OldInterpreterExecState* exec)
{
return inlineEvaluateToInt32(exec);
}
-void BitXOrNode::optimizeVariableAccess(ExecState*, const SymbolTable&, const LocalStorage&, NodeStack& nodeStack)
+RegisterID* BitXOrNode::emitCode(CodeGenerator& generator, RegisterID* dst)
+{
+ RefPtr<RegisterID> src1 = generator.emitNode(m_expr1.get());
+ RegisterID* src2 = generator.emitNode(m_expr2.get());
+ return generator.emitBitXOr(generator.finalDestination(dst, src1.get()), src1.get(), src2);
+}
+
+void BitXOrNode::optimizeVariableAccess(OldInterpreterExecState*, const SymbolTable&, const LocalStorage&, NodeStack& nodeStack)
{
nodeStack.append(m_expr2.get());
nodeStack.append(m_expr1.get());
}
-int32_t BitXOrNode::inlineEvaluateToInt32(ExecState* exec)
+int32_t BitXOrNode::inlineEvaluateToInt32(OldInterpreterExecState* exec)
{
int i1 = m_expr1->evaluateToInt32(exec);
KJS_CHECKEXCEPTIONNUMBER
@@ -3273,38 +3847,45 @@
return (i1 ^ i2);
}
-JSValue* BitXOrNode::evaluate(ExecState* exec)
+JSValue* BitXOrNode::evaluate(OldInterpreterExecState* exec)
{
return jsNumber(inlineEvaluateToInt32(exec));
}
-double BitXOrNode::evaluateToNumber(ExecState* exec)
+double BitXOrNode::evaluateToNumber(OldInterpreterExecState* exec)
{
return inlineEvaluateToInt32(exec);
}
-bool BitXOrNode::evaluateToBoolean(ExecState* exec)
+bool BitXOrNode::evaluateToBoolean(OldInterpreterExecState* exec)
{
return inlineEvaluateToInt32(exec);
}
-int32_t BitXOrNode::evaluateToInt32(ExecState* exec)
+int32_t BitXOrNode::evaluateToInt32(OldInterpreterExecState* exec)
{
return inlineEvaluateToInt32(exec);
}
-uint32_t BitXOrNode::evaluateToUInt32(ExecState* exec)
+uint32_t BitXOrNode::evaluateToUInt32(OldInterpreterExecState* exec)
{
return inlineEvaluateToInt32(exec);
}
-void BitOrNode::optimizeVariableAccess(ExecState*, const SymbolTable&, const LocalStorage&, NodeStack& nodeStack)
+RegisterID* BitOrNode::emitCode(CodeGenerator& generator, RegisterID* dst)
+{
+ RefPtr<RegisterID> src1 = generator.emitNode(m_expr1.get());
+ RegisterID* src2 = generator.emitNode(m_expr2.get());
+ return generator.emitBitOr(generator.finalDestination(dst, src1.get()), src1.get(), src2);
+}
+
+void BitOrNode::optimizeVariableAccess(OldInterpreterExecState*, const SymbolTable&, const LocalStorage&, NodeStack& nodeStack)
{
nodeStack.append(m_expr2.get());
nodeStack.append(m_expr1.get());
}
-int32_t BitOrNode::inlineEvaluateToInt32(ExecState* exec)
+int32_t BitOrNode::inlineEvaluateToInt32(OldInterpreterExecState* exec)
{
int i1 = m_expr1->evaluateToInt32(exec);
KJS_CHECKEXCEPTIONNUMBER
@@ -3312,41 +3893,54 @@
return (i1 | i2);
}
-JSValue* BitOrNode::evaluate(ExecState* exec)
+JSValue* BitOrNode::evaluate(OldInterpreterExecState* exec)
{
return jsNumber(inlineEvaluateToInt32(exec));
}
-double BitOrNode::evaluateToNumber(ExecState* exec)
+double BitOrNode::evaluateToNumber(OldInterpreterExecState* exec)
{
return inlineEvaluateToInt32(exec);
}
-bool BitOrNode::evaluateToBoolean(ExecState* exec)
+bool BitOrNode::evaluateToBoolean(OldInterpreterExecState* exec)
{
return inlineEvaluateToInt32(exec);
}
-int32_t BitOrNode::evaluateToInt32(ExecState* exec)
+int32_t BitOrNode::evaluateToInt32(OldInterpreterExecState* exec)
{
return inlineEvaluateToInt32(exec);
}
-uint32_t BitOrNode::evaluateToUInt32(ExecState* exec)
+uint32_t BitOrNode::evaluateToUInt32(OldInterpreterExecState* exec)
{
return inlineEvaluateToInt32(exec);
}
// ------------------------------ Binary Logical Nodes ----------------------------
-void LogicalAndNode::optimizeVariableAccess(ExecState*, const SymbolTable&, const LocalStorage&, NodeStack& nodeStack)
+RegisterID* LogicalAndNode::emitCode(CodeGenerator& generator, RegisterID* dst)
+{
+ RefPtr<RegisterID> temp = generator.tempDestination(dst);
+ RefPtr<LabelID> target = generator.newLabel();
+
+ generator.emitNode(temp.get(), m_expr1.get());
+ generator.emitJumpIfFalse(temp.get(), target.get());
+ generator.emitNode(temp.get(), m_expr2.get());
+ generator.emitLabel(target.get());
+
+ return generator.moveToDestinationIfNeeded(dst, temp.get());
+}
+
+void LogicalAndNode::optimizeVariableAccess(OldInterpreterExecState*, const SymbolTable&, const LocalStorage&, NodeStack& nodeStack)
{
nodeStack.append(m_expr2.get());
nodeStack.append(m_expr1.get());
}
// ECMA 11.11
-JSValue* LogicalAndNode::evaluate(ExecState* exec)
+JSValue* LogicalAndNode::evaluate(OldInterpreterExecState* exec)
{
JSValue* v1 = m_expr1->evaluate(exec);
KJS_CHECKEXCEPTIONVALUE
@@ -3359,20 +3953,33 @@
return v2;
}
-bool LogicalAndNode::evaluateToBoolean(ExecState* exec)
+bool LogicalAndNode::evaluateToBoolean(OldInterpreterExecState* exec)
{
bool b = m_expr1->evaluateToBoolean(exec);
KJS_CHECKEXCEPTIONBOOLEAN
return b && m_expr2->evaluateToBoolean(exec);
}
-void LogicalOrNode::optimizeVariableAccess(ExecState*, const SymbolTable&, const LocalStorage&, NodeStack& nodeStack)
+RegisterID* LogicalOrNode::emitCode(CodeGenerator& generator, RegisterID* dst)
+{
+ RefPtr<RegisterID> temp = generator.tempDestination(dst);
+ RefPtr<LabelID> target = generator.newLabel();
+
+ generator.emitNode(temp.get(), m_expr1.get());
+ generator.emitJumpIfTrue(temp.get(), target.get());
+ generator.emitNode(temp.get(), m_expr2.get());
+ generator.emitLabel(target.get());
+
+ return generator.moveToDestinationIfNeeded(dst, temp.get());
+}
+
+void LogicalOrNode::optimizeVariableAccess(OldInterpreterExecState*, const SymbolTable&, const LocalStorage&, NodeStack& nodeStack)
{
nodeStack.append(m_expr2.get());
nodeStack.append(m_expr1.get());
}
-JSValue* LogicalOrNode::evaluate(ExecState* exec)
+JSValue* LogicalOrNode::evaluate(OldInterpreterExecState* exec)
{
JSValue* v1 = m_expr1->evaluate(exec);
KJS_CHECKEXCEPTIONVALUE
@@ -3381,7 +3988,7 @@
return m_expr2->evaluate(exec);
}
-bool LogicalOrNode::evaluateToBoolean(ExecState* exec)
+bool LogicalOrNode::evaluateToBoolean(OldInterpreterExecState* exec)
{
bool b = m_expr1->evaluateToBoolean(exec);
KJS_CHECKEXCEPTIONBOOLEAN
@@ -3390,7 +3997,27 @@
// ------------------------------ ConditionalNode ------------------------------
-void ConditionalNode::optimizeVariableAccess(ExecState*, const SymbolTable&, const LocalStorage&, NodeStack& nodeStack)
+RegisterID* ConditionalNode::emitCode(CodeGenerator& generator, RegisterID* dst)
+{
+ RefPtr<RegisterID> newDst = generator.finalDestination(dst);
+ RefPtr<LabelID> beforeElse = generator.newLabel();
+ RefPtr<LabelID> afterElse = generator.newLabel();
+
+ RegisterID* cond = generator.emitNode(m_logical.get());
+ generator.emitJumpIfFalse(cond, beforeElse.get());
+
+ generator.emitNode(newDst.get(), m_expr1.get());
+ generator.emitJump(afterElse.get());
+
+ generator.emitLabel(beforeElse.get());
+ generator.emitNode(newDst.get(), m_expr2.get());
+
+ generator.emitLabel(afterElse.get());
+
+ return newDst.get();
+}
+
+void ConditionalNode::optimizeVariableAccess(OldInterpreterExecState*, const SymbolTable&, const LocalStorage&, NodeStack& nodeStack)
{
nodeStack.append(m_expr2.get());
nodeStack.append(m_expr1.get());
@@ -3398,35 +4025,35 @@
}
// ECMA 11.12
-JSValue* ConditionalNode::evaluate(ExecState* exec)
+JSValue* ConditionalNode::evaluate(OldInterpreterExecState* exec)
{
bool b = m_logical->evaluateToBoolean(exec);
KJS_CHECKEXCEPTIONVALUE
return b ? m_expr1->evaluate(exec) : m_expr2->evaluate(exec);
}
-bool ConditionalNode::evaluateToBoolean(ExecState* exec)
+bool ConditionalNode::evaluateToBoolean(OldInterpreterExecState* exec)
{
bool b = m_logical->evaluateToBoolean(exec);
KJS_CHECKEXCEPTIONBOOLEAN
return b ? m_expr1->evaluateToBoolean(exec) : m_expr2->evaluateToBoolean(exec);
}
-double ConditionalNode::evaluateToNumber(ExecState* exec)
+double ConditionalNode::evaluateToNumber(OldInterpreterExecState* exec)
{
bool b = m_logical->evaluateToBoolean(exec);
KJS_CHECKEXCEPTIONNUMBER
return b ? m_expr1->evaluateToNumber(exec) : m_expr2->evaluateToNumber(exec);
}
-int32_t ConditionalNode::evaluateToInt32(ExecState* exec)
+int32_t ConditionalNode::evaluateToInt32(OldInterpreterExecState* exec)
{
bool b = m_logical->evaluateToBoolean(exec);
KJS_CHECKEXCEPTIONNUMBER
return b ? m_expr1->evaluateToInt32(exec) : m_expr2->evaluateToInt32(exec);
}
-uint32_t ConditionalNode::evaluateToUInt32(ExecState* exec)
+uint32_t ConditionalNode::evaluateToUInt32(OldInterpreterExecState* exec)
{
bool b = m_logical->evaluateToBoolean(exec);
KJS_CHECKEXCEPTIONNUMBER
@@ -3435,8 +4062,8 @@
// ECMA 11.13
-static ALWAYS_INLINE JSValue* valueForReadModifyAssignment(ExecState* exec, JSValue* current, ExpressionNode* right, Operator oper) KJS_FAST_CALL;
-static ALWAYS_INLINE JSValue* valueForReadModifyAssignment(ExecState* exec, JSValue* current, ExpressionNode* right, Operator oper)
+static ALWAYS_INLINE JSValue* valueForReadModifyAssignment(OldInterpreterExecState* exec, JSValue* current, ExpressionNode* right, Operator oper) KJS_FAST_CALL;
+static ALWAYS_INLINE JSValue* valueForReadModifyAssignment(OldInterpreterExecState* exec, JSValue* current, ExpressionNode* right, Operator oper)
{
JSValue* v;
int i1;
@@ -3501,10 +4128,72 @@
// ------------------------------ ReadModifyResolveNode -----------------------------------
-void ReadModifyResolveNode::optimizeVariableAccess(ExecState*, const SymbolTable& symbolTable, const LocalStorage& localStorage, NodeStack& nodeStack)
+// FIXME: should this be moved to be a method on CodeGenerator?
+static ALWAYS_INLINE RegisterID* emitReadModifyAssignment(CodeGenerator& generator, RegisterID* dst, RegisterID* src1, RegisterID* src2, Operator oper)
+{
+ switch (oper) {
+ case OpMultEq:
+ return generator.emitMul(dst, src1, src2);
+ case OpDivEq:
+ return generator.emitDiv(dst, src1, src2);
+ case OpPlusEq:
+ return generator.emitAdd(dst, src1, src2);
+ case OpMinusEq:
+ return generator.emitSub(dst, src1, src2);
+ case OpLShift:
+ return generator.emitLeftShift(dst, src1, src2);
+ case OpRShift:
+ return generator.emitRightShift(dst, src1, src2);
+ case OpURShift:
+ return generator.emitUnsignedRightShift(dst, src1, src2);
+ case OpAndEq:
+ return generator.emitBitAnd(dst, src1, src2);
+ case OpXOrEq:
+ return generator.emitBitXOr(dst, src1, src2);
+ case OpOrEq:
+ return generator.emitBitOr(dst, src1, src2);
+ case OpModEq:
+ return generator.emitMod(dst, src1, src2);
+ default:
+ ASSERT_NOT_REACHED();
+ }
+
+ return dst;
+}
+
+RegisterID* ReadModifyResolveNode::emitCode(CodeGenerator& generator, RegisterID* dst)
+{
+ if (RegisterID* local = generator.registerForLocal(m_ident)) {
+ if (generator.isLocalConstant(m_ident)) {
+ RegisterID* src2 = generator.emitNode(m_right.get());
+ return emitReadModifyAssignment(generator, generator.finalDestination(dst), local, src2, m_operator);
+ }
+
+ if (generator.leftHandSideNeedsCopy(m_rightHasAssignments) && !m_right.get()->isNumber()) {
+ RefPtr<RegisterID> result = generator.newTemporary();
+ generator.emitMove(result.get(), local);
+ RegisterID* src2 = generator.emitNode(m_right.get());
+ emitReadModifyAssignment(generator, result.get(), result.get(), src2, m_operator);
+ generator.emitMove(local, result.get());
+ return generator.moveToDestinationIfNeeded(dst, result.get());
+ }
+
+ RegisterID* src2 = generator.emitNode(m_right.get());
+ RegisterID* result = emitReadModifyAssignment(generator, local, local, src2, m_operator);
+ return generator.moveToDestinationIfNeeded(dst, result);
+ }
+
+ RefPtr<RegisterID> src1 = generator.tempDestination(dst);
+ RefPtr<RegisterID> base = generator.emitResolveWithBase(generator.newTemporary(), src1.get(), m_ident);
+ RegisterID* src2 = generator.emitNode(m_right.get());
+ RegisterID* result = emitReadModifyAssignment(generator, generator.finalDestination(dst, src1.get()), src1.get(), src2, m_operator);
+ return generator.emitPutById(base.get(), m_ident, result);
+}
+
+void ReadModifyResolveNode::optimizeVariableAccess(OldInterpreterExecState*, const SymbolTable& symbolTable, const LocalStorage& localStorage, NodeStack& nodeStack)
{
nodeStack.append(m_right.get());
- size_t index = symbolTable.get(m_ident.ustring().rep());
+ int index = symbolTable.get(m_ident.ustring().rep()).getIndex();
if (index != missingSymbolMarker()) {
if (isConstant(localStorage, index))
new (this) ReadModifyConstNode(index);
@@ -3515,10 +4204,33 @@
// ------------------------------ AssignResolveNode -----------------------------------
-void AssignResolveNode::optimizeVariableAccess(ExecState*, const SymbolTable& symbolTable, const LocalStorage& localStorage, NodeStack& nodeStack)
+RegisterID* AssignResolveNode::emitCode(CodeGenerator& generator, RegisterID* dst)
+{
+ if (RegisterID* local = generator.registerForLocal(m_ident)) {
+ if (generator.isLocalConstant(m_ident))
+ return generator.emitNode(dst, m_right.get());
+
+ RegisterID* result = generator.emitNode(local, m_right.get());
+ return generator.moveToDestinationIfNeeded(dst, result);
+ }
+
+ int index = 0;
+ size_t depth = 0;
+ if (generator.findScopedProperty(m_ident, index, depth) && index != missingSymbolMarker()) {
+ RegisterID* value = generator.emitNode(dst, m_right.get());
+ generator.emitPutScopedVar(depth, index, value);
+ return value;
+ }
+
+ RefPtr<RegisterID> base = generator.emitResolveBase(generator.newTemporary(), m_ident);
+ RegisterID* value = generator.emitNode(dst, m_right.get());
+ return generator.emitPutById(base.get(), m_ident, value);
+}
+
+void AssignResolveNode::optimizeVariableAccess(OldInterpreterExecState*, const SymbolTable& symbolTable, const LocalStorage& localStorage, NodeStack& nodeStack)
{
nodeStack.append(m_right.get());
- size_t index = symbolTable.get(m_ident.ustring().rep());
+ int index = symbolTable.get(m_ident.ustring().rep()).getIndex();
if (index != missingSymbolMarker()) {
if (isConstant(localStorage, index))
new (this) AssignConstNode;
@@ -3529,7 +4241,7 @@
// ------------------------------ ReadModifyLocalVarNode -----------------------------------
-JSValue* ReadModifyLocalVarNode::evaluate(ExecState* exec)
+JSValue* ReadModifyLocalVarNode::evaluate(OldInterpreterExecState* exec)
{
ASSERT(exec->variableObject() == exec->scopeChain().top());
@@ -3548,7 +4260,7 @@
// ------------------------------ AssignLocalVarNode -----------------------------------
-JSValue* AssignLocalVarNode::evaluate(ExecState* exec)
+JSValue* AssignLocalVarNode::evaluate(OldInterpreterExecState* exec)
{
ASSERT(exec->variableObject() == exec->scopeChain().top());
JSValue* v = m_right->evaluate(exec);
@@ -3562,7 +4274,7 @@
// ------------------------------ ReadModifyConstNode -----------------------------------
-JSValue* ReadModifyConstNode::evaluate(ExecState* exec)
+JSValue* ReadModifyConstNode::evaluate(OldInterpreterExecState* exec)
{
ASSERT(exec->variableObject() == exec->scopeChain().top());
JSValue* left = exec->localStorage()[m_index].value;
@@ -3574,12 +4286,12 @@
// ------------------------------ AssignConstNode -----------------------------------
-JSValue* AssignConstNode::evaluate(ExecState* exec)
+JSValue* AssignConstNode::evaluate(OldInterpreterExecState* exec)
{
return m_right->evaluate(exec);
}
-JSValue* ReadModifyResolveNode::evaluate(ExecState* exec)
+JSValue* ReadModifyResolveNode::evaluate(OldInterpreterExecState* exec)
{
const ScopeChain& chain = exec->scopeChain();
ScopeChainIterator iter = chain.begin();
@@ -3622,7 +4334,7 @@
return v;
}
-JSValue* AssignResolveNode::evaluate(ExecState* exec)
+JSValue* AssignResolveNode::evaluate(OldInterpreterExecState* exec)
{
const ScopeChain& chain = exec->scopeChain();
ScopeChainIterator iter = chain.begin();
@@ -3656,13 +4368,22 @@
// ------------------------------ ReadModifyDotNode -----------------------------------
-void AssignDotNode::optimizeVariableAccess(ExecState*, const SymbolTable&, const LocalStorage&, NodeStack& nodeStack)
+RegisterID* AssignDotNode::emitCode(CodeGenerator& generator, RegisterID* dst)
+{
+ RefPtr<RegisterID> base = generator.emitNodeForLeftHandSide(m_base.get(), m_rightHasAssignments);
+ RefPtr<RegisterID> value = generator.destinationForAssignResult(dst);
+ RegisterID* result = generator.emitNode(value.get(), m_right.get());
+ generator.emitPutById(base.get(), m_ident, result);
+ return generator.moveToDestinationIfNeeded(dst, result);
+}
+
+void AssignDotNode::optimizeVariableAccess(OldInterpreterExecState*, const SymbolTable&, const LocalStorage&, NodeStack& nodeStack)
{
nodeStack.append(m_right.get());
nodeStack.append(m_base.get());
}
-JSValue* AssignDotNode::evaluate(ExecState* exec)
+JSValue* AssignDotNode::evaluate(OldInterpreterExecState* exec)
{
JSValue* baseValue = m_base->evaluate(exec);
KJS_CHECKEXCEPTIONVALUE
@@ -3676,13 +4397,22 @@
return v;
}
-void ReadModifyDotNode::optimizeVariableAccess(ExecState*, const SymbolTable&, const LocalStorage&, NodeStack& nodeStack)
+RegisterID* ReadModifyDotNode::emitCode(CodeGenerator& generator, RegisterID* dst)
+{
+ RefPtr<RegisterID> base = generator.emitNodeForLeftHandSide(m_base.get(), m_rightHasAssignments);
+ RefPtr<RegisterID> value = generator.emitGetById(generator.tempDestination(dst), base.get(), m_ident);
+ RegisterID* change = generator.emitNode(m_right.get());
+ RegisterID* updatedValue = emitReadModifyAssignment(generator, generator.finalDestination(dst, value.get()), value.get(), change, m_operator);
+ return generator.emitPutById(base.get(), m_ident, updatedValue);
+}
+
+void ReadModifyDotNode::optimizeVariableAccess(OldInterpreterExecState*, const SymbolTable&, const LocalStorage&, NodeStack& nodeStack)
{
nodeStack.append(m_right.get());
nodeStack.append(m_base.get());
}
-JSValue* ReadModifyDotNode::evaluate(ExecState* exec)
+JSValue* ReadModifyDotNode::evaluate(OldInterpreterExecState* exec)
{
JSValue* baseValue = m_base->evaluate(exec);
KJS_CHECKEXCEPTIONVALUE
@@ -3704,7 +4434,12 @@
// ------------------------------ AssignErrorNode -----------------------------------
-JSValue* AssignErrorNode::evaluate(ExecState* exec)
+RegisterID* AssignErrorNode::emitCode(CodeGenerator& generator, RegisterID*)
+{
+ return emitThrowError(generator, ReferenceError, "Left side of assignment is not a reference.");
+}
+
+JSValue* AssignErrorNode::evaluate(OldInterpreterExecState* exec)
{
throwError(exec, ReferenceError, "Left side of assignment is not a reference.");
handleException(exec);
@@ -3713,14 +4448,24 @@
// ------------------------------ AssignBracketNode -----------------------------------
-void AssignBracketNode::optimizeVariableAccess(ExecState*, const SymbolTable&, const LocalStorage&, NodeStack& nodeStack)
+RegisterID* AssignBracketNode::emitCode(CodeGenerator& generator, RegisterID* dst)
+{
+ RefPtr<RegisterID> base = generator.emitNodeForLeftHandSide(m_base.get(), m_subscriptHasAssignments || m_rightHasAssignments);
+ RefPtr<RegisterID> property = generator.emitNodeForLeftHandSide(m_subscript.get(), m_rightHasAssignments);
+ RefPtr<RegisterID> value = generator.destinationForAssignResult(dst);
+ RegisterID* result = generator.emitNode(value.get(), m_right.get());
+ generator.emitPutByVal(base.get(), property.get(), result);
+ return generator.moveToDestinationIfNeeded(dst, result);
+}
+
+void AssignBracketNode::optimizeVariableAccess(OldInterpreterExecState*, const SymbolTable&, const LocalStorage&, NodeStack& nodeStack)
{
nodeStack.append(m_right.get());
nodeStack.append(m_subscript.get());
nodeStack.append(m_base.get());
}
-JSValue* AssignBracketNode::evaluate(ExecState* exec)
+JSValue* AssignBracketNode::evaluate(OldInterpreterExecState* exec)
{
JSValue* baseValue = m_base->evaluate(exec);
KJS_CHECKEXCEPTIONVALUE
@@ -3745,14 +4490,29 @@
base->put(exec, propertyName, v);
return v;
}
-void ReadModifyBracketNode::optimizeVariableAccess(ExecState*, const SymbolTable&, const LocalStorage&, NodeStack& nodeStack)
+
+RegisterID* ReadModifyBracketNode::emitCode(CodeGenerator& generator, RegisterID* dst)
+{
+ RefPtr<RegisterID> base = generator.emitNodeForLeftHandSide(m_base.get(), m_subscriptHasAssignments || m_rightHasAssignments);
+ RefPtr<RegisterID> property = generator.emitNodeForLeftHandSide(m_subscript.get(), m_rightHasAssignments);
+
+ RefPtr<RegisterID> value = generator.emitGetByVal(generator.tempDestination(dst), base.get(), property.get());
+ RegisterID* change = generator.emitNode(m_right.get());
+ RegisterID* updatedValue = emitReadModifyAssignment(generator, generator.finalDestination(dst, value.get()), value.get(), change, m_operator);
+
+ generator.emitPutByVal(base.get(), property.get(), updatedValue);
+
+ return updatedValue;
+}
+
+void ReadModifyBracketNode::optimizeVariableAccess(OldInterpreterExecState*, const SymbolTable&, const LocalStorage&, NodeStack& nodeStack)
{
nodeStack.append(m_right.get());
nodeStack.append(m_subscript.get());
nodeStack.append(m_base.get());
}
-JSValue* ReadModifyBracketNode::evaluate(ExecState* exec)
+JSValue* ReadModifyBracketNode::evaluate(OldInterpreterExecState* exec)
{
JSValue* baseValue = m_base->evaluate(exec);
KJS_CHECKEXCEPTIONVALUE
@@ -3793,14 +4553,20 @@
// ------------------------------ CommaNode ------------------------------------
-void CommaNode::optimizeVariableAccess(ExecState*, const SymbolTable&, const LocalStorage&, NodeStack& nodeStack)
+RegisterID* CommaNode::emitCode(CodeGenerator& generator, RegisterID* dst)
+{
+ generator.emitNode(m_expr1.get());
+ return generator.emitNode(dst, m_expr2.get());
+}
+
+void CommaNode::optimizeVariableAccess(OldInterpreterExecState*, const SymbolTable&, const LocalStorage&, NodeStack& nodeStack)
{
nodeStack.append(m_expr2.get());
nodeStack.append(m_expr1.get());
}
// ECMA 11.14
-JSValue* CommaNode::evaluate(ExecState* exec)
+JSValue* CommaNode::evaluate(OldInterpreterExecState* exec)
{
m_expr1->evaluate(exec);
KJS_CHECKEXCEPTIONVALUE
@@ -3815,7 +4581,7 @@
{
}
-void ConstDeclNode::optimizeVariableAccess(ExecState*, const SymbolTable&, const LocalStorage&, NodeStack& nodeStack)
+void ConstDeclNode::optimizeVariableAccess(OldInterpreterExecState*, const SymbolTable&, const LocalStorage&, NodeStack& nodeStack)
{
if (m_next)
nodeStack.append(m_next.get());
@@ -3823,7 +4589,7 @@
nodeStack.append(m_init.get());
}
-void ConstDeclNode::handleSlowCase(ExecState* exec, const ScopeChain& chain, JSValue* val)
+void ConstDeclNode::handleSlowCase(OldInterpreterExecState* exec, const ScopeChain& chain, JSValue* val)
{
ScopeChainIterator iter = chain.begin();
ScopeChainIterator end = chain.end();
@@ -3846,14 +4612,12 @@
}
// ECMA 12.2
-inline void ConstDeclNode::evaluateSingle(ExecState* exec)
+inline void ConstDeclNode::evaluateSingle(OldInterpreterExecState* exec)
{
ASSERT(exec->variableObject()->hasOwnProperty(exec, m_ident) || exec->codeType() == EvalCode); // Guaranteed by processDeclarations.
const ScopeChain& chain = exec->scopeChain();
JSVariableObject* variableObject = exec->variableObject();
- ASSERT(!chain.isEmpty());
-
bool inGlobalScope = ++chain.begin() == chain.end();
if (m_init) {
@@ -3878,7 +4642,28 @@
}
}
-JSValue* ConstDeclNode::evaluate(ExecState* exec)
+RegisterID* ConstDeclNode::emitCodeSingle(CodeGenerator& generator)
+{
+ if (RegisterID* local = generator.registerForLocalConstInit(m_ident))
+ return generator.emitNode(local, m_init.get());
+
+ // FIXME: While this code should only be hit in eval code, it will potentially
+ // assign to the wrong base if m_ident exists in an intervening dynamic scope.
+ RefPtr<RegisterID> base = generator.emitResolveBase(generator.newTemporary(), m_ident);
+ RegisterID* value = generator.emitNode(m_init.get());
+ return generator.emitPutById(base.get(), m_ident, value);
+}
+
+RegisterID* ConstDeclNode::emitCode(CodeGenerator& generator, RegisterID*)
+{
+ RegisterID* result = 0;
+ for (ConstDeclNode* n = this; n; n = n->m_next.get())
+ result = n->emitCodeSingle(generator);
+
+ return result;
+}
+
+JSValue* ConstDeclNode::evaluate(OldInterpreterExecState* exec)
{
evaluateSingle(exec);
@@ -3894,14 +4679,19 @@
// ------------------------------ ConstStatementNode -----------------------------
-void ConstStatementNode::optimizeVariableAccess(ExecState*, const SymbolTable&, const LocalStorage&, NodeStack& nodeStack)
+void ConstStatementNode::optimizeVariableAccess(OldInterpreterExecState*, const SymbolTable&, const LocalStorage&, NodeStack& nodeStack)
{
ASSERT(m_next);
nodeStack.append(m_next.get());
}
+RegisterID* ConstStatementNode::emitCode(CodeGenerator& generator, RegisterID*)
+{
+ return generator.emitNode(m_next.get());
+}
+
// ECMA 12.2
-JSValue* ConstStatementNode::execute(ExecState* exec)
+JSValue* ConstStatementNode::execute(OldInterpreterExecState* exec)
{
m_next->evaluate(exec);
KJS_CHECKEXCEPTION
@@ -3911,6 +4701,21 @@
// ------------------------------ Helper functions for handling Vectors of StatementNode -------------------------------
+static inline RegisterID* statementListEmitCode(StatementVector& statements, CodeGenerator& generator, RegisterID* dst = 0)
+{
+ RefPtr<RegisterID> r0 = dst;
+
+ StatementVector::iterator end = statements.end();
+ for (StatementVector::iterator it = statements.begin(); it != end; ++it) {
+ StatementNode* n = it->get();
+ generator.emitDebugHook(WillExecuteStatement, n->firstLine(), n->lastLine());
+ if (RegisterID* r1 = generator.emitNode(dst, n))
+ r0 = r1;
+ }
+
+ return r0.get();
+}
+
static inline void statementListPushFIFO(StatementVector& statements, DeclarationStacks::NodeStack& stack)
{
StatementVector::iterator it = statements.end();
@@ -3938,7 +4743,7 @@
return (*begin).get();
}
-static inline JSValue* statementListExecute(StatementVector& statements, ExecState* exec)
+static inline JSValue* statementListExecute(StatementVector& statements, OldInterpreterExecState* exec)
{
JSValue* value = 0;
size_t size = statements.size();
@@ -3960,35 +4765,51 @@
children->releaseContentsIntoVector(m_children);
}
-void BlockNode::optimizeVariableAccess(ExecState*, const SymbolTable&, const LocalStorage&, NodeStack& nodeStack)
+RegisterID* BlockNode::emitCode(CodeGenerator& generator, RegisterID* dst)
+{
+ return statementListEmitCode(m_children, generator, dst);
+}
+
+void BlockNode::optimizeVariableAccess(OldInterpreterExecState*, const SymbolTable&, const LocalStorage&, NodeStack& nodeStack)
{
statementListPushFIFO(m_children, nodeStack);
}
// ECMA 12.1
-JSValue* BlockNode::execute(ExecState* exec)
+JSValue* BlockNode::execute(OldInterpreterExecState* exec)
{
return statementListExecute(m_children, exec);
}
// ------------------------------ EmptyStatementNode ---------------------------
+RegisterID* EmptyStatementNode::emitCode(CodeGenerator&, RegisterID* dst)
+{
+ return dst;
+}
+
// ECMA 12.3
-JSValue* EmptyStatementNode::execute(ExecState* exec)
+JSValue* EmptyStatementNode::execute(OldInterpreterExecState* exec)
{
return exec->setNormalCompletion();
}
// ------------------------------ ExprStatementNode ----------------------------
-void ExprStatementNode::optimizeVariableAccess(ExecState*, const SymbolTable&, const LocalStorage&, NodeStack& nodeStack)
+RegisterID* ExprStatementNode::emitCode(CodeGenerator& generator, RegisterID* dst)
+{
+ ASSERT(m_expr);
+ return generator.emitNode(dst, m_expr.get());
+}
+
+void ExprStatementNode::optimizeVariableAccess(OldInterpreterExecState*, const SymbolTable&, const LocalStorage&, NodeStack& nodeStack)
{
ASSERT(m_expr);
nodeStack.append(m_expr.get());
}
// ECMA 12.4
-JSValue* ExprStatementNode::execute(ExecState* exec)
+JSValue* ExprStatementNode::execute(OldInterpreterExecState* exec)
{
JSValue* value = m_expr->evaluate(exec);
KJS_CHECKEXCEPTION
@@ -3998,13 +4819,19 @@
// ------------------------------ VarStatementNode ----------------------------
-void VarStatementNode::optimizeVariableAccess(ExecState*, const SymbolTable&, const LocalStorage&, NodeStack& nodeStack)
+RegisterID* VarStatementNode::emitCode(CodeGenerator& generator, RegisterID*)
+{
+ ASSERT(m_expr);
+ return generator.emitNode(m_expr.get());
+}
+
+void VarStatementNode::optimizeVariableAccess(OldInterpreterExecState*, const SymbolTable&, const LocalStorage&, NodeStack& nodeStack)
{
ASSERT(m_expr);
nodeStack.append(m_expr.get());
}
-JSValue* VarStatementNode::execute(ExecState* exec)
+JSValue* VarStatementNode::execute(OldInterpreterExecState* exec)
{
m_expr->evaluate(exec);
KJS_CHECKEXCEPTION
@@ -4014,14 +4841,28 @@
// ------------------------------ IfNode ---------------------------------------
-void IfNode::optimizeVariableAccess(ExecState*, const SymbolTable&, const LocalStorage&, NodeStack& nodeStack)
+RegisterID* IfNode::emitCode(CodeGenerator& generator, RegisterID* dst)
+{
+ RefPtr<LabelID> afterThen = generator.newLabel();
+
+ RegisterID* cond = generator.emitNode(m_condition.get());
+ generator.emitJumpIfFalse(cond, afterThen.get());
+
+ generator.emitNode(dst, m_ifBlock.get());
+ generator.emitLabel(afterThen.get());
+
+ // FIXME: This should return the last statement exectuted so that it can be returned as a Completion
+ return 0;
+}
+
+void IfNode::optimizeVariableAccess(OldInterpreterExecState*, const SymbolTable&, const LocalStorage&, NodeStack& nodeStack)
{
nodeStack.append(m_ifBlock.get());
nodeStack.append(m_condition.get());
}
// ECMA 12.5
-JSValue* IfNode::execute(ExecState* exec)
+JSValue* IfNode::execute(OldInterpreterExecState* exec)
{
bool b = m_condition->evaluateToBoolean(exec);
KJS_CHECKEXCEPTION
@@ -4031,14 +4872,34 @@
return exec->setNormalCompletion();
}
-void IfElseNode::optimizeVariableAccess(ExecState* exec, const SymbolTable& symbolTable, const LocalStorage& localStorage, NodeStack& nodeStack)
+RegisterID* IfElseNode::emitCode(CodeGenerator& generator, RegisterID* dst)
+{
+ RefPtr<LabelID> beforeElse = generator.newLabel();
+ RefPtr<LabelID> afterElse = generator.newLabel();
+
+ RegisterID* cond = generator.emitNode(m_condition.get());
+ generator.emitJumpIfFalse(cond, beforeElse.get());
+
+ generator.emitNode(dst, m_ifBlock.get());
+ generator.emitJump(afterElse.get());
+
+ generator.emitLabel(beforeElse.get());
+ generator.emitNode(dst, m_elseBlock.get());
+
+ generator.emitLabel(afterElse.get());
+
+ // FIXME: This should return the last statement exectuted so that it can be returned as a Completion
+ return 0;
+}
+
+void IfElseNode::optimizeVariableAccess(OldInterpreterExecState* exec, const SymbolTable& symbolTable, const LocalStorage& localStorage, NodeStack& nodeStack)
{
nodeStack.append(m_elseBlock.get());
IfNode::optimizeVariableAccess(exec, symbolTable, localStorage, nodeStack);
}
// ECMA 12.5
-JSValue* IfElseNode::execute(ExecState* exec)
+JSValue* IfElseNode::execute(OldInterpreterExecState* exec)
{
bool b = m_condition->evaluateToBoolean(exec);
KJS_CHECKEXCEPTION
@@ -4050,14 +4911,33 @@
// ------------------------------ DoWhileNode ----------------------------------
-void DoWhileNode::optimizeVariableAccess(ExecState*, const SymbolTable&, const LocalStorage&, NodeStack& nodeStack)
+RegisterID* DoWhileNode::emitCode(CodeGenerator& generator, RegisterID* dst)
+{
+ RefPtr<LabelID> topOfLoop = generator.newLabel();
+ generator.emitLabel(topOfLoop.get());
+
+ RefPtr<LabelID> continueTarget = generator.newLabel();
+ RefPtr<LabelID> breakTarget = generator.newLabel();
+
+ generator.pushJumpContext(&m_labelStack, continueTarget.get(), breakTarget.get(), true);
+ RefPtr<RegisterID> result = generator.emitNode(dst, m_statement.get());
+ generator.popJumpContext();
+
+ generator.emitLabel(continueTarget.get());
+ RegisterID* cond = generator.emitNode(m_expr.get());
+ generator.emitJumpIfTrue(cond, topOfLoop.get());
+ generator.emitLabel(breakTarget.get());
+ return result.get();
+}
+
+void DoWhileNode::optimizeVariableAccess(OldInterpreterExecState*, const SymbolTable&, const LocalStorage&, NodeStack& nodeStack)
{
nodeStack.append(m_statement.get());
nodeStack.append(m_expr.get());
}
// ECMA 12.6.1
-JSValue* DoWhileNode::execute(ExecState* exec)
+JSValue* DoWhileNode::execute(OldInterpreterExecState* exec)
{
JSValue* value = 0;
@@ -4092,14 +4972,37 @@
// ------------------------------ WhileNode ------------------------------------
-void WhileNode::optimizeVariableAccess(ExecState*, const SymbolTable&, const LocalStorage&, NodeStack& nodeStack)
+RegisterID* WhileNode::emitCode(CodeGenerator& generator, RegisterID* dst)
+{
+ RefPtr<LabelID> topOfLoop = generator.newLabel();
+ RefPtr<LabelID> continueTarget = generator.newLabel();
+ RefPtr<LabelID> breakTarget = generator.newLabel();
+
+ generator.emitJump(continueTarget.get());
+ generator.emitLabel(topOfLoop.get());
+
+ generator.pushJumpContext(&m_labelStack, continueTarget.get(), breakTarget.get(), true);
+ generator.emitNode(dst, m_statement.get());
+ generator.popJumpContext();
+
+ generator.emitLabel(continueTarget.get());
+ RegisterID* cond = generator.emitNode(m_expr.get());
+ generator.emitJumpIfTrue(cond, topOfLoop.get());
+
+ generator.emitLabel(breakTarget.get());
+
+ // FIXME: This should return the last statement executed so that it can be returned as a Completion
+ return 0;
+}
+
+void WhileNode::optimizeVariableAccess(OldInterpreterExecState*, const SymbolTable&, const LocalStorage&, NodeStack& nodeStack)
{
nodeStack.append(m_statement.get());
nodeStack.append(m_expr.get());
}
// ECMA 12.6.2
-JSValue* WhileNode::execute(ExecState* exec)
+JSValue* WhileNode::execute(OldInterpreterExecState* exec)
{
JSValue* value = 0;
@@ -4133,7 +5036,31 @@
// ------------------------------ ForNode --------------------------------------
-void ForNode::optimizeVariableAccess(ExecState*, const SymbolTable&, const LocalStorage&, NodeStack& nodeStack)
+RegisterID* ForNode::emitCode(CodeGenerator& generator, RegisterID* dst)
+{
+ generator.emitNode(m_expr1.get());
+
+ RefPtr<LabelID> topOfLoop = generator.newLabel();
+ RefPtr<LabelID> beforeCondition = generator.newLabel();
+ RefPtr<LabelID> continueTarget = generator.newLabel();
+ RefPtr<LabelID> breakTarget = generator.newLabel();
+ generator.emitJump(beforeCondition.get());
+
+ generator.emitLabel(topOfLoop.get());
+ generator.pushJumpContext(&m_labelStack, continueTarget.get(), breakTarget.get(), true);
+ RefPtr<RegisterID> result = generator.emitNode(dst, m_statement.get());
+ generator.popJumpContext();
+ generator.emitLabel(continueTarget.get());
+ generator.emitNode(m_expr3.get());
+
+ generator.emitLabel(beforeCondition.get());
+ RegisterID* cond = generator.emitNode(m_expr2.get());
+ generator.emitJumpIfTrue(cond, topOfLoop.get());
+ generator.emitLabel(breakTarget.get());
+ return result.get();
+}
+
+void ForNode::optimizeVariableAccess(OldInterpreterExecState*, const SymbolTable&, const LocalStorage&, NodeStack& nodeStack)
{
nodeStack.append(m_statement.get());
nodeStack.append(m_expr3.get());
@@ -4142,7 +5069,7 @@
}
// ECMA 12.6.3
-JSValue* ForNode::execute(ExecState* exec)
+JSValue* ForNode::execute(OldInterpreterExecState* exec)
{
JSValue* value = 0;
@@ -4199,11 +5126,11 @@
, m_identIsVarDecl(true)
{
if (in)
- m_init = new AssignResolveNode(ident, in);
+ m_init = new AssignResolveNode(ident, in, true);
// for( var foo = bar in baz )
}
-void ForInNode::optimizeVariableAccess(ExecState*, const SymbolTable&, const LocalStorage&, NodeStack& nodeStack)
+void ForInNode::optimizeVariableAccess(OldInterpreterExecState*, const SymbolTable&, const LocalStorage&, NodeStack& nodeStack)
{
nodeStack.append(m_statement.get());
nodeStack.append(m_expr.get());
@@ -4212,8 +5139,57 @@
nodeStack.append(m_init.get());
}
+RegisterID* ForInNode::emitCode(CodeGenerator& generator, RegisterID* dst)
+{
+ RefPtr<LabelID> loopStart = generator.newLabel();
+ RefPtr<LabelID> continueTarget = generator.newLabel();
+ RefPtr<LabelID> breakTarget = generator.newLabel();
+
+ if (m_init)
+ generator.emitNode(m_init.get());
+ RegisterID* forInBase = generator.emitNode(m_expr.get());
+ RefPtr<RegisterID> iter = generator.emitGetPropertyNames(generator.newTemporary(), forInBase);
+ generator.emitJump(continueTarget.get());
+ generator.emitLabel(loopStart.get());
+ RegisterID* propertyName;
+ if (m_lexpr->isResolveNode()) {
+ const Identifier& ident = static_cast<ResolveNode*>(m_lexpr.get())->identifier();
+ propertyName = generator.registerForLocal(ident);
+ if (!propertyName) {
+ propertyName = generator.newTemporary();
+ RefPtr<RegisterID> protect = propertyName;
+ RegisterID* base = generator.emitResolveBase(generator.newTemporary(), ident);
+ generator.emitPutById(base, ident, propertyName);
+ }
+ } else if (m_lexpr->isDotAccessorNode()) {
+ DotAccessorNode* assignNode = static_cast<DotAccessorNode*>(m_lexpr.get());
+ const Identifier& ident = assignNode->identifier();
+ propertyName = generator.newTemporary();
+ RefPtr<RegisterID> protect = propertyName;
+ RegisterID* base = generator.emitNode(assignNode->base());
+ generator.emitPutById(base, ident, propertyName);
+ } else {
+ ASSERT(m_lexpr->isBracketAccessorNode());
+ BracketAccessorNode* assignNode = static_cast<BracketAccessorNode*>(m_lexpr.get());
+ propertyName = generator.newTemporary();
+ RefPtr<RegisterID> protect = propertyName;
+ RefPtr<RegisterID> base = generator.emitNode(assignNode->base());
+ RegisterID* subscript = generator.emitNode(assignNode->subscript());
+ generator.emitPutByVal(base.get(), subscript, propertyName);
+ }
+
+ generator.pushJumpContext(&m_labelStack, continueTarget.get(), breakTarget.get(), true);
+ generator.emitNode(dst, m_statement.get());
+ generator.popJumpContext();
+
+ generator.emitLabel(continueTarget.get());
+ generator.emitNextPropertyName(propertyName, iter.get(), loopStart.get());
+ generator.emitLabel(breakTarget.get());
+ return dst;
+}
+
// ECMA 12.6.4
-JSValue* ForInNode::execute(ExecState* exec)
+JSValue* ForInNode::execute(OldInterpreterExecState* exec)
{
JSValue* value = 0;
@@ -4312,7 +5288,29 @@
// ------------------------------ ContinueNode ---------------------------------
// ECMA 12.7
-JSValue* ContinueNode::execute(ExecState* exec)
+RegisterID* ContinueNode::emitCode(CodeGenerator& generator, RegisterID* dst)
+{
+ if (!generator.inContinueContext())
+ return emitThrowError(generator, SyntaxError, "Invalid continue statement.");
+
+ JumpContext* targetContext = generator.jumpContextForContinue(m_ident);
+
+ if (!targetContext) {
+ if (m_ident.isEmpty())
+ return emitThrowError(generator, SyntaxError, "Invalid continue statement.");
+ else
+ return emitThrowError(generator, SyntaxError, "Label %s not found.", m_ident);
+ }
+
+ if (!targetContext->continueTarget)
+ return emitThrowError(generator, SyntaxError, "Invalid continue statement.");
+
+ generator.emitJumpScopes(targetContext->continueTarget, targetContext->scopeDepth);
+
+ return dst;
+}
+
+JSValue* ContinueNode::execute(OldInterpreterExecState* exec)
{
if (m_ident.isEmpty() && !exec->inIteration())
return setErrorCompletion(exec, SyntaxError, "Invalid continue statement.");
@@ -4324,7 +5322,28 @@
// ------------------------------ BreakNode ------------------------------------
// ECMA 12.8
-JSValue* BreakNode::execute(ExecState* exec)
+RegisterID* BreakNode::emitCode(CodeGenerator& generator, RegisterID* dst)
+{
+ if (!generator.inJumpContext())
+ return emitThrowError(generator, SyntaxError, "Invalid break statement.");
+
+ JumpContext* targetContext = generator.jumpContextForBreak(m_ident);
+
+ if (!targetContext) {
+ if (m_ident.isEmpty())
+ return emitThrowError(generator, SyntaxError, "Invalid break statement.");
+ else
+ return emitThrowError(generator, SyntaxError, "Label %s not found.", m_ident);
+ }
+
+ ASSERT(targetContext->breakTarget);
+
+ generator.emitJumpScopes(targetContext->breakTarget, targetContext->scopeDepth);
+
+ return dst;
+}
+
+JSValue* BreakNode::execute(OldInterpreterExecState* exec)
{
if (m_ident.isEmpty() && !exec->inIteration() && !exec->inSwitch())
return setErrorCompletion(exec, SyntaxError, "Invalid break statement.");
@@ -4335,14 +5354,29 @@
// ------------------------------ ReturnNode -----------------------------------
-void ReturnNode::optimizeVariableAccess(ExecState*, const SymbolTable&, const LocalStorage&, NodeStack& nodeStack)
+RegisterID* ReturnNode::emitCode(CodeGenerator& generator, RegisterID* dst)
+{
+ if (generator.codeType() != FunctionCode)
+ return emitThrowError(generator, SyntaxError, "Invalid return statement.");
+
+ RegisterID* r0 = m_value ? generator.emitNode(dst, m_value.get()) : generator.emitLoad(generator.finalDestination(dst), jsUndefined());
+ if (generator.scopeDepth()) {
+ RefPtr<LabelID> l0 = generator.newLabel();
+ generator.emitJumpScopes(l0.get(), 0);
+ generator.emitLabel(l0.get());
+ }
+ generator.emitDebugHook(WillLeaveCallFrame, firstLine(), lastLine());
+ return generator.emitReturn(r0);
+}
+
+void ReturnNode::optimizeVariableAccess(OldInterpreterExecState*, const SymbolTable&, const LocalStorage&, NodeStack& nodeStack)
{
if (m_value)
nodeStack.append(m_value.get());
}
// ECMA 12.9
-JSValue* ReturnNode::execute(ExecState* exec)
+JSValue* ReturnNode::execute(OldInterpreterExecState* exec)
{
CodeType codeType = exec->codeType();
if (codeType != FunctionCode)
@@ -4359,30 +5393,31 @@
// ------------------------------ WithNode -------------------------------------
-void WithNode::optimizeVariableAccess(ExecState*, const SymbolTable&, const LocalStorage&, NodeStack& nodeStack)
+RegisterID* WithNode::emitCode(CodeGenerator& generator, RegisterID* dst)
+{
+ RegisterID* scope = generator.emitNode(m_expr.get());
+ generator.emitPushScope(scope);
+ RegisterID* result = generator.emitNode(dst, m_statement.get());
+ generator.emitPopScope();
+ return result;
+}
+
+void WithNode::optimizeVariableAccess(OldInterpreterExecState*, const SymbolTable&, const LocalStorage&, NodeStack& nodeStack)
{
// Can't optimize within statement because "with" introduces a dynamic scope.
nodeStack.append(m_expr.get());
}
// ECMA 12.10
-JSValue* WithNode::execute(ExecState* exec)
+JSValue* WithNode::execute(OldInterpreterExecState*)
{
- JSValue* v = m_expr->evaluate(exec);
- KJS_CHECKEXCEPTION
- JSObject* o = v->toObject(exec);
- KJS_CHECKEXCEPTION
- exec->dynamicGlobalObject()->tearOffActivation(exec);
- exec->pushScope(o);
- JSValue* value = m_statement->execute(exec);
- exec->popScope();
-
- return value;
+ ASSERT_NOT_REACHED();
+ return 0;
}
// ------------------------------ CaseClauseNode -------------------------------
-void CaseClauseNode::optimizeVariableAccess(ExecState*, const SymbolTable&, const LocalStorage&, NodeStack& nodeStack)
+void CaseClauseNode::optimizeVariableAccess(OldInterpreterExecState*, const SymbolTable&, const LocalStorage&, NodeStack& nodeStack)
{
if (m_expr)
nodeStack.append(m_expr.get());
@@ -4390,7 +5425,7 @@
}
// ECMA 12.11
-JSValue* CaseClauseNode::evaluate(ExecState* exec)
+JSValue* CaseClauseNode::evaluate(OldInterpreterExecState* exec)
{
JSValue* v = m_expr->evaluate(exec);
KJS_CHECKEXCEPTIONVALUE
@@ -4399,14 +5434,14 @@
}
// ECMA 12.11
-JSValue* CaseClauseNode::executeStatements(ExecState* exec)
+JSValue* CaseClauseNode::executeStatements(OldInterpreterExecState* exec)
{
return statementListExecute(m_children, exec);
}
// ------------------------------ ClauseListNode -------------------------------
-void ClauseListNode::optimizeVariableAccess(ExecState*, const SymbolTable&, const LocalStorage&, NodeStack& nodeStack)
+void ClauseListNode::optimizeVariableAccess(OldInterpreterExecState*, const SymbolTable&, const LocalStorage&, NodeStack& nodeStack)
{
if (m_next)
nodeStack.append(m_next.get());
@@ -4415,14 +5450,55 @@
// ------------------------------ CaseBlockNode --------------------------------
-CaseBlockNode::CaseBlockNode(ClauseListNode* list1, CaseClauseNode* defaultClause, ClauseListNode* list2)
- : m_list1(list1)
- , m_defaultClause(defaultClause)
- , m_list2(list2)
+RegisterID* CaseBlockNode::emitCodeForBlock(CodeGenerator& generator, RegisterID* switchExpression, RegisterID* dst)
{
+ Vector<RefPtr<LabelID>, 8> labelVector;
+
+ // Setup jumps
+ for (ClauseListNode* list = m_list1.get(); list; list = list->getNext()) {
+ RegisterID* clauseVal = generator.emitNode(list->getClause()->expr());
+ generator.emitStrictEqual(clauseVal, clauseVal, switchExpression);
+ labelVector.append(generator.newLabel());
+ generator.emitJumpIfTrue(clauseVal, labelVector[labelVector.size() - 1].get());
+ }
+
+ for (ClauseListNode* list = m_list2.get(); list; list = list->getNext()) {
+ RegisterID* clauseVal = generator.emitNode(list->getClause()->expr());
+ generator.emitStrictEqual(clauseVal, clauseVal, switchExpression);
+ labelVector.append(generator.newLabel());
+ generator.emitJumpIfTrue(clauseVal, labelVector[labelVector.size() - 1].get());
+ }
+
+ RefPtr<LabelID> defaultLabel;
+ defaultLabel = generator.newLabel();
+ generator.emitJump(defaultLabel.get());
+
+ RegisterID* result = 0;
+
+ size_t i = 0;
+ for (ClauseListNode* list = m_list1.get(); list; list = list->getNext()) {
+ generator.emitLabel(labelVector[i++].get());
+ result = statementListEmitCode(list->getClause()->children(), generator, dst);
+ }
+
+ if (m_defaultClause) {
+ generator.emitLabel(defaultLabel.get());
+ result = statementListEmitCode(m_defaultClause->children(), generator, dst);
+ }
+
+ for (ClauseListNode* list = m_list2.get(); list; list = list->getNext()) {
+ generator.emitLabel(labelVector[i++].get());
+ result = statementListEmitCode(list->getClause()->children(), generator, dst);
+ }
+ if (!m_defaultClause)
+ generator.emitLabel(defaultLabel.get());
+
+ ASSERT(i == labelVector.size());
+
+ return result;
}
-void CaseBlockNode::optimizeVariableAccess(ExecState*, const SymbolTable&, const LocalStorage&, NodeStack& nodeStack)
+void CaseBlockNode::optimizeVariableAccess(OldInterpreterExecState*, const SymbolTable&, const LocalStorage&, NodeStack& nodeStack)
{
if (m_list2)
nodeStack.append(m_list2.get());
@@ -4433,7 +5509,7 @@
}
// ECMA 12.11
-JSValue* CaseBlockNode::executeBlock(ExecState* exec, JSValue* input)
+JSValue* CaseBlockNode::executeBlock(OldInterpreterExecState* exec, JSValue* input)
{
ClauseListNode* a = m_list1.get();
while (a) {
@@ -4441,7 +5517,7 @@
a = a->getNext();
JSValue* v = clause->evaluate(exec);
KJS_CHECKEXCEPTION
- if (strictEqual(exec, input, v)) {
+ if (strictEqual(input, v)) {
JSValue* res = clause->executeStatements(exec);
if (exec->completionType() != Normal)
return res;
@@ -4460,7 +5536,7 @@
b = b->getNext();
JSValue* v = clause->evaluate(exec);
KJS_CHECKEXCEPTION
- if (strictEqual(exec, input, v)) {
+ if (strictEqual(input, v)) {
JSValue* res = clause->executeStatements(exec);
if (exec->completionType() != Normal)
return res;
@@ -4492,14 +5568,28 @@
// ------------------------------ SwitchNode -----------------------------------
-void SwitchNode::optimizeVariableAccess(ExecState*, const SymbolTable&, const LocalStorage&, NodeStack& nodeStack)
+RegisterID* SwitchNode::emitCode(CodeGenerator& generator, RegisterID* dst)
+{
+ RefPtr<LabelID> breakTarget = generator.newLabel();
+
+ RefPtr<RegisterID> r0 = generator.emitNode(m_expr.get());
+ generator.pushJumpContext(&m_labelStack, 0, breakTarget.get(), true);
+ RegisterID* r1 = m_block->emitCodeForBlock(generator, r0.get(), dst);
+ generator.popJumpContext();
+
+ generator.emitLabel(breakTarget.get());
+
+ return r1;
+}
+
+void SwitchNode::optimizeVariableAccess(OldInterpreterExecState*, const SymbolTable&, const LocalStorage&, NodeStack& nodeStack)
{
nodeStack.append(m_block.get());
nodeStack.append(m_expr.get());
}
// ECMA 12.11
-JSValue* SwitchNode::execute(ExecState* exec)
+JSValue* SwitchNode::execute(OldInterpreterExecState* exec)
{
JSValue* v = m_expr->evaluate(exec);
KJS_CHECKEXCEPTION
@@ -4514,14 +5604,31 @@
}
// ------------------------------ LabelNode ------------------------------------
+RegisterID* LabelNode::emitCode(CodeGenerator& generator, RegisterID* dst)
+{
+ if (generator.jumpContextForBreak(m_label))
+ return emitThrowError(generator, SyntaxError, "Duplicated label %s found.", m_label);
+
+ RefPtr<LabelID> l0 = generator.newLabel();
+ m_labelStack.push(m_label);
+ generator.pushJumpContext(&m_labelStack, 0, l0.get(), false);
+
+ RegisterID* r0 = generator.emitNode(dst, m_statement.get());
+
+ generator.popJumpContext();
+ m_labelStack.pop();
+
+ generator.emitLabel(l0.get());
+ return r0;
+}
-void LabelNode::optimizeVariableAccess(ExecState*, const SymbolTable&, const LocalStorage&, NodeStack& nodeStack)
+void LabelNode::optimizeVariableAccess(OldInterpreterExecState*, const SymbolTable&, const LocalStorage&, NodeStack& nodeStack)
{
nodeStack.append(m_statement.get());
}
// ECMA 12.12
-JSValue* LabelNode::execute(ExecState* exec)
+JSValue* LabelNode::execute(OldInterpreterExecState* exec)
{
if (!exec->seenLabels().push(m_label))
return setErrorCompletion(exec, SyntaxError, "Duplicated label %s found.", m_label);
@@ -4535,13 +5642,19 @@
// ------------------------------ ThrowNode ------------------------------------
-void ThrowNode::optimizeVariableAccess(ExecState*, const SymbolTable&, const LocalStorage&, NodeStack& nodeStack)
+RegisterID* ThrowNode::emitCode(CodeGenerator& generator, RegisterID* dst)
+{
+ generator.emitThrow(generator.emitNode(dst, m_expr.get()));
+ return dst;
+}
+
+void ThrowNode::optimizeVariableAccess(OldInterpreterExecState*, const SymbolTable&, const LocalStorage&, NodeStack& nodeStack)
{
nodeStack.append(m_expr.get());
}
// ECMA 12.13
-JSValue* ThrowNode::execute(ExecState* exec)
+JSValue* ThrowNode::execute(OldInterpreterExecState* exec)
{
JSValue* v = m_expr->evaluate(exec);
KJS_CHECKEXCEPTION
@@ -4552,7 +5665,58 @@
// ------------------------------ TryNode --------------------------------------
-void TryNode::optimizeVariableAccess(ExecState*, const SymbolTable&, const LocalStorage&, NodeStack& nodeStack)
+RegisterID* TryNode::emitCode(CodeGenerator& generator, RegisterID* dst)
+{
+ RefPtr<LabelID> tryStartLabel = generator.newLabel();
+ RefPtr<LabelID> tryEndLabel = generator.newLabel();
+ RefPtr<LabelID> finallyStart;
+ RefPtr<RegisterID> finallyReturnAddr;
+ if (m_finallyBlock) {
+ finallyStart = generator.newLabel();
+ finallyReturnAddr = generator.newTemporary();
+ generator.pushFinallyContext(finallyStart.get(), finallyReturnAddr.get());
+ }
+ generator.emitLabel(tryStartLabel.get());
+ generator.emitNode(dst, m_tryBlock.get());
+ generator.emitLabel(tryEndLabel.get());
+
+ if (m_catchBlock) {
+ RefPtr<LabelID> handlerEndLabel = generator.newLabel();
+ generator.emitJump(handlerEndLabel.get());
+ RefPtr<RegisterID> exceptionRegister = generator.emitCatch(generator.newTemporary(), tryStartLabel.get(), tryEndLabel.get());
+ RegisterID* newScope = generator.emitNewObject(generator.newTemporary());
+ generator.emitPutById(newScope, m_exceptionIdent, exceptionRegister.get());
+ exceptionRegister = 0; // Release register used for temporaries
+ generator.emitPushScope(newScope);
+ generator.emitNode(dst, m_catchBlock.get());
+ generator.emitPopScope();
+ generator.emitLabel(handlerEndLabel.get());
+ }
+
+ if (m_finallyBlock) {
+ generator.popFinallyContext();
+ RefPtr<LabelID> finallyEndLabel = generator.newLabel();
+ generator.emitJumpSubroutine(finallyReturnAddr.get(), finallyStart.get());
+ generator.emitJump(finallyEndLabel.get());
+
+ // Finally block for exception path
+ RefPtr<RegisterID> tempExceptionRegister = generator.emitCatch(generator.newTemporary(), tryStartLabel.get(), generator.emitLabel(generator.newLabel().get()).get());
+ generator.emitJumpSubroutine(finallyReturnAddr.get(), finallyStart.get());
+ generator.emitThrow(tempExceptionRegister.get());
+
+ // emit the finally block itself
+ generator.emitLabel(finallyStart.get());
+ generator.emitNode(dst, m_finallyBlock.get());
+ generator.emitSubroutineReturn(finallyReturnAddr.get());
+
+ generator.emitLabel(finallyEndLabel.get());
+ }
+
+ return dst;
+}
+
+
+void TryNode::optimizeVariableAccess(OldInterpreterExecState*, const SymbolTable&, const LocalStorage&, NodeStack& nodeStack)
{
// Can't optimize within catchBlock because "catch" introduces a dynamic scope.
if (m_finallyBlock)
@@ -4561,29 +5725,10 @@
}
// ECMA 12.14
-JSValue* TryNode::execute(ExecState* exec)
+JSValue* TryNode::execute(OldInterpreterExecState*)
{
- JSValue* result = m_tryBlock->execute(exec);
-
- if (m_catchBlock && exec->completionType() == Throw) {
- JSObject* obj = new JSObject;
- obj->putDirect(m_exceptionIdent, result, DontDelete);
- exec->dynamicGlobalObject()->tearOffActivation(exec);
- exec->pushScope(obj);
- result = m_catchBlock->execute(exec);
- exec->popScope();
- }
-
- if (m_finallyBlock) {
- ComplType savedCompletionType = exec->completionType();
- JSValue* finallyResult = m_finallyBlock->execute(exec);
- if (exec->completionType() != Normal)
- result = finallyResult;
- else
- exec->setCompletionType(savedCompletionType);
- }
-
- return result;
+ ASSERT_NOT_REACHED();
+ return 0;
}
// ------------------------------ FunctionBodyNode -----------------------------
@@ -4608,6 +5753,10 @@
{
}
+ProgramNode::~ProgramNode()
+{
+}
+
ProgramNode* ProgramNode::create(SourceElements* children, VarStack* varStack, FunctionStack* funcStack, bool usesEval, bool needsClosure)
{
return new ProgramNode(children, varStack, funcStack, usesEval, needsClosure);
@@ -4620,6 +5769,33 @@
{
}
+EvalNode::~EvalNode()
+{
+}
+
+RegisterID* EvalNode::emitCode(CodeGenerator& generator, RegisterID*)
+{
+ RefPtr<RegisterID> dstRegister = generator.newTemporary();
+ generator.emitLoad(dstRegister.get(), jsUndefined());
+ statementListEmitCode(m_children, generator, dstRegister.get());
+ generator.emitEnd(dstRegister.get());
+ return 0;
+}
+
+void EvalNode::generateCode(ScopeChainNode* sc)
+{
+ ScopeChain scopeChain(sc);
+ JSGlobalObject* globalObject = static_cast<JSGlobalObject*>(scopeChain.bottom());
+ ASSERT(globalObject->isGlobalObject());
+
+ m_code.set(new EvalCodeBlock(this, globalObject));
+
+ CodeGenerator generator(this, globalObject->debugger(), scopeChain, new SymbolTable(), m_code.get(), m_varStack, m_functionStack);
+ generator.generate();
+
+ m_children.shrinkCapacity(0);
+}
+
EvalNode* EvalNode::create(SourceElements* children, VarStack* varStack, FunctionStack* funcStack, bool usesEval, bool needsClosure)
{
return new EvalNode(children, varStack, funcStack, usesEval, needsClosure);
@@ -4629,45 +5805,74 @@
FunctionBodyNode::FunctionBodyNode(SourceElements* children, VarStack* varStack, FunctionStack* funcStack, bool usesEval, bool needsClosure)
: ScopeNode(children, varStack, funcStack, usesEval, needsClosure)
- , m_initialized(false)
{
}
+FunctionBodyNode::~FunctionBodyNode()
+{
+}
+
+void FunctionBodyNode::mark()
+{
+ if (m_code)
+ m_code->mark();
+}
+
FunctionBodyNode* FunctionBodyNode::create(SourceElements* children, VarStack* varStack, FunctionStack* funcStack, bool usesEval, bool needsClosure)
{
- if (Debugger::debuggersPresent)
- return new FunctionBodyNodeWithDebuggerHooks(children, varStack, funcStack, usesEval, needsClosure);
return new FunctionBodyNode(children, varStack, funcStack, usesEval, needsClosure);
}
-void FunctionBodyNode::initializeSymbolTable(ExecState* exec)
+void FunctionBodyNode::generateCode(ScopeChainNode* sc)
{
- SymbolTable& symbolTable = exec->variableObject()->symbolTable();
- ASSERT(symbolTable.isEmpty());
+ m_code.set(new CodeBlock(this));
- size_t localStorageIndex = 0;
+ ScopeChain scopeChain(sc);
+ JSGlobalObject* globalObject = static_cast<JSGlobalObject*>(scopeChain.bottom());
+ ASSERT(globalObject->isGlobalObject());
- // Order must match the order in processDeclarations.
+ CodeGenerator generator(this, globalObject->debugger(), scopeChain, &m_symbolTable, m_code.get(), m_varStack, m_functionStack, m_parameters);
+ generator.generate();
- for (size_t i = 0, size = m_parameters.size(); i < size; ++i, ++localStorageIndex) {
- UString::Rep* rep = m_parameters[i].ustring().rep();
- symbolTable.set(rep, localStorageIndex);
- }
-
- for (size_t i = 0, size = m_functionStack.size(); i < size; ++i, ++localStorageIndex) {
- UString::Rep* rep = m_functionStack[i]->m_ident.ustring().rep();
- symbolTable.set(rep, localStorageIndex);
- }
-
- for (size_t i = 0, size = m_varStack.size(); i < size; ++i, ++localStorageIndex) {
- Identifier& ident = m_varStack[i].first;
- if (ident == exec->propertyNames().arguments)
- continue;
- symbolTable.add(ident.ustring().rep(), localStorageIndex);
- }
+ m_children.shrinkCapacity(0);
}
-void ProgramNode::initializeSymbolTable(ExecState* exec)
+RegisterID* FunctionBodyNode::emitCode(CodeGenerator& generator, RegisterID*)
+{
+ generator.emitDebugHook(DidEnterCallFrame, firstLine(), lastLine());
+ statementListEmitCode(m_children, generator);
+ if (!m_children.size() || !m_children.last()->isReturnNode()) {
+ RegisterID* r0 = generator.emitLoad(generator.newTemporary(), jsUndefined());
+ generator.emitDebugHook(WillLeaveCallFrame, firstLine(), lastLine());
+ generator.emitReturn(r0);
+ }
+ return 0;
+}
+
+RegisterID* ProgramNode::emitCode(CodeGenerator& generator, RegisterID*)
+{
+ RefPtr<RegisterID> dstRegister = generator.newTemporary();
+ generator.emitLoad(dstRegister.get(), jsUndefined());
+ statementListEmitCode(m_children, generator, dstRegister.get());
+ generator.emitEnd(dstRegister.get());
+ return 0;
+}
+
+void ProgramNode::generateCode(ScopeChainNode* sc, bool canCreateGlobals)
+{
+ ScopeChain scopeChain(sc);
+ JSGlobalObject* globalObject = static_cast<JSGlobalObject*>(scopeChain.bottom());
+ ASSERT(globalObject->isGlobalObject());
+
+ m_code.set(new ProgramCodeBlock(this, globalObject));
+
+ CodeGenerator generator(this, globalObject->debugger(), scopeChain, &globalObject->symbolTable(), m_code.get(), m_varStack, m_functionStack, canCreateGlobals);
+ generator.generate();
+
+ m_children.shrinkCapacity(0);
+}
+
+void ProgramNode::initializeSymbolTable(OldInterpreterExecState* exec)
{
// If a previous script defined a symbol with the same name as one of our
// symbols, to avoid breaking previously optimized nodes, we need to reuse
@@ -4688,7 +5893,7 @@
for (size_t i = 0; i < size; ++i) {
UString::Rep* rep = m_functionStack[i]->m_ident.ustring().rep();
pair<SymbolTable::iterator, bool> result = symbolTable.add(rep, localStorageIndex);
- m_functionIndexes[i] = result.first->second;
+ m_functionIndexes[i] = result.first->second.getIndex();
if (result.second)
++localStorageIndex;
}
@@ -4709,12 +5914,12 @@
continue;
}
- m_varIndexes[i] = result.first->second;
+ m_varIndexes[i] = result.first->second.getIndex();
++localStorageIndex;
}
}
-void ScopeNode::optimizeVariableAccess(ExecState* exec)
+void ScopeNode::optimizeVariableAccess(OldInterpreterExecState* exec)
{
NodeStack nodeStack;
Node* node = statementListInitializeVariableAccessStack(m_children, nodeStack);
@@ -4722,7 +5927,8 @@
return;
const SymbolTable& symbolTable = exec->variableObject()->symbolTable();
- const LocalStorage& localStorage = exec->variableObject()->localStorage();
+ ASSERT_NOT_REACHED();
+ const LocalStorage localStorage;
while (true) {
node->optimizeVariableAccess(exec, symbolTable, localStorage, nodeStack);
@@ -4735,55 +5941,12 @@
}
}
-void FunctionBodyNode::processDeclarations(ExecState* exec)
-{
- if (!m_initialized)
- initializeSymbolTable(exec);
-
- if (!m_functionStack.isEmpty())
- exec->dynamicGlobalObject()->tearOffActivation(exec);
-
- LocalStorage& localStorage = exec->variableObject()->localStorage();
-
- // We can't just resize localStorage here because that would temporarily
- // leave uninitialized entries, which would crash GC during the mark phase.
- size_t totalSize = m_varStack.size() + m_parameters.size() + m_functionStack.size();
- if (totalSize > localStorage.capacity()) // Doing this check inline avoids function call overhead.
- localStorage.reserveCapacity(totalSize);
-
- int minAttributes = DontDelete;
-
- // In order for our localStorage indexes to be correct, we must match the
- // order of addition in initializeSymbolTable().
-
- const List& args = *exec->arguments();
- for (size_t i = 0, size = m_parameters.size(); i < size; ++i)
- localStorage.uncheckedAppend(LocalStorageEntry(args[i], DontDelete));
-
- for (size_t i = 0, size = m_functionStack.size(); i < size; ++i) {
- FuncDeclNode* node = m_functionStack[i];
- localStorage.uncheckedAppend(LocalStorageEntry(node->makeFunction(exec), minAttributes));
- }
-
- for (size_t i = 0, size = m_varStack.size(); i < size; ++i) {
- int attributes = minAttributes;
- if (m_varStack[i].second & DeclarationStacks::IsConstant)
- attributes |= ReadOnly;
- localStorage.uncheckedAppend(LocalStorageEntry(jsUndefined(), attributes));
- }
-
- if (!m_initialized) {
- optimizeVariableAccess(exec);
- m_initialized = true;
- }
-}
-
static void gccIsCrazy() KJS_FAST_CALL;
static void gccIsCrazy()
{
}
-void ProgramNode::processDeclarations(ExecState* exec)
+void ProgramNode::processDeclarations(OldInterpreterExecState* exec)
{
// If you remove this call, some SunSpider tests, including
// bitops-nsieve-bits.js, will regress substantially on Mac, due to a ~40%
@@ -4792,7 +5955,8 @@
initializeSymbolTable(exec);
- LocalStorage& localStorage = exec->variableObject()->localStorage();
+ ASSERT_NOT_REACHED();
+ LocalStorage localStorage;
// We can't just resize localStorage here because that would temporarily
// leave uninitialized entries, which would crash GC during the mark phase.
@@ -4805,7 +5969,7 @@
for (size_t i = 0, size = m_functionStack.size(); i < size; ++i) {
FuncDeclNode* node = m_functionStack[i];
- LocalStorageEntry entry = LocalStorageEntry(node->makeFunction(exec), minAttributes);
+ LocalStorageEntry entry = LocalStorageEntry(node->makeFunction(exec, exec->scopeChain().node()), minAttributes);
size_t index = m_functionIndexes[i];
if (index == localStorage.size())
@@ -4817,7 +5981,7 @@
}
for (size_t i = 0, size = m_varStack.size(); i < size; ++i) {
- size_t index = m_varIndexes[i];
+ int index = m_varIndexes[i];
if (index == missingSymbolMarker())
continue;
@@ -4826,14 +5990,14 @@
attributes |= ReadOnly;
LocalStorageEntry entry = LocalStorageEntry(jsUndefined(), attributes);
- ASSERT(index == localStorage.size());
+ ASSERT(static_cast<unsigned>(index) == localStorage.size());
localStorage.uncheckedAppend(entry);
}
optimizeVariableAccess(exec);
}
-void EvalNode::processDeclarations(ExecState* exec)
+void EvalNode::processDeclarations(OldInterpreterExecState* exec)
{
// We could optimize access to pre-existing symbols here, but SunSpider
// reports that to be a net loss.
@@ -4855,7 +6019,7 @@
for (i = 0, size = m_functionStack.size(); i < size; ++i) {
FuncDeclNode* funcDecl = m_functionStack[i];
- variableObject->putWithAttributes(exec, funcDecl->m_ident, funcDecl->makeFunction(exec), 0);
+ variableObject->putWithAttributes(exec, funcDecl->m_ident, funcDecl->makeFunction(exec, exec->scopeChain().node()), 0);
}
}
@@ -4872,19 +6036,13 @@
return s;
}
-JSValue* ProgramNode::execute(ExecState* exec)
+JSValue* ProgramNode::execute(OldInterpreterExecState* exec)
{
processDeclarations(exec);
return ScopeNode::execute(exec);
}
-JSValue* EvalNode::execute(ExecState* exec)
-{
- processDeclarations(exec);
- return ScopeNode::execute(exec);
-}
-
-JSValue* FunctionBodyNode::execute(ExecState* exec)
+JSValue* EvalNode::execute(OldInterpreterExecState* exec)
{
processDeclarations(exec);
return ScopeNode::execute(exec);
@@ -4897,22 +6055,10 @@
{
}
-JSValue* FunctionBodyNodeWithDebuggerHooks::execute(ExecState* exec)
+JSValue* FunctionBodyNodeWithDebuggerHooks::execute(OldInterpreterExecState* exec)
{
- if (Debugger* dbg = exec->dynamicGlobalObject()->debugger()) {
- if (!dbg->callEvent(exec, sourceId(), lineNo(), exec->function(), *exec->arguments()))
- return exec->setInterruptedCompletion();
- }
-
JSValue* result = FunctionBodyNode::execute(exec);
- if (Debugger* dbg = exec->dynamicGlobalObject()->debugger()) {
- if (exec->completionType() == Throw)
- exec->setException(result);
- if (!dbg->returnEvent(exec, sourceId(), lastLine(), exec->function()))
- return exec->setInterruptedCompletion();
- }
-
return result;
}
@@ -4924,9 +6070,9 @@
m_body->parameters().append(p->ident());
}
-FunctionImp* FuncDeclNode::makeFunction(ExecState* exec)
+FunctionImp* FuncDeclNode::makeFunction(ExecState* exec, ScopeChainNode* scopeChain)
{
- FunctionImp* func = new FunctionImp(exec, m_ident, m_body.get(), exec->scopeChain());
+ FunctionImp* func = new FunctionImp(exec, m_ident, m_body.get(), scopeChain);
JSObject* proto = exec->lexicalGlobalObject()->objectConstructor()->construct(exec, exec->emptyList());
proto->putDirect(exec->propertyNames().constructor, func, DontEnum);
@@ -4935,13 +6081,47 @@
return func;
}
-JSValue* FuncDeclNode::execute(ExecState* exec)
+RegisterID* FuncDeclNode::emitCode(CodeGenerator&, RegisterID* dst)
+{
+ return dst;
+}
+
+JSValue* FuncDeclNode::execute(OldInterpreterExecState* exec)
{
return exec->setNormalCompletion();
}
// ------------------------------ FuncExprNode ---------------------------------
+RegisterID* FuncExprNode::emitCode(CodeGenerator& generator, RegisterID* dst)
+{
+ return generator.emitNewFunctionExpression(generator.finalDestination(dst), this);
+}
+
+FunctionImp* FuncExprNode::makeFunction(ExecState* exec, ScopeChainNode* scopeChain)
+{
+ FunctionImp* func = new FunctionImp(exec, m_ident, m_body.get(), scopeChain);
+ JSObject* proto = exec->lexicalGlobalObject()->objectConstructor()->construct(exec, exec->emptyList());
+ proto->putDirect(exec->propertyNames().constructor, func, DontEnum);
+ func->putDirect(exec->propertyNames().prototype, proto, DontDelete);
+
+ /*
+ The Identifier in a FunctionExpression can be referenced from inside
+ the FunctionExpression's FunctionBody to allow the function to call
+ itself recursively. However, unlike in a FunctionDeclaration, the
+ Identifier in a FunctionExpression cannot be referenced from and
+ does not affect the scope enclosing the FunctionExpression.
+ */
+
+ if (!m_ident.isNull()) {
+ JSObject* functionScopeObject = new JSObject;
+ functionScopeObject->putDirect(m_ident, func, ReadOnly | DontDelete);
+ func->scope().push(functionScopeObject);
+ }
+
+ return func;
+}
+
// ECMA 13
void FuncExprNode::addParams()
{
@@ -4949,9 +6129,9 @@
m_body->parameters().append(p->ident());
}
-JSValue* FuncExprNode::evaluate(ExecState* exec)
+JSValue* FuncExprNode::evaluate(OldInterpreterExecState* exec)
{
- exec->dynamicGlobalObject()->tearOffActivation(exec);
+ ASSERT_NOT_REACHED();
bool named = !m_ident.isNull();
JSObject* functionScopeObject = 0;
@@ -4964,7 +6144,7 @@
exec->pushScope(functionScopeObject);
}
- FunctionImp* func = new FunctionImp(exec, m_ident, m_body.get(), exec->scopeChain());
+ FunctionImp* func = new FunctionImp(exec, m_ident, m_body.get(), exec->scopeChain().node());
JSObject* proto = exec->lexicalGlobalObject()->objectConstructor()->construct(exec, exec->emptyList());
proto->putDirect(exec->propertyNames().constructor, func, DontEnum);
func->putDirect(exec->propertyNames().prototype, proto, DontDelete);
diff --git a/JavaScriptCore/kjs/nodes.h b/JavaScriptCore/kjs/nodes.h
index 6a086d0..ddebedf 100644
--- a/JavaScriptCore/kjs/nodes.h
+++ b/JavaScriptCore/kjs/nodes.h
@@ -28,7 +28,10 @@
#include "internal.h"
#include "regexp.h"
+#include "RegisterID.h"
+#include "SourceRange.h"
#include "SymbolTable.h"
+#include <wtf/UnusedParam.h>
#include <wtf/ListRefPtr.h>
#include <wtf/MathExtras.h>
#include <wtf/OwnPtr.h>
@@ -43,9 +46,13 @@
namespace KJS {
class ArgumentsNode;
+ class CodeBlock;
+ class CodeGenerator;
class ConstDeclNode;
class FuncDeclNode;
class Node;
+ class EvalCodeBlock;
+ class ProgramCodeBlock;
class PropertyListNode;
class SourceStream;
@@ -137,40 +144,74 @@
{
}
+ /*
+ Return value: The register holding the production's value.
+ dst: An optional parameter specifying the most efficient
+ destination at which to store the production's value.
+ The callee must honor dst.
+
+ dst provides for a crude form of copy propagation. For example,
+
+ x = 1
+
+ becomes
+
+ load r[x], 1
+
+ instead of
+
+ load r0, 1
+ mov r[x], r0
+
+ because the assignment node, "x =", passes r[x] as dst to the number
+ node, "1".
+ */
+ virtual RegisterID* emitCode(CodeGenerator&, RegisterID* dst = 0) KJS_FAST_CALL
+ {
+ ASSERT_WITH_MESSAGE(0, "Don't know how to generate code for:\n%s\n", toString().ascii());
+ UNUSED_PARAM(dst);
+ return 0;
+ } // FIXME: Make this pure virtual.
+
UString toString() const KJS_FAST_CALL;
int lineNo() const KJS_FAST_CALL { return m_line; }
+ virtual bool isReturnNode() const KJS_FAST_CALL { return false; }
+
// Serialization.
virtual void streamTo(SourceStream&) const KJS_FAST_CALL = 0;
virtual Precedence precedence() const = 0;
virtual bool needsParensIfLeftmost() const { return false; }
-
+
// Used for iterative, depth-first traversal of the node tree. Does not cross function call boundaries.
- virtual void optimizeVariableAccess(ExecState*, const SymbolTable&, const LocalStorage&, NodeStack&) KJS_FAST_CALL { }
+ virtual void optimizeVariableAccess(OldInterpreterExecState*, const SymbolTable&, const LocalStorage&, NodeStack&) KJS_FAST_CALL { }
protected:
Node(JSType) KJS_FAST_CALL; // used by ExpressionNode
// for use in execute()
- JSValue* setErrorCompletion(ExecState*, ErrorType, const char* msg) KJS_FAST_CALL;
- JSValue* setErrorCompletion(ExecState*, ErrorType, const char* msg, const Identifier&) KJS_FAST_CALL;
+ JSValue* setErrorCompletion(OldInterpreterExecState*, ErrorType, const char* msg) KJS_FAST_CALL;
+ JSValue* setErrorCompletion(OldInterpreterExecState*, ErrorType, const char* msg, const Identifier&) KJS_FAST_CALL;
// for use in evaluate()
- JSValue* throwError(ExecState*, ErrorType, const char* msg) KJS_FAST_CALL;
- JSValue* throwError(ExecState*, ErrorType, const char* msg, const char*) KJS_FAST_CALL;
- JSValue* throwError(ExecState*, ErrorType, const char* msg, JSValue*, Node*) KJS_FAST_CALL;
- JSValue* throwError(ExecState*, ErrorType, const char* msg, const Identifier&) KJS_FAST_CALL;
- JSValue* throwError(ExecState*, ErrorType, const char* msg, JSValue*, const Identifier&) KJS_FAST_CALL;
- JSValue* throwError(ExecState*, ErrorType, const char* msg, JSValue*, Node*, Node*) KJS_FAST_CALL;
- JSValue* throwError(ExecState*, ErrorType, const char* msg, JSValue*, Node*, const Identifier&) KJS_FAST_CALL;
+ JSValue* throwError(OldInterpreterExecState*, ErrorType, const char* msg) KJS_FAST_CALL;
+ JSValue* throwError(OldInterpreterExecState*, ErrorType, const char* msg, const char*) KJS_FAST_CALL;
+ JSValue* throwError(OldInterpreterExecState*, ErrorType, const char* msg, JSValue*, Node*) KJS_FAST_CALL;
+ JSValue* throwError(OldInterpreterExecState*, ErrorType, const char* msg, const Identifier&) KJS_FAST_CALL;
+ JSValue* throwError(OldInterpreterExecState*, ErrorType, const char* msg, JSValue*, const Identifier&) KJS_FAST_CALL;
+ JSValue* throwError(OldInterpreterExecState*, ErrorType, const char* msg, JSValue*, Node*, Node*) KJS_FAST_CALL;
+ JSValue* throwError(OldInterpreterExecState*, ErrorType, const char* msg, JSValue*, Node*, const Identifier&) KJS_FAST_CALL;
+
+ RegisterID* emitThrowError(CodeGenerator&, ErrorType, const char* msg);
+ RegisterID* emitThrowError(CodeGenerator&, ErrorType, const char* msg, const Identifier&);
- JSValue* throwUndefinedVariableError(ExecState*, const Identifier&) KJS_FAST_CALL;
+ JSValue* throwUndefinedVariableError(OldInterpreterExecState*, const Identifier&) KJS_FAST_CALL;
- void handleException(ExecState*) KJS_FAST_CALL;
- void handleException(ExecState*, JSValue*) KJS_FAST_CALL;
+ void handleException(OldInterpreterExecState*) KJS_FAST_CALL;
+ void handleException(OldInterpreterExecState*, JSValue*) KJS_FAST_CALL;
// for use in execute()
- JSValue* rethrowException(ExecState*) KJS_FAST_CALL;
+ JSValue* rethrowException(OldInterpreterExecState*) KJS_FAST_CALL;
int m_line : 28;
unsigned m_expectedReturnType : 3; // JSType
@@ -198,11 +239,11 @@
JSType expectedReturnType() const KJS_FAST_CALL { return static_cast<JSType>(m_expectedReturnType); }
- virtual JSValue* evaluate(ExecState*) KJS_FAST_CALL = 0;
- virtual double evaluateToNumber(ExecState*) KJS_FAST_CALL;
- virtual int32_t evaluateToInt32(ExecState*) KJS_FAST_CALL;
- virtual uint32_t evaluateToUInt32(ExecState*) KJS_FAST_CALL;
- virtual bool evaluateToBoolean(ExecState*) KJS_FAST_CALL;
+ virtual JSValue* evaluate(OldInterpreterExecState*) KJS_FAST_CALL = 0;
+ virtual double evaluateToNumber(OldInterpreterExecState*) KJS_FAST_CALL;
+ virtual int32_t evaluateToInt32(OldInterpreterExecState*) KJS_FAST_CALL;
+ virtual uint32_t evaluateToUInt32(OldInterpreterExecState*) KJS_FAST_CALL;
+ virtual bool evaluateToBoolean(OldInterpreterExecState*) KJS_FAST_CALL;
// Used to optimize those nodes that do extra work when returning a result, even if the result has no semantic relevance
virtual void optimizeForUnnecessaryResult() { }
@@ -210,7 +251,7 @@
// This needs to be in public in order to compile using GCC 3.x
typedef enum { EvalOperator, FunctionCall } CallerType;
protected:
- template <CallerType, bool> inline JSValue* resolveAndCall(ExecState*, const Identifier&, ArgumentsNode*, size_t = 0);
+ template <CallerType, bool> inline JSValue* resolveAndCall(OldInterpreterExecState*, const Identifier&, ArgumentsNode*, size_t = 0);
};
class StatementNode : public Node {
@@ -219,7 +260,9 @@
void setLoc(int line0, int line1) KJS_FAST_CALL;
int firstLine() const KJS_FAST_CALL { return lineNo(); }
int lastLine() const KJS_FAST_CALL { return m_lastLine; }
- virtual JSValue* execute(ExecState *exec) KJS_FAST_CALL = 0;
+
+ virtual JSValue* execute(OldInterpreterExecState *exec) KJS_FAST_CALL = 0;
+
virtual void pushLabel(const Identifier& ident) KJS_FAST_CALL { m_labelStack.push(ident); }
virtual Precedence precedence() const { ASSERT_NOT_REACHED(); return PrecExpression; }
virtual bool isEmptyStatement() const KJS_FAST_CALL { return false; }
@@ -233,8 +276,14 @@
class NullNode : public ExpressionNode {
public:
- NullNode() KJS_FAST_CALL : ExpressionNode(NullType) {}
- virtual JSValue* evaluate(ExecState*) KJS_FAST_CALL;
+ NullNode() KJS_FAST_CALL
+ : ExpressionNode(NullType)
+ {
+ }
+
+ virtual RegisterID* emitCode(CodeGenerator&, RegisterID* = 0) KJS_FAST_CALL;
+
+ virtual JSValue* evaluate(OldInterpreterExecState*) KJS_FAST_CALL;
virtual void streamTo(SourceStream&) const KJS_FAST_CALL;
virtual Precedence precedence() const { return PrecPrimary; }
};
@@ -246,8 +295,10 @@
{
}
- virtual JSValue* evaluate(ExecState*) KJS_FAST_CALL;
- virtual bool evaluateToBoolean(ExecState*) KJS_FAST_CALL { return false; }
+ virtual RegisterID* emitCode(CodeGenerator&, RegisterID* = 0) KJS_FAST_CALL;
+
+ virtual JSValue* evaluate(OldInterpreterExecState*) KJS_FAST_CALL;
+ virtual bool evaluateToBoolean(OldInterpreterExecState*) KJS_FAST_CALL { return false; }
virtual void streamTo(SourceStream&) const KJS_FAST_CALL;
virtual Precedence precedence() const { return PrecPrimary; }
};
@@ -259,8 +310,10 @@
{
}
- virtual JSValue* evaluate(ExecState*) KJS_FAST_CALL;
- virtual bool evaluateToBoolean(ExecState*) KJS_FAST_CALL { return true; }
+ virtual RegisterID* emitCode(CodeGenerator&, RegisterID* = 0) KJS_FAST_CALL;
+
+ virtual JSValue* evaluate(OldInterpreterExecState*) KJS_FAST_CALL;
+ virtual bool evaluateToBoolean(OldInterpreterExecState*) KJS_FAST_CALL { return true; }
virtual void streamTo(SourceStream&) const KJS_FAST_CALL;
virtual Precedence precedence() const { return PrecPrimary; }
};
@@ -284,11 +337,13 @@
{
}
- virtual JSValue* evaluate(ExecState*) KJS_FAST_CALL;
- virtual double evaluateToNumber(ExecState*) KJS_FAST_CALL;
- virtual bool evaluateToBoolean(ExecState*) KJS_FAST_CALL;
- virtual int32_t evaluateToInt32(ExecState*) KJS_FAST_CALL;
- virtual uint32_t evaluateToUInt32(ExecState*) KJS_FAST_CALL;
+ virtual RegisterID* emitCode(CodeGenerator&, RegisterID* = 0) KJS_FAST_CALL;
+
+ virtual JSValue* evaluate(OldInterpreterExecState*) KJS_FAST_CALL;
+ virtual double evaluateToNumber(OldInterpreterExecState*) KJS_FAST_CALL;
+ virtual bool evaluateToBoolean(OldInterpreterExecState*) KJS_FAST_CALL;
+ virtual int32_t evaluateToInt32(OldInterpreterExecState*) KJS_FAST_CALL;
+ virtual uint32_t evaluateToUInt32(OldInterpreterExecState*) KJS_FAST_CALL;
virtual void streamTo(SourceStream&) const KJS_FAST_CALL;
virtual Precedence precedence() const { return signbit(m_double) ? PrecUnary : PrecPrimary; }
@@ -309,9 +364,9 @@
ASSERT(v == JSImmediate::from(d));
}
- virtual JSValue* evaluate(ExecState*) KJS_FAST_CALL;
- virtual int32_t evaluateToInt32(ExecState*) KJS_FAST_CALL;
- virtual uint32_t evaluateToUInt32(ExecState*) KJS_FAST_CALL;
+ virtual JSValue* evaluate(OldInterpreterExecState*) KJS_FAST_CALL;
+ virtual int32_t evaluateToInt32(OldInterpreterExecState*) KJS_FAST_CALL;
+ virtual uint32_t evaluateToUInt32(OldInterpreterExecState*) KJS_FAST_CALL;
virtual void setValue(double d) KJS_FAST_CALL { m_double = d; m_value = JSImmediate::from(d); ASSERT(m_value); }
@@ -327,9 +382,11 @@
{
}
- virtual JSValue* evaluate(ExecState*) KJS_FAST_CALL;
- virtual double evaluateToNumber(ExecState*) KJS_FAST_CALL;
- virtual bool evaluateToBoolean(ExecState*) KJS_FAST_CALL;
+ virtual RegisterID* emitCode(CodeGenerator&, RegisterID* = 0) KJS_FAST_CALL;
+
+ virtual JSValue* evaluate(OldInterpreterExecState*) KJS_FAST_CALL;
+ virtual double evaluateToNumber(OldInterpreterExecState*) KJS_FAST_CALL;
+ virtual bool evaluateToBoolean(OldInterpreterExecState*) KJS_FAST_CALL;
virtual void streamTo(SourceStream&) const KJS_FAST_CALL;
virtual Precedence precedence() const { return PrecPrimary; }
@@ -344,7 +401,9 @@
{
}
- JSValue* evaluate(ExecState*) KJS_FAST_CALL;
+ virtual RegisterID* emitCode(CodeGenerator&, RegisterID* = 0) KJS_FAST_CALL;
+
+ JSValue* evaluate(OldInterpreterExecState*) KJS_FAST_CALL;
virtual void streamTo(SourceStream&) const KJS_FAST_CALL;
virtual Precedence precedence() const { return PrecPrimary; }
@@ -358,7 +417,9 @@
{
}
- virtual JSValue* evaluate(ExecState*) KJS_FAST_CALL;
+ virtual RegisterID* emitCode(CodeGenerator&, RegisterID* = 0) KJS_FAST_CALL;
+
+ virtual JSValue* evaluate(OldInterpreterExecState*) KJS_FAST_CALL;
virtual void streamTo(SourceStream&) const KJS_FAST_CALL;
virtual Precedence precedence() const { return PrecPrimary; }
};
@@ -377,13 +438,14 @@
{
}
- virtual void optimizeVariableAccess(ExecState*, const SymbolTable&, const LocalStorage&, NodeStack&) KJS_FAST_CALL;
+ virtual RegisterID* emitCode(CodeGenerator&, RegisterID* = 0) KJS_FAST_CALL;
+ virtual void optimizeVariableAccess(OldInterpreterExecState*, const SymbolTable&, const LocalStorage&, NodeStack&) KJS_FAST_CALL;
- virtual JSValue* evaluate(ExecState*) KJS_FAST_CALL;
- virtual bool evaluateToBoolean(ExecState*) KJS_FAST_CALL;
- virtual double evaluateToNumber(ExecState*) KJS_FAST_CALL;
- virtual int32_t evaluateToInt32(ExecState*) KJS_FAST_CALL;
- virtual uint32_t evaluateToUInt32(ExecState*) KJS_FAST_CALL;
+ virtual JSValue* evaluate(OldInterpreterExecState*) KJS_FAST_CALL;
+ virtual bool evaluateToBoolean(OldInterpreterExecState*) KJS_FAST_CALL;
+ virtual double evaluateToNumber(OldInterpreterExecState*) KJS_FAST_CALL;
+ virtual int32_t evaluateToInt32(OldInterpreterExecState*) KJS_FAST_CALL;
+ virtual uint32_t evaluateToUInt32(OldInterpreterExecState*) KJS_FAST_CALL;
virtual void streamTo(SourceStream&) const KJS_FAST_CALL;
virtual Precedence precedence() const { return PrecPrimary; }
@@ -392,36 +454,36 @@
const Identifier& identifier() const KJS_FAST_CALL { return m_ident; }
protected:
- ALWAYS_INLINE JSValue* inlineEvaluate(ExecState*);
+ ALWAYS_INLINE JSValue* inlineEvaluate(OldInterpreterExecState*);
Identifier m_ident;
- size_t m_index; // Used by LocalVarAccessNode and ScopedVarAccessNode.
+ int m_index; // Used by LocalVarAccessNode and ScopedVarAccessNode.
size_t m_scopeDepth; // Used by ScopedVarAccessNode
};
class LocalVarAccessNode : public ResolveNode {
public:
// Overwrites a ResolveNode in place.
- LocalVarAccessNode(size_t i) KJS_FAST_CALL
+ LocalVarAccessNode(int i) KJS_FAST_CALL
: ResolveNode(PlacementNewAdopt)
{
ASSERT(i != missingSymbolMarker());
m_index = i;
}
- virtual JSValue* evaluate(ExecState*) KJS_FAST_CALL;
- virtual double evaluateToNumber(ExecState*) KJS_FAST_CALL;
- virtual bool evaluateToBoolean(ExecState*) KJS_FAST_CALL;
- virtual int32_t evaluateToInt32(ExecState*) KJS_FAST_CALL;
- virtual uint32_t evaluateToUInt32(ExecState*) KJS_FAST_CALL;
+ virtual JSValue* evaluate(OldInterpreterExecState*) KJS_FAST_CALL;
+ virtual double evaluateToNumber(OldInterpreterExecState*) KJS_FAST_CALL;
+ virtual bool evaluateToBoolean(OldInterpreterExecState*) KJS_FAST_CALL;
+ virtual int32_t evaluateToInt32(OldInterpreterExecState*) KJS_FAST_CALL;
+ virtual uint32_t evaluateToUInt32(OldInterpreterExecState*) KJS_FAST_CALL;
private:
- ALWAYS_INLINE JSValue* inlineEvaluate(ExecState*);
+ ALWAYS_INLINE JSValue* inlineEvaluate(OldInterpreterExecState*);
};
class ScopedVarAccessNode : public ResolveNode {
public:
// Overwrites a ResolveNode in place.
- ScopedVarAccessNode(size_t i, size_t scopeDepth) KJS_FAST_CALL
+ ScopedVarAccessNode(int i, size_t scopeDepth) KJS_FAST_CALL
: ResolveNode(PlacementNewAdopt)
{
ASSERT(i != missingSymbolMarker());
@@ -429,14 +491,14 @@
m_scopeDepth = scopeDepth;
}
- virtual JSValue* evaluate(ExecState*) KJS_FAST_CALL;
- virtual double evaluateToNumber(ExecState*) KJS_FAST_CALL;
- virtual bool evaluateToBoolean(ExecState*) KJS_FAST_CALL;
- virtual int32_t evaluateToInt32(ExecState*) KJS_FAST_CALL;
- virtual uint32_t evaluateToUInt32(ExecState*) KJS_FAST_CALL;
+ virtual JSValue* evaluate(OldInterpreterExecState*) KJS_FAST_CALL;
+ virtual double evaluateToNumber(OldInterpreterExecState*) KJS_FAST_CALL;
+ virtual bool evaluateToBoolean(OldInterpreterExecState*) KJS_FAST_CALL;
+ virtual int32_t evaluateToInt32(OldInterpreterExecState*) KJS_FAST_CALL;
+ virtual uint32_t evaluateToUInt32(OldInterpreterExecState*) KJS_FAST_CALL;
private:
- ALWAYS_INLINE JSValue* inlineEvaluate(ExecState*);
+ ALWAYS_INLINE JSValue* inlineEvaluate(OldInterpreterExecState*);
};
class NonLocalVarAccessNode : public ResolveNode {
@@ -449,14 +511,14 @@
m_scopeDepth = scopeDepth;
}
- virtual JSValue* evaluate(ExecState*) KJS_FAST_CALL;
- virtual double evaluateToNumber(ExecState*) KJS_FAST_CALL;
- virtual bool evaluateToBoolean(ExecState*) KJS_FAST_CALL;
- virtual int32_t evaluateToInt32(ExecState*) KJS_FAST_CALL;
- virtual uint32_t evaluateToUInt32(ExecState*) KJS_FAST_CALL;
+ virtual JSValue* evaluate(OldInterpreterExecState*) KJS_FAST_CALL;
+ virtual double evaluateToNumber(OldInterpreterExecState*) KJS_FAST_CALL;
+ virtual bool evaluateToBoolean(OldInterpreterExecState*) KJS_FAST_CALL;
+ virtual int32_t evaluateToInt32(OldInterpreterExecState*) KJS_FAST_CALL;
+ virtual uint32_t evaluateToUInt32(OldInterpreterExecState*) KJS_FAST_CALL;
private:
- ALWAYS_INLINE JSValue* inlineEvaluate(ExecState*);
+ ALWAYS_INLINE JSValue* inlineEvaluate(OldInterpreterExecState*);
};
class ElementNode : public Node {
@@ -476,11 +538,11 @@
virtual Precedence precedence() const { ASSERT_NOT_REACHED(); return PrecExpression; }
virtual void streamTo(SourceStream&) const KJS_FAST_CALL;
- virtual void optimizeVariableAccess(ExecState*, const SymbolTable&, const LocalStorage&, NodeStack&) KJS_FAST_CALL;
+ virtual void optimizeVariableAccess(OldInterpreterExecState*, const SymbolTable&, const LocalStorage&, NodeStack&) KJS_FAST_CALL;
PassRefPtr<ElementNode> releaseNext() KJS_FAST_CALL { return m_next.release(); }
- JSValue* evaluate(ExecState*) KJS_FAST_CALL;
+ JSValue* evaluate(OldInterpreterExecState*) KJS_FAST_CALL;
private:
friend class ArrayNode;
@@ -511,8 +573,10 @@
{
}
- virtual void optimizeVariableAccess(ExecState*, const SymbolTable&, const LocalStorage&, NodeStack&) KJS_FAST_CALL;
- virtual JSValue* evaluate(ExecState*) KJS_FAST_CALL;
+ virtual RegisterID* emitCode(CodeGenerator&, RegisterID* = 0) KJS_FAST_CALL;
+
+ virtual void optimizeVariableAccess(OldInterpreterExecState*, const SymbolTable&, const LocalStorage&, NodeStack&) KJS_FAST_CALL;
+ virtual JSValue* evaluate(OldInterpreterExecState*) KJS_FAST_CALL;
virtual void streamTo(SourceStream&) const KJS_FAST_CALL;
virtual Precedence precedence() const { return PrecPrimary; }
@@ -533,11 +597,11 @@
{
}
- virtual void optimizeVariableAccess(ExecState*, const SymbolTable&, const LocalStorage&, NodeStack&) KJS_FAST_CALL;
+ virtual void optimizeVariableAccess(OldInterpreterExecState*, const SymbolTable&, const LocalStorage&, NodeStack&) KJS_FAST_CALL;
virtual void streamTo(SourceStream&) const KJS_FAST_CALL;
virtual Precedence precedence() const { ASSERT_NOT_REACHED(); return PrecExpression; }
- JSValue* evaluate(ExecState*) KJS_FAST_CALL;
+ JSValue* evaluate(OldInterpreterExecState*) KJS_FAST_CALL;
const Identifier& name() const { return m_name; }
private:
@@ -560,11 +624,12 @@
list->m_next = this;
}
- virtual void optimizeVariableAccess(ExecState*, const SymbolTable&, const LocalStorage&, NodeStack&) KJS_FAST_CALL;
+ virtual RegisterID* emitCode(CodeGenerator&, RegisterID* = 0) KJS_FAST_CALL;
+ virtual void optimizeVariableAccess(OldInterpreterExecState*, const SymbolTable&, const LocalStorage&, NodeStack&) KJS_FAST_CALL;
virtual void streamTo(SourceStream&) const KJS_FAST_CALL;
virtual Precedence precedence() const { ASSERT_NOT_REACHED(); return PrecExpression; }
- JSValue* evaluate(ExecState*) KJS_FAST_CALL;
+ JSValue* evaluate(OldInterpreterExecState*) KJS_FAST_CALL;
PassRefPtr<PropertyListNode> releaseNext() KJS_FAST_CALL { return m_next.release(); }
private:
@@ -584,8 +649,9 @@
{
}
- virtual void optimizeVariableAccess(ExecState*, const SymbolTable&, const LocalStorage&, NodeStack&) KJS_FAST_CALL;
- virtual JSValue* evaluate(ExecState*) KJS_FAST_CALL;
+ virtual RegisterID* emitCode(CodeGenerator&, RegisterID* = 0) KJS_FAST_CALL;
+ virtual void optimizeVariableAccess(OldInterpreterExecState*, const SymbolTable&, const LocalStorage&, NodeStack&) KJS_FAST_CALL;
+ virtual JSValue* evaluate(OldInterpreterExecState*) KJS_FAST_CALL;
virtual void streamTo(SourceStream&) const KJS_FAST_CALL;
virtual Precedence precedence() const { return PrecPrimary; }
virtual bool needsParensIfLeftmost() const { return true; }
@@ -602,12 +668,14 @@
{
}
- virtual void optimizeVariableAccess(ExecState*, const SymbolTable&, const LocalStorage&, NodeStack&) KJS_FAST_CALL;
- virtual JSValue* evaluate(ExecState*) KJS_FAST_CALL;
- virtual double evaluateToNumber(ExecState*) KJS_FAST_CALL;
- virtual bool evaluateToBoolean(ExecState*) KJS_FAST_CALL;
- virtual int32_t evaluateToInt32(ExecState*) KJS_FAST_CALL;
- virtual uint32_t evaluateToUInt32(ExecState*) KJS_FAST_CALL;
+ virtual RegisterID* emitCode(CodeGenerator&, RegisterID* = 0) KJS_FAST_CALL;
+
+ virtual void optimizeVariableAccess(OldInterpreterExecState*, const SymbolTable&, const LocalStorage&, NodeStack&) KJS_FAST_CALL;
+ virtual JSValue* evaluate(OldInterpreterExecState*) KJS_FAST_CALL;
+ virtual double evaluateToNumber(OldInterpreterExecState*) KJS_FAST_CALL;
+ virtual bool evaluateToBoolean(OldInterpreterExecState*) KJS_FAST_CALL;
+ virtual int32_t evaluateToInt32(OldInterpreterExecState*) KJS_FAST_CALL;
+ virtual uint32_t evaluateToUInt32(OldInterpreterExecState*) KJS_FAST_CALL;
virtual void streamTo(SourceStream&) const KJS_FAST_CALL;
virtual Precedence precedence() const { return PrecMember; }
@@ -617,7 +685,7 @@
ExpressionNode* subscript() KJS_FAST_CALL { return m_subscript.get(); }
private:
- ALWAYS_INLINE JSValue* inlineEvaluate(ExecState*);
+ ALWAYS_INLINE JSValue* inlineEvaluate(OldInterpreterExecState*);
RefPtr<ExpressionNode> m_base;
RefPtr<ExpressionNode> m_subscript;
@@ -631,12 +699,13 @@
{
}
- virtual void optimizeVariableAccess(ExecState*, const SymbolTable&, const LocalStorage&, NodeStack&) KJS_FAST_CALL;
- virtual JSValue* evaluate(ExecState*) KJS_FAST_CALL;
- virtual bool evaluateToBoolean(ExecState*) KJS_FAST_CALL;
- virtual double evaluateToNumber(ExecState*) KJS_FAST_CALL;
- virtual int32_t evaluateToInt32(ExecState*) KJS_FAST_CALL;
- virtual uint32_t evaluateToUInt32(ExecState*) KJS_FAST_CALL;
+ virtual RegisterID* emitCode(CodeGenerator&, RegisterID* = 0) KJS_FAST_CALL;
+ virtual void optimizeVariableAccess(OldInterpreterExecState*, const SymbolTable&, const LocalStorage&, NodeStack&) KJS_FAST_CALL;
+ virtual JSValue* evaluate(OldInterpreterExecState*) KJS_FAST_CALL;
+ virtual bool evaluateToBoolean(OldInterpreterExecState*) KJS_FAST_CALL;
+ virtual double evaluateToNumber(OldInterpreterExecState*) KJS_FAST_CALL;
+ virtual int32_t evaluateToInt32(OldInterpreterExecState*) KJS_FAST_CALL;
+ virtual uint32_t evaluateToUInt32(OldInterpreterExecState*) KJS_FAST_CALL;
virtual void streamTo(SourceStream&) const KJS_FAST_CALL;
virtual Precedence precedence() const { return PrecMember; }
@@ -646,7 +715,7 @@
const Identifier& identifier() const KJS_FAST_CALL { return m_ident; }
private:
- ALWAYS_INLINE JSValue* inlineEvaluate(ExecState*);
+ ALWAYS_INLINE JSValue* inlineEvaluate(OldInterpreterExecState*);
RefPtr<ExpressionNode> m_base;
Identifier m_ident;
@@ -665,15 +734,14 @@
listNode->m_next = this;
}
- virtual void optimizeVariableAccess(ExecState*, const SymbolTable&, const LocalStorage&, NodeStack&) KJS_FAST_CALL;
+ virtual RegisterID* emitCode(CodeGenerator&, RegisterID* = 0) KJS_FAST_CALL;
+ virtual void optimizeVariableAccess(OldInterpreterExecState*, const SymbolTable&, const LocalStorage&, NodeStack&) KJS_FAST_CALL;
virtual void streamTo(SourceStream&) const KJS_FAST_CALL;
virtual Precedence precedence() const { ASSERT_NOT_REACHED(); return PrecExpression; }
- void evaluateList(ExecState*, List&) KJS_FAST_CALL;
+ void evaluateList(OldInterpreterExecState*, List&) KJS_FAST_CALL;
PassRefPtr<ArgumentListNode> releaseNext() KJS_FAST_CALL { return m_next.release(); }
- private:
- friend class ArgumentsNode;
ListRefPtr<ArgumentListNode> m_next;
RefPtr<ExpressionNode> m_expr;
};
@@ -689,13 +757,12 @@
{
}
- virtual void optimizeVariableAccess(ExecState*, const SymbolTable&, const LocalStorage&, NodeStack&) KJS_FAST_CALL;
+ virtual void optimizeVariableAccess(OldInterpreterExecState*, const SymbolTable&, const LocalStorage&, NodeStack&) KJS_FAST_CALL;
virtual void streamTo(SourceStream&) const KJS_FAST_CALL;
virtual Precedence precedence() const { ASSERT_NOT_REACHED(); return PrecExpression; }
- void evaluateList(ExecState* exec, List& list) KJS_FAST_CALL { if (m_listNode) m_listNode->evaluateList(exec, list); }
+ void evaluateList(OldInterpreterExecState* exec, List& list) KJS_FAST_CALL { if (m_listNode) m_listNode->evaluateList(exec, list); }
- private:
RefPtr<ArgumentListNode> m_listNode;
};
@@ -712,17 +779,19 @@
{
}
- virtual void optimizeVariableAccess(ExecState*, const SymbolTable&, const LocalStorage&, NodeStack&) KJS_FAST_CALL;
- virtual JSValue* evaluate(ExecState*) KJS_FAST_CALL;
- virtual double evaluateToNumber(ExecState*) KJS_FAST_CALL;
- virtual int32_t evaluateToInt32(ExecState*) KJS_FAST_CALL;
- virtual uint32_t evaluateToUInt32(ExecState*) KJS_FAST_CALL;
- virtual bool evaluateToBoolean(ExecState*) KJS_FAST_CALL;
+ virtual RegisterID* emitCode(CodeGenerator&, RegisterID* = 0) KJS_FAST_CALL;
+
+ virtual void optimizeVariableAccess(OldInterpreterExecState*, const SymbolTable&, const LocalStorage&, NodeStack&) KJS_FAST_CALL;
+ virtual JSValue* evaluate(OldInterpreterExecState*) KJS_FAST_CALL;
+ virtual double evaluateToNumber(OldInterpreterExecState*) KJS_FAST_CALL;
+ virtual int32_t evaluateToInt32(OldInterpreterExecState*) KJS_FAST_CALL;
+ virtual uint32_t evaluateToUInt32(OldInterpreterExecState*) KJS_FAST_CALL;
+ virtual bool evaluateToBoolean(OldInterpreterExecState*) KJS_FAST_CALL;
virtual void streamTo(SourceStream&) const KJS_FAST_CALL;
virtual Precedence precedence() const { return PrecLeftHandSide; }
private:
- ALWAYS_INLINE JSValue* inlineEvaluate(ExecState*);
+ ALWAYS_INLINE JSValue* inlineEvaluate(OldInterpreterExecState*);
RefPtr<ExpressionNode> m_expr;
RefPtr<ArgumentsNode> m_args;
@@ -735,8 +804,9 @@
{
}
- virtual void optimizeVariableAccess(ExecState*, const SymbolTable&, const LocalStorage&, NodeStack&) KJS_FAST_CALL;
- virtual JSValue* evaluate(ExecState*) KJS_FAST_CALL;
+ virtual RegisterID* emitCode(CodeGenerator&, RegisterID* = 0) KJS_FAST_CALL;
+ virtual void optimizeVariableAccess(OldInterpreterExecState*, const SymbolTable&, const LocalStorage&, NodeStack&) KJS_FAST_CALL;
+ virtual JSValue* evaluate(OldInterpreterExecState*) KJS_FAST_CALL;
virtual void streamTo(SourceStream&) const KJS_FAST_CALL;
virtual Precedence precedence() const { return PrecCall; }
@@ -752,8 +822,9 @@
{
}
- virtual void optimizeVariableAccess(ExecState*, const SymbolTable&, const LocalStorage&, NodeStack&) KJS_FAST_CALL;
- virtual JSValue* evaluate(ExecState*) KJS_FAST_CALL;
+ virtual RegisterID* emitCode(CodeGenerator&, RegisterID* = 0) KJS_FAST_CALL;
+ virtual void optimizeVariableAccess(OldInterpreterExecState*, const SymbolTable&, const LocalStorage&, NodeStack&) KJS_FAST_CALL;
+ virtual JSValue* evaluate(OldInterpreterExecState*) KJS_FAST_CALL;
virtual void streamTo(SourceStream&) const KJS_FAST_CALL;
virtual Precedence precedence() const { return PrecCall; }
@@ -777,17 +848,19 @@
{
}
- virtual void optimizeVariableAccess(ExecState*, const SymbolTable&, const LocalStorage&, NodeStack&) KJS_FAST_CALL;
- virtual JSValue* evaluate(ExecState*) KJS_FAST_CALL;
- virtual double evaluateToNumber(ExecState*) KJS_FAST_CALL;
- virtual bool evaluateToBoolean(ExecState*) KJS_FAST_CALL;
- virtual int32_t evaluateToInt32(ExecState*) KJS_FAST_CALL;
- virtual uint32_t evaluateToUInt32(ExecState*) KJS_FAST_CALL;
+ virtual RegisterID* emitCode(CodeGenerator&, RegisterID* = 0) KJS_FAST_CALL;
+
+ virtual void optimizeVariableAccess(OldInterpreterExecState*, const SymbolTable&, const LocalStorage&, NodeStack&) KJS_FAST_CALL;
+ virtual JSValue* evaluate(OldInterpreterExecState*) KJS_FAST_CALL;
+ virtual double evaluateToNumber(OldInterpreterExecState*) KJS_FAST_CALL;
+ virtual bool evaluateToBoolean(OldInterpreterExecState*) KJS_FAST_CALL;
+ virtual int32_t evaluateToInt32(OldInterpreterExecState*) KJS_FAST_CALL;
+ virtual uint32_t evaluateToUInt32(OldInterpreterExecState*) KJS_FAST_CALL;
virtual void streamTo(SourceStream&) const KJS_FAST_CALL;
virtual Precedence precedence() const { return PrecCall; }
protected:
- ALWAYS_INLINE JSValue* inlineEvaluate(ExecState*);
+ ALWAYS_INLINE JSValue* inlineEvaluate(OldInterpreterExecState*);
Identifier m_ident;
RefPtr<ArgumentsNode> m_args;
@@ -797,26 +870,26 @@
class LocalVarFunctionCallNode : public FunctionCallResolveNode {
public:
- LocalVarFunctionCallNode(size_t i) KJS_FAST_CALL
+ LocalVarFunctionCallNode(int i) KJS_FAST_CALL
: FunctionCallResolveNode(PlacementNewAdopt)
{
ASSERT(i != missingSymbolMarker());
m_index = i;
}
- virtual JSValue* evaluate(ExecState*) KJS_FAST_CALL;
- virtual bool evaluateToBoolean(ExecState*) KJS_FAST_CALL;
- virtual double evaluateToNumber(ExecState*) KJS_FAST_CALL;
- virtual int32_t evaluateToInt32(ExecState*) KJS_FAST_CALL;
- virtual uint32_t evaluateToUInt32(ExecState*) KJS_FAST_CALL;
+ virtual JSValue* evaluate(OldInterpreterExecState*) KJS_FAST_CALL;
+ virtual bool evaluateToBoolean(OldInterpreterExecState*) KJS_FAST_CALL;
+ virtual double evaluateToNumber(OldInterpreterExecState*) KJS_FAST_CALL;
+ virtual int32_t evaluateToInt32(OldInterpreterExecState*) KJS_FAST_CALL;
+ virtual uint32_t evaluateToUInt32(OldInterpreterExecState*) KJS_FAST_CALL;
private:
- ALWAYS_INLINE JSValue* inlineEvaluate(ExecState*);
+ ALWAYS_INLINE JSValue* inlineEvaluate(OldInterpreterExecState*);
};
class ScopedVarFunctionCallNode : public FunctionCallResolveNode {
public:
- ScopedVarFunctionCallNode(size_t i, size_t depth) KJS_FAST_CALL
+ ScopedVarFunctionCallNode(int i, size_t depth) KJS_FAST_CALL
: FunctionCallResolveNode(PlacementNewAdopt)
{
ASSERT(i != missingSymbolMarker());
@@ -824,14 +897,14 @@
m_scopeDepth = depth;
}
- virtual JSValue* evaluate(ExecState*) KJS_FAST_CALL;
- virtual bool evaluateToBoolean(ExecState*) KJS_FAST_CALL;
- virtual double evaluateToNumber(ExecState*) KJS_FAST_CALL;
- virtual int32_t evaluateToInt32(ExecState*) KJS_FAST_CALL;
- virtual uint32_t evaluateToUInt32(ExecState*) KJS_FAST_CALL;
+ virtual JSValue* evaluate(OldInterpreterExecState*) KJS_FAST_CALL;
+ virtual bool evaluateToBoolean(OldInterpreterExecState*) KJS_FAST_CALL;
+ virtual double evaluateToNumber(OldInterpreterExecState*) KJS_FAST_CALL;
+ virtual int32_t evaluateToInt32(OldInterpreterExecState*) KJS_FAST_CALL;
+ virtual uint32_t evaluateToUInt32(OldInterpreterExecState*) KJS_FAST_CALL;
private:
- ALWAYS_INLINE JSValue* inlineEvaluate(ExecState*);
+ ALWAYS_INLINE JSValue* inlineEvaluate(OldInterpreterExecState*);
};
class NonLocalVarFunctionCallNode : public FunctionCallResolveNode {
@@ -842,14 +915,14 @@
m_scopeDepth = depth;
}
- virtual JSValue* evaluate(ExecState*) KJS_FAST_CALL;
- virtual bool evaluateToBoolean(ExecState*) KJS_FAST_CALL;
- virtual double evaluateToNumber(ExecState*) KJS_FAST_CALL;
- virtual int32_t evaluateToInt32(ExecState*) KJS_FAST_CALL;
- virtual uint32_t evaluateToUInt32(ExecState*) KJS_FAST_CALL;
+ virtual JSValue* evaluate(OldInterpreterExecState*) KJS_FAST_CALL;
+ virtual bool evaluateToBoolean(OldInterpreterExecState*) KJS_FAST_CALL;
+ virtual double evaluateToNumber(OldInterpreterExecState*) KJS_FAST_CALL;
+ virtual int32_t evaluateToInt32(OldInterpreterExecState*) KJS_FAST_CALL;
+ virtual uint32_t evaluateToUInt32(OldInterpreterExecState*) KJS_FAST_CALL;
private:
- ALWAYS_INLINE JSValue* inlineEvaluate(ExecState*);
+ ALWAYS_INLINE JSValue* inlineEvaluate(OldInterpreterExecState*);
};
class FunctionCallBracketNode : public ExpressionNode {
@@ -861,8 +934,9 @@
{
}
- virtual void optimizeVariableAccess(ExecState*, const SymbolTable&, const LocalStorage&, NodeStack&) KJS_FAST_CALL;
- virtual JSValue* evaluate(ExecState*) KJS_FAST_CALL;
+ virtual RegisterID* emitCode(CodeGenerator&, RegisterID* = 0) KJS_FAST_CALL;
+ virtual void optimizeVariableAccess(OldInterpreterExecState*, const SymbolTable&, const LocalStorage&, NodeStack&) KJS_FAST_CALL;
+ virtual JSValue* evaluate(OldInterpreterExecState*) KJS_FAST_CALL;
virtual void streamTo(SourceStream&) const KJS_FAST_CALL;
virtual Precedence precedence() const { return PrecCall; }
@@ -881,17 +955,18 @@
{
}
- virtual void optimizeVariableAccess(ExecState*, const SymbolTable&, const LocalStorage&, NodeStack&) KJS_FAST_CALL;
- virtual JSValue* evaluate(ExecState*) KJS_FAST_CALL;
- virtual bool evaluateToBoolean(ExecState*) KJS_FAST_CALL;
- virtual double evaluateToNumber(ExecState*) KJS_FAST_CALL;
- virtual int32_t evaluateToInt32(ExecState*) KJS_FAST_CALL;
- virtual uint32_t evaluateToUInt32(ExecState*) KJS_FAST_CALL;
+ virtual RegisterID* emitCode(CodeGenerator&, RegisterID* = 0) KJS_FAST_CALL;
+ virtual void optimizeVariableAccess(OldInterpreterExecState*, const SymbolTable&, const LocalStorage&, NodeStack&) KJS_FAST_CALL;
+ virtual JSValue* evaluate(OldInterpreterExecState*) KJS_FAST_CALL;
+ virtual bool evaluateToBoolean(OldInterpreterExecState*) KJS_FAST_CALL;
+ virtual double evaluateToNumber(OldInterpreterExecState*) KJS_FAST_CALL;
+ virtual int32_t evaluateToInt32(OldInterpreterExecState*) KJS_FAST_CALL;
+ virtual uint32_t evaluateToUInt32(OldInterpreterExecState*) KJS_FAST_CALL;
virtual void streamTo(SourceStream&) const KJS_FAST_CALL;
virtual Precedence precedence() const { return PrecCall; }
private:
- ALWAYS_INLINE JSValue* inlineEvaluate(ExecState*);
+ ALWAYS_INLINE JSValue* inlineEvaluate(OldInterpreterExecState*);
RefPtr<ExpressionNode> m_base;
Identifier m_ident;
@@ -929,8 +1004,9 @@
{
}
- virtual void optimizeVariableAccess(ExecState*, const SymbolTable&, const LocalStorage&, NodeStack&) KJS_FAST_CALL;
- virtual JSValue* evaluate(ExecState*) KJS_FAST_CALL;
+ virtual RegisterID* emitCode(CodeGenerator&, RegisterID* = 0) KJS_FAST_CALL;
+ virtual void optimizeVariableAccess(OldInterpreterExecState*, const SymbolTable&, const LocalStorage&, NodeStack&) KJS_FAST_CALL;
+ virtual JSValue* evaluate(OldInterpreterExecState*) KJS_FAST_CALL;
virtual void streamTo(SourceStream&) const KJS_FAST_CALL;
virtual Precedence precedence() const { return PrecPostfix; }
virtual void optimizeForUnnecessaryResult();
@@ -938,27 +1014,27 @@
class PostIncLocalVarNode : public PostIncResolveNode {
public:
- PostIncLocalVarNode(size_t i) KJS_FAST_CALL
+ PostIncLocalVarNode(int i) KJS_FAST_CALL
: PostIncResolveNode(PlacementNewAdopt)
{
ASSERT(i != missingSymbolMarker());
m_index = i;
}
- virtual JSValue* evaluate(ExecState*) KJS_FAST_CALL;
+ virtual JSValue* evaluate(OldInterpreterExecState*) KJS_FAST_CALL;
virtual void optimizeForUnnecessaryResult();
};
class PostIncConstNode : public PostIncResolveNode {
public:
- PostIncConstNode(size_t i) KJS_FAST_CALL
+ PostIncConstNode(int i) KJS_FAST_CALL
: PostIncResolveNode(PlacementNewAdopt)
{
ASSERT(i != missingSymbolMarker());
m_index = i;
}
- virtual JSValue* evaluate(ExecState*) KJS_FAST_CALL;
+ virtual JSValue* evaluate(OldInterpreterExecState*) KJS_FAST_CALL;
};
class PostDecResolveNode : public PrePostResolveNode {
@@ -973,8 +1049,10 @@
{
}
- virtual void optimizeVariableAccess(ExecState*, const SymbolTable&, const LocalStorage&, NodeStack&) KJS_FAST_CALL;
- virtual JSValue* evaluate(ExecState*) KJS_FAST_CALL;
+ virtual RegisterID* emitCode(CodeGenerator&, RegisterID* = 0) KJS_FAST_CALL;
+
+ virtual void optimizeVariableAccess(OldInterpreterExecState*, const SymbolTable&, const LocalStorage&, NodeStack&) KJS_FAST_CALL;
+ virtual JSValue* evaluate(OldInterpreterExecState*) KJS_FAST_CALL;
virtual void streamTo(SourceStream&) const KJS_FAST_CALL;
virtual Precedence precedence() const { return PrecPostfix; }
virtual void optimizeForUnnecessaryResult();
@@ -982,34 +1060,34 @@
class PostDecLocalVarNode : public PostDecResolveNode {
public:
- PostDecLocalVarNode(size_t i) KJS_FAST_CALL
+ PostDecLocalVarNode(int i) KJS_FAST_CALL
: PostDecResolveNode(PlacementNewAdopt)
{
ASSERT(i != missingSymbolMarker());
m_index = i;
}
- virtual JSValue* evaluate(ExecState*) KJS_FAST_CALL;
- virtual bool evaluateToBoolean(ExecState*) KJS_FAST_CALL;
- virtual double evaluateToNumber(ExecState*) KJS_FAST_CALL;
- virtual int32_t evaluateToInt32(ExecState*) KJS_FAST_CALL;
- virtual uint32_t evaluateToUInt32(ExecState*) KJS_FAST_CALL;
+ virtual JSValue* evaluate(OldInterpreterExecState*) KJS_FAST_CALL;
+ virtual bool evaluateToBoolean(OldInterpreterExecState*) KJS_FAST_CALL;
+ virtual double evaluateToNumber(OldInterpreterExecState*) KJS_FAST_CALL;
+ virtual int32_t evaluateToInt32(OldInterpreterExecState*) KJS_FAST_CALL;
+ virtual uint32_t evaluateToUInt32(OldInterpreterExecState*) KJS_FAST_CALL;
virtual void optimizeForUnnecessaryResult();
private:
- ALWAYS_INLINE double inlineEvaluateToNumber(ExecState*);
+ ALWAYS_INLINE double inlineEvaluateToNumber(OldInterpreterExecState*);
};
class PostDecConstNode : public PostDecResolveNode {
public:
- PostDecConstNode(size_t i) KJS_FAST_CALL
+ PostDecConstNode(int i) KJS_FAST_CALL
: PostDecResolveNode(PlacementNewAdopt)
{
ASSERT(i != missingSymbolMarker());
m_index = i;
}
- virtual JSValue* evaluate(ExecState*) KJS_FAST_CALL;
+ virtual JSValue* evaluate(OldInterpreterExecState*) KJS_FAST_CALL;
};
class PostfixBracketNode : public ExpressionNode {
@@ -1020,7 +1098,7 @@
{
}
- virtual void optimizeVariableAccess(ExecState*, const SymbolTable&, const LocalStorage&, NodeStack&) KJS_FAST_CALL;
+ virtual void optimizeVariableAccess(OldInterpreterExecState*, const SymbolTable&, const LocalStorage&, NodeStack&) KJS_FAST_CALL;
virtual Precedence precedence() const { return PrecPostfix; }
protected:
@@ -1035,7 +1113,9 @@
{
}
- virtual JSValue* evaluate(ExecState*) KJS_FAST_CALL;
+ virtual RegisterID* emitCode(CodeGenerator&, RegisterID* = 0) KJS_FAST_CALL;
+
+ virtual JSValue* evaluate(OldInterpreterExecState*) KJS_FAST_CALL;
virtual void streamTo(SourceStream&) const KJS_FAST_CALL;
};
@@ -1046,7 +1126,9 @@
{
}
- virtual JSValue* evaluate(ExecState*) KJS_FAST_CALL;
+ virtual RegisterID* emitCode(CodeGenerator&, RegisterID* = 0) KJS_FAST_CALL;
+
+ virtual JSValue* evaluate(OldInterpreterExecState*) KJS_FAST_CALL;
virtual void streamTo(SourceStream&) const KJS_FAST_CALL;
};
@@ -1058,7 +1140,7 @@
{
}
- virtual void optimizeVariableAccess(ExecState*, const SymbolTable&, const LocalStorage&, NodeStack&) KJS_FAST_CALL;
+ virtual void optimizeVariableAccess(OldInterpreterExecState*, const SymbolTable&, const LocalStorage&, NodeStack&) KJS_FAST_CALL;
virtual Precedence precedence() const { return PrecPostfix; }
protected:
@@ -1073,7 +1155,9 @@
{
}
- virtual JSValue* evaluate(ExecState*) KJS_FAST_CALL;
+ virtual RegisterID* emitCode(CodeGenerator&, RegisterID* = 0) KJS_FAST_CALL;
+
+ virtual JSValue* evaluate(OldInterpreterExecState*) KJS_FAST_CALL;
virtual void streamTo(SourceStream&) const KJS_FAST_CALL;
};
@@ -1084,7 +1168,9 @@
{
}
- virtual JSValue* evaluate(ExecState*) KJS_FAST_CALL;
+ virtual RegisterID* emitCode(CodeGenerator&, RegisterID* = 0) KJS_FAST_CALL;
+
+ virtual JSValue* evaluate(OldInterpreterExecState*) KJS_FAST_CALL;
virtual void streamTo(SourceStream&) const KJS_FAST_CALL;
};
@@ -1096,7 +1182,8 @@
{
}
- virtual JSValue* evaluate(ExecState*) KJS_FAST_CALL;
+ virtual RegisterID* emitCode(CodeGenerator&, RegisterID* = 0) KJS_FAST_CALL;
+ virtual JSValue* evaluate(OldInterpreterExecState*) KJS_FAST_CALL;
virtual void streamTo(SourceStream&) const KJS_FAST_CALL;
virtual Precedence precedence() const { return PrecPostfix; }
@@ -1118,8 +1205,10 @@
{
}
- virtual void optimizeVariableAccess(ExecState*, const SymbolTable&, const LocalStorage&, NodeStack&) KJS_FAST_CALL;
- virtual JSValue* evaluate(ExecState*) KJS_FAST_CALL;
+ virtual RegisterID* emitCode(CodeGenerator&, RegisterID* = 0) KJS_FAST_CALL;
+
+ virtual void optimizeVariableAccess(OldInterpreterExecState*, const SymbolTable&, const LocalStorage&, NodeStack&) KJS_FAST_CALL;
+ virtual JSValue* evaluate(OldInterpreterExecState*) KJS_FAST_CALL;
virtual void streamTo(SourceStream&) const KJS_FAST_CALL;
virtual Precedence precedence() const { return PrecUnary; }
@@ -1134,7 +1223,7 @@
{
}
- virtual JSValue* evaluate(ExecState*) KJS_FAST_CALL;
+ virtual JSValue* evaluate(OldInterpreterExecState*) KJS_FAST_CALL;
};
class DeleteBracketNode : public ExpressionNode {
@@ -1145,8 +1234,10 @@
{
}
- virtual void optimizeVariableAccess(ExecState*, const SymbolTable&, const LocalStorage&, NodeStack&) KJS_FAST_CALL;
- virtual JSValue* evaluate(ExecState*) KJS_FAST_CALL;
+ virtual RegisterID* emitCode(CodeGenerator&, RegisterID* = 0) KJS_FAST_CALL;
+
+ virtual void optimizeVariableAccess(OldInterpreterExecState*, const SymbolTable&, const LocalStorage&, NodeStack&) KJS_FAST_CALL;
+ virtual JSValue* evaluate(OldInterpreterExecState*) KJS_FAST_CALL;
virtual void streamTo(SourceStream&) const KJS_FAST_CALL;
virtual Precedence precedence() const { return PrecUnary; }
@@ -1163,8 +1254,10 @@
{
}
- virtual void optimizeVariableAccess(ExecState*, const SymbolTable&, const LocalStorage&, NodeStack&) KJS_FAST_CALL;
- virtual JSValue* evaluate(ExecState*) KJS_FAST_CALL;
+ virtual RegisterID* emitCode(CodeGenerator&, RegisterID* = 0) KJS_FAST_CALL;
+
+ virtual void optimizeVariableAccess(OldInterpreterExecState*, const SymbolTable&, const LocalStorage&, NodeStack&) KJS_FAST_CALL;
+ virtual JSValue* evaluate(OldInterpreterExecState*) KJS_FAST_CALL;
virtual void streamTo(SourceStream&) const KJS_FAST_CALL;
virtual Precedence precedence() const { return PrecUnary; }
@@ -1180,8 +1273,10 @@
{
}
- virtual void optimizeVariableAccess(ExecState*, const SymbolTable&, const LocalStorage&, NodeStack&) KJS_FAST_CALL;
- virtual JSValue* evaluate(ExecState*) KJS_FAST_CALL;
+ virtual RegisterID* emitCode(CodeGenerator&, RegisterID* = 0) KJS_FAST_CALL;
+
+ virtual void optimizeVariableAccess(OldInterpreterExecState*, const SymbolTable&, const LocalStorage&, NodeStack&) KJS_FAST_CALL;
+ virtual JSValue* evaluate(OldInterpreterExecState*) KJS_FAST_CALL;
virtual void streamTo(SourceStream&) const KJS_FAST_CALL;
virtual Precedence precedence() const { return PrecUnary; }
@@ -1196,8 +1291,10 @@
{
}
- virtual void optimizeVariableAccess(ExecState*, const SymbolTable&, const LocalStorage&, NodeStack&) KJS_FAST_CALL;
- virtual JSValue* evaluate(ExecState*) KJS_FAST_CALL;
+ virtual RegisterID* emitCode(CodeGenerator&, RegisterID* = 0) KJS_FAST_CALL;
+
+ virtual void optimizeVariableAccess(OldInterpreterExecState*, const SymbolTable&, const LocalStorage&, NodeStack&) KJS_FAST_CALL;
+ virtual JSValue* evaluate(OldInterpreterExecState*) KJS_FAST_CALL;
virtual void streamTo(SourceStream&) const KJS_FAST_CALL;
virtual Precedence precedence() const { return PrecUnary; }
@@ -1220,9 +1317,10 @@
m_expectedReturnType = StringType;
}
- virtual void optimizeVariableAccess(ExecState*, const SymbolTable&, const LocalStorage&, NodeStack&) KJS_FAST_CALL;
+ virtual RegisterID* emitCode(CodeGenerator&, RegisterID* = 0) KJS_FAST_CALL;
- virtual JSValue* evaluate(ExecState*) KJS_FAST_CALL;
+ virtual void optimizeVariableAccess(OldInterpreterExecState*, const SymbolTable&, const LocalStorage&, NodeStack&) KJS_FAST_CALL;
+ virtual JSValue* evaluate(OldInterpreterExecState*) KJS_FAST_CALL;
virtual void streamTo(SourceStream&) const KJS_FAST_CALL;
virtual Precedence precedence() const { return PrecUnary; }
@@ -1235,7 +1333,7 @@
class LocalVarTypeOfNode : public TypeOfResolveNode {
public:
- LocalVarTypeOfNode(size_t i) KJS_FAST_CALL
+ LocalVarTypeOfNode(int i) KJS_FAST_CALL
: TypeOfResolveNode(PlacementNewAdopt)
{
m_expectedReturnType = StringType;
@@ -1243,7 +1341,7 @@
m_index = i;
}
- virtual JSValue* evaluate(ExecState*) KJS_FAST_CALL;
+ virtual JSValue* evaluate(OldInterpreterExecState*) KJS_FAST_CALL;
};
class TypeOfValueNode : public ExpressionNode {
@@ -1254,8 +1352,10 @@
{
}
- virtual void optimizeVariableAccess(ExecState*, const SymbolTable&, const LocalStorage&, NodeStack&) KJS_FAST_CALL;
- virtual JSValue* evaluate(ExecState*) KJS_FAST_CALL;
+ virtual RegisterID* emitCode(CodeGenerator&, RegisterID* = 0) KJS_FAST_CALL;
+
+ virtual void optimizeVariableAccess(OldInterpreterExecState*, const SymbolTable&, const LocalStorage&, NodeStack&) KJS_FAST_CALL;
+ virtual JSValue* evaluate(OldInterpreterExecState*) KJS_FAST_CALL;
virtual void streamTo(SourceStream&) const KJS_FAST_CALL;
virtual Precedence precedence() const { return PrecUnary; }
@@ -1275,35 +1375,36 @@
{
}
- virtual void optimizeVariableAccess(ExecState*, const SymbolTable&, const LocalStorage&, NodeStack&) KJS_FAST_CALL;
+ virtual RegisterID* emitCode(CodeGenerator&, RegisterID* = 0) KJS_FAST_CALL;
- virtual JSValue* evaluate(ExecState*) KJS_FAST_CALL;
+ virtual void optimizeVariableAccess(OldInterpreterExecState*, const SymbolTable&, const LocalStorage&, NodeStack&) KJS_FAST_CALL;
+ virtual JSValue* evaluate(OldInterpreterExecState*) KJS_FAST_CALL;
virtual void streamTo(SourceStream&) const KJS_FAST_CALL;
virtual Precedence precedence() const { return PrecUnary; }
};
class PreIncLocalVarNode : public PreIncResolveNode {
public:
- PreIncLocalVarNode(size_t i) KJS_FAST_CALL
+ PreIncLocalVarNode(int i) KJS_FAST_CALL
: PreIncResolveNode(PlacementNewAdopt)
{
ASSERT(i != missingSymbolMarker());
m_index = i;
}
- virtual JSValue* evaluate(ExecState*) KJS_FAST_CALL;
+ virtual JSValue* evaluate(OldInterpreterExecState*) KJS_FAST_CALL;
};
class PreIncConstNode : public PreIncResolveNode {
public:
- PreIncConstNode(size_t i) KJS_FAST_CALL
+ PreIncConstNode(int i) KJS_FAST_CALL
: PreIncResolveNode(PlacementNewAdopt)
{
ASSERT(i != missingSymbolMarker());
m_index = i;
}
- virtual JSValue* evaluate(ExecState*) KJS_FAST_CALL;
+ virtual JSValue* evaluate(OldInterpreterExecState*) KJS_FAST_CALL;
};
class PreDecResolveNode : public PrePostResolveNode {
@@ -1318,35 +1419,36 @@
{
}
- virtual void optimizeVariableAccess(ExecState*, const SymbolTable&, const LocalStorage&, NodeStack&) KJS_FAST_CALL;
+ virtual RegisterID* emitCode(CodeGenerator&, RegisterID* = 0) KJS_FAST_CALL;
- virtual JSValue* evaluate(ExecState*) KJS_FAST_CALL;
+ virtual void optimizeVariableAccess(OldInterpreterExecState*, const SymbolTable&, const LocalStorage&, NodeStack&) KJS_FAST_CALL;
+ virtual JSValue* evaluate(OldInterpreterExecState*) KJS_FAST_CALL;
virtual void streamTo(SourceStream&) const KJS_FAST_CALL;
virtual Precedence precedence() const { return PrecUnary; }
};
class PreDecLocalVarNode : public PreDecResolveNode {
public:
- PreDecLocalVarNode(size_t i) KJS_FAST_CALL
+ PreDecLocalVarNode(int i) KJS_FAST_CALL
: PreDecResolveNode(PlacementNewAdopt)
{
ASSERT(i != missingSymbolMarker());
m_index = i;
}
- virtual JSValue* evaluate(ExecState*) KJS_FAST_CALL;
+ virtual JSValue* evaluate(OldInterpreterExecState*) KJS_FAST_CALL;
};
class PreDecConstNode : public PreDecResolveNode {
public:
- PreDecConstNode(size_t i) KJS_FAST_CALL
+ PreDecConstNode(int i) KJS_FAST_CALL
: PreDecResolveNode(PlacementNewAdopt)
{
ASSERT(i != missingSymbolMarker());
m_index = i;
}
- virtual JSValue* evaluate(ExecState*) KJS_FAST_CALL;
+ virtual JSValue* evaluate(OldInterpreterExecState*) KJS_FAST_CALL;
};
class PrefixBracketNode : public ExpressionNode {
@@ -1357,7 +1459,7 @@
{
}
- virtual void optimizeVariableAccess(ExecState*, const SymbolTable&, const LocalStorage&, NodeStack&) KJS_FAST_CALL;
+ virtual void optimizeVariableAccess(OldInterpreterExecState*, const SymbolTable&, const LocalStorage&, NodeStack&) KJS_FAST_CALL;
virtual Precedence precedence() const { return PrecUnary; }
protected:
@@ -1372,7 +1474,9 @@
{
}
- virtual JSValue* evaluate(ExecState*) KJS_FAST_CALL;
+ virtual RegisterID* emitCode(CodeGenerator&, RegisterID* = 0) KJS_FAST_CALL;
+
+ virtual JSValue* evaluate(OldInterpreterExecState*) KJS_FAST_CALL;
virtual void streamTo(SourceStream&) const KJS_FAST_CALL;
};
@@ -1383,7 +1487,9 @@
{
}
- virtual JSValue* evaluate(ExecState*) KJS_FAST_CALL;
+ virtual RegisterID* emitCode(CodeGenerator&, RegisterID* = 0) KJS_FAST_CALL;
+
+ virtual JSValue* evaluate(OldInterpreterExecState*) KJS_FAST_CALL;
virtual void streamTo(SourceStream&) const KJS_FAST_CALL;
};
@@ -1395,7 +1501,7 @@
{
}
- virtual void optimizeVariableAccess(ExecState*, const SymbolTable&, const LocalStorage&, NodeStack&) KJS_FAST_CALL;
+ virtual void optimizeVariableAccess(OldInterpreterExecState*, const SymbolTable&, const LocalStorage&, NodeStack&) KJS_FAST_CALL;
virtual Precedence precedence() const { return PrecPostfix; }
protected:
@@ -1410,7 +1516,9 @@
{
}
- virtual JSValue* evaluate(ExecState*) KJS_FAST_CALL;
+ virtual RegisterID* emitCode(CodeGenerator&, RegisterID* = 0) KJS_FAST_CALL;
+
+ virtual JSValue* evaluate(OldInterpreterExecState*) KJS_FAST_CALL;
virtual void streamTo(SourceStream&) const KJS_FAST_CALL;
};
@@ -1421,7 +1529,9 @@
{
}
- virtual JSValue* evaluate(ExecState*) KJS_FAST_CALL;
+ virtual RegisterID* emitCode(CodeGenerator&, RegisterID* = 0) KJS_FAST_CALL;
+
+ virtual JSValue* evaluate(OldInterpreterExecState*) KJS_FAST_CALL;
virtual void streamTo(SourceStream&) const KJS_FAST_CALL;
};
@@ -1433,7 +1543,8 @@
{
}
- virtual JSValue* evaluate(ExecState*) KJS_FAST_CALL;
+ virtual RegisterID* emitCode(CodeGenerator&, RegisterID* = 0) KJS_FAST_CALL;
+ virtual JSValue* evaluate(OldInterpreterExecState*) KJS_FAST_CALL;
virtual void streamTo(SourceStream&) const KJS_FAST_CALL;
virtual Precedence precedence() const { return PrecUnary; }
@@ -1450,12 +1561,13 @@
{
}
- virtual void optimizeVariableAccess(ExecState*, const SymbolTable&, const LocalStorage&, NodeStack&) KJS_FAST_CALL;
- virtual JSValue* evaluate(ExecState*) KJS_FAST_CALL;
- virtual bool evaluateToBoolean(ExecState*) KJS_FAST_CALL;
- virtual double evaluateToNumber(ExecState*) KJS_FAST_CALL;
- virtual int32_t evaluateToInt32(ExecState*) KJS_FAST_CALL;
- virtual uint32_t evaluateToUInt32(ExecState*) KJS_FAST_CALL;
+ virtual RegisterID* emitCode(CodeGenerator&, RegisterID* = 0) KJS_FAST_CALL;
+ virtual void optimizeVariableAccess(OldInterpreterExecState*, const SymbolTable&, const LocalStorage&, NodeStack&) KJS_FAST_CALL;
+ virtual JSValue* evaluate(OldInterpreterExecState*) KJS_FAST_CALL;
+ virtual bool evaluateToBoolean(OldInterpreterExecState*) KJS_FAST_CALL;
+ virtual double evaluateToNumber(OldInterpreterExecState*) KJS_FAST_CALL;
+ virtual int32_t evaluateToInt32(OldInterpreterExecState*) KJS_FAST_CALL;
+ virtual uint32_t evaluateToUInt32(OldInterpreterExecState*) KJS_FAST_CALL;
virtual void streamTo(SourceStream&) const KJS_FAST_CALL;
virtual Precedence precedence() const { return PrecUnary; }
@@ -1471,9 +1583,10 @@
{
}
- virtual void optimizeVariableAccess(ExecState*, const SymbolTable&, const LocalStorage&, NodeStack&) KJS_FAST_CALL;
- virtual JSValue* evaluate(ExecState*) KJS_FAST_CALL;
- virtual double evaluateToNumber(ExecState*) KJS_FAST_CALL;
+ virtual RegisterID* emitCode(CodeGenerator&, RegisterID* = 0) KJS_FAST_CALL;
+ virtual void optimizeVariableAccess(OldInterpreterExecState*, const SymbolTable&, const LocalStorage&, NodeStack&) KJS_FAST_CALL;
+ virtual JSValue* evaluate(OldInterpreterExecState*) KJS_FAST_CALL;
+ virtual double evaluateToNumber(OldInterpreterExecState*) KJS_FAST_CALL;
virtual void streamTo(SourceStream&) const KJS_FAST_CALL;
virtual Precedence precedence() const { return PrecUnary; }
@@ -1489,17 +1602,18 @@
{
}
- virtual void optimizeVariableAccess(ExecState*, const SymbolTable&, const LocalStorage&, NodeStack&) KJS_FAST_CALL;
- virtual JSValue* evaluate(ExecState*) KJS_FAST_CALL;
- virtual double evaluateToNumber(ExecState*) KJS_FAST_CALL;
- virtual bool evaluateToBoolean(ExecState*) KJS_FAST_CALL;
- virtual int32_t evaluateToInt32(ExecState*) KJS_FAST_CALL;
- virtual uint32_t evaluateToUInt32(ExecState*) KJS_FAST_CALL;
+ virtual RegisterID* emitCode(CodeGenerator&, RegisterID* = 0) KJS_FAST_CALL;
+ virtual void optimizeVariableAccess(OldInterpreterExecState*, const SymbolTable&, const LocalStorage&, NodeStack&) KJS_FAST_CALL;
+ virtual JSValue* evaluate(OldInterpreterExecState*) KJS_FAST_CALL;
+ virtual double evaluateToNumber(OldInterpreterExecState*) KJS_FAST_CALL;
+ virtual bool evaluateToBoolean(OldInterpreterExecState*) KJS_FAST_CALL;
+ virtual int32_t evaluateToInt32(OldInterpreterExecState*) KJS_FAST_CALL;
+ virtual uint32_t evaluateToUInt32(OldInterpreterExecState*) KJS_FAST_CALL;
virtual void streamTo(SourceStream&) const KJS_FAST_CALL;
virtual Precedence precedence() const { return PrecUnary; }
private:
- ALWAYS_INLINE int32_t inlineEvaluateToInt32(ExecState*);
+ ALWAYS_INLINE int32_t inlineEvaluateToInt32(OldInterpreterExecState*);
RefPtr<ExpressionNode> m_expr;
};
@@ -1512,9 +1626,10 @@
{
}
- virtual void optimizeVariableAccess(ExecState*, const SymbolTable&, const LocalStorage&, NodeStack&) KJS_FAST_CALL;
- virtual JSValue* evaluate(ExecState*) KJS_FAST_CALL;
- virtual bool evaluateToBoolean(ExecState*) KJS_FAST_CALL;
+ virtual RegisterID* emitCode(CodeGenerator&, RegisterID* = 0) KJS_FAST_CALL;
+ virtual void optimizeVariableAccess(OldInterpreterExecState*, const SymbolTable&, const LocalStorage&, NodeStack&) KJS_FAST_CALL;
+ virtual JSValue* evaluate(OldInterpreterExecState*) KJS_FAST_CALL;
+ virtual bool evaluateToBoolean(OldInterpreterExecState*) KJS_FAST_CALL;
virtual void streamTo(SourceStream&) const KJS_FAST_CALL;
virtual Precedence precedence() const { return PrecUnary; }
@@ -1531,17 +1646,18 @@
{
}
- virtual void optimizeVariableAccess(ExecState*, const SymbolTable&, const LocalStorage&, NodeStack&) KJS_FAST_CALL;
- virtual JSValue* evaluate(ExecState*) KJS_FAST_CALL;
- virtual double evaluateToNumber(ExecState*) KJS_FAST_CALL;
- virtual bool evaluateToBoolean(ExecState*) KJS_FAST_CALL;
- virtual int32_t evaluateToInt32(ExecState*) KJS_FAST_CALL;
- virtual uint32_t evaluateToUInt32(ExecState*) KJS_FAST_CALL;
+ virtual RegisterID* emitCode(CodeGenerator&, RegisterID* = 0) KJS_FAST_CALL;
+ virtual void optimizeVariableAccess(OldInterpreterExecState*, const SymbolTable&, const LocalStorage&, NodeStack&) KJS_FAST_CALL;
+ virtual JSValue* evaluate(OldInterpreterExecState*) KJS_FAST_CALL;
+ virtual double evaluateToNumber(OldInterpreterExecState*) KJS_FAST_CALL;
+ virtual bool evaluateToBoolean(OldInterpreterExecState*) KJS_FAST_CALL;
+ virtual int32_t evaluateToInt32(OldInterpreterExecState*) KJS_FAST_CALL;
+ virtual uint32_t evaluateToUInt32(OldInterpreterExecState*) KJS_FAST_CALL;
virtual void streamTo(SourceStream&) const KJS_FAST_CALL;
virtual Precedence precedence() const { return PrecMultiplicitave; }
private:
- ALWAYS_INLINE double inlineEvaluateToNumber(ExecState*);
+ ALWAYS_INLINE double inlineEvaluateToNumber(OldInterpreterExecState*);
RefPtr<ExpressionNode> m_term1;
RefPtr<ExpressionNode> m_term2;
@@ -1556,16 +1672,17 @@
{
}
- virtual void optimizeVariableAccess(ExecState*, const SymbolTable&, const LocalStorage&, NodeStack&) KJS_FAST_CALL;
- virtual JSValue* evaluate(ExecState*) KJS_FAST_CALL;
- virtual double evaluateToNumber(ExecState*) KJS_FAST_CALL;
- virtual int32_t evaluateToInt32(ExecState*) KJS_FAST_CALL;
- virtual uint32_t evaluateToUInt32(ExecState*) KJS_FAST_CALL;
+ virtual RegisterID* emitCode(CodeGenerator&, RegisterID* = 0) KJS_FAST_CALL;
+ virtual void optimizeVariableAccess(OldInterpreterExecState*, const SymbolTable&, const LocalStorage&, NodeStack&) KJS_FAST_CALL;
+ virtual JSValue* evaluate(OldInterpreterExecState*) KJS_FAST_CALL;
+ virtual double evaluateToNumber(OldInterpreterExecState*) KJS_FAST_CALL;
+ virtual int32_t evaluateToInt32(OldInterpreterExecState*) KJS_FAST_CALL;
+ virtual uint32_t evaluateToUInt32(OldInterpreterExecState*) KJS_FAST_CALL;
virtual void streamTo(SourceStream&) const KJS_FAST_CALL;
virtual Precedence precedence() const { return PrecMultiplicitave; }
private:
- ALWAYS_INLINE double inlineEvaluateToNumber(ExecState*);
+ ALWAYS_INLINE double inlineEvaluateToNumber(OldInterpreterExecState*);
RefPtr<ExpressionNode> m_term1;
RefPtr<ExpressionNode> m_term2;
@@ -1580,17 +1697,18 @@
{
}
- virtual void optimizeVariableAccess(ExecState*, const SymbolTable&, const LocalStorage&, NodeStack&) KJS_FAST_CALL;
- virtual JSValue* evaluate(ExecState*) KJS_FAST_CALL;
- virtual double evaluateToNumber(ExecState*) KJS_FAST_CALL;
- virtual bool evaluateToBoolean(ExecState*) KJS_FAST_CALL;
- virtual int32_t evaluateToInt32(ExecState*) KJS_FAST_CALL;
- virtual uint32_t evaluateToUInt32(ExecState*) KJS_FAST_CALL;
+ virtual RegisterID* emitCode(CodeGenerator&, RegisterID* = 0) KJS_FAST_CALL;
+ virtual void optimizeVariableAccess(OldInterpreterExecState*, const SymbolTable&, const LocalStorage&, NodeStack&) KJS_FAST_CALL;
+ virtual JSValue* evaluate(OldInterpreterExecState*) KJS_FAST_CALL;
+ virtual double evaluateToNumber(OldInterpreterExecState*) KJS_FAST_CALL;
+ virtual bool evaluateToBoolean(OldInterpreterExecState*) KJS_FAST_CALL;
+ virtual int32_t evaluateToInt32(OldInterpreterExecState*) KJS_FAST_CALL;
+ virtual uint32_t evaluateToUInt32(OldInterpreterExecState*) KJS_FAST_CALL;
virtual void streamTo(SourceStream&) const KJS_FAST_CALL;
virtual Precedence precedence() const { return PrecMultiplicitave; }
private:
- ALWAYS_INLINE double inlineEvaluateToNumber(ExecState*);
+ ALWAYS_INLINE double inlineEvaluateToNumber(OldInterpreterExecState*);
RefPtr<ExpressionNode> m_term1;
RefPtr<ExpressionNode> m_term2;
@@ -1604,11 +1722,12 @@
{
}
- virtual void optimizeVariableAccess(ExecState*, const SymbolTable&, const LocalStorage&, NodeStack&) KJS_FAST_CALL;
- virtual JSValue* evaluate(ExecState*) KJS_FAST_CALL;
- virtual double evaluateToNumber(ExecState*) KJS_FAST_CALL;
- virtual int32_t evaluateToInt32(ExecState*) KJS_FAST_CALL;
- virtual uint32_t evaluateToUInt32(ExecState*) KJS_FAST_CALL;
+ virtual RegisterID* emitCode(CodeGenerator&, RegisterID* = 0) KJS_FAST_CALL;
+ virtual void optimizeVariableAccess(OldInterpreterExecState*, const SymbolTable&, const LocalStorage&, NodeStack&) KJS_FAST_CALL;
+ virtual JSValue* evaluate(OldInterpreterExecState*) KJS_FAST_CALL;
+ virtual double evaluateToNumber(OldInterpreterExecState*) KJS_FAST_CALL;
+ virtual int32_t evaluateToInt32(OldInterpreterExecState*) KJS_FAST_CALL;
+ virtual uint32_t evaluateToUInt32(OldInterpreterExecState*) KJS_FAST_CALL;
virtual void streamTo(SourceStream&) const KJS_FAST_CALL;
virtual Precedence precedence() const { return PrecAdditive; }
@@ -1624,7 +1743,7 @@
RefPtr<ExpressionNode> m_term2;
private:
- ALWAYS_INLINE double inlineEvaluateToNumber(ExecState*);
+ ALWAYS_INLINE double inlineEvaluateToNumber(OldInterpreterExecState*);
};
class AddNumbersNode : public AddNode {
@@ -1634,13 +1753,13 @@
{
}
- virtual JSValue* evaluate(ExecState*) KJS_FAST_CALL;
- virtual double evaluateToNumber(ExecState*) KJS_FAST_CALL;
- virtual int32_t evaluateToInt32(ExecState*) KJS_FAST_CALL;
- virtual uint32_t evaluateToUInt32(ExecState*) KJS_FAST_CALL;
+ virtual JSValue* evaluate(OldInterpreterExecState*) KJS_FAST_CALL;
+ virtual double evaluateToNumber(OldInterpreterExecState*) KJS_FAST_CALL;
+ virtual int32_t evaluateToInt32(OldInterpreterExecState*) KJS_FAST_CALL;
+ virtual uint32_t evaluateToUInt32(OldInterpreterExecState*) KJS_FAST_CALL;
private:
- ALWAYS_INLINE double inlineEvaluateToNumber(ExecState*) KJS_FAST_CALL;
+ ALWAYS_INLINE double inlineEvaluateToNumber(OldInterpreterExecState*) KJS_FAST_CALL;
};
class AddStringLeftNode : public AddNode {
@@ -1650,7 +1769,7 @@
{
}
- virtual JSValue* evaluate(ExecState*) KJS_FAST_CALL;
+ virtual JSValue* evaluate(OldInterpreterExecState*) KJS_FAST_CALL;
};
class AddStringRightNode : public AddNode {
@@ -1660,7 +1779,7 @@
{
}
- virtual JSValue* evaluate(ExecState*) KJS_FAST_CALL;
+ virtual JSValue* evaluate(OldInterpreterExecState*) KJS_FAST_CALL;
};
class AddStringsNode : public AddNode {
@@ -1670,7 +1789,7 @@
{
}
- virtual JSValue* evaluate(ExecState*) KJS_FAST_CALL;
+ virtual JSValue* evaluate(OldInterpreterExecState*) KJS_FAST_CALL;
};
class SubNode : public ExpressionNode {
@@ -1682,16 +1801,17 @@
{
}
- virtual void optimizeVariableAccess(ExecState*, const SymbolTable&, const LocalStorage&, NodeStack&) KJS_FAST_CALL;
- virtual JSValue* evaluate(ExecState*) KJS_FAST_CALL;
- virtual double evaluateToNumber(ExecState*) KJS_FAST_CALL;
- virtual int32_t evaluateToInt32(ExecState*) KJS_FAST_CALL;
- virtual uint32_t evaluateToUInt32(ExecState*) KJS_FAST_CALL;
+ virtual RegisterID* emitCode(CodeGenerator&, RegisterID* = 0) KJS_FAST_CALL;
+ virtual void optimizeVariableAccess(OldInterpreterExecState*, const SymbolTable&, const LocalStorage&, NodeStack&) KJS_FAST_CALL;
+ virtual JSValue* evaluate(OldInterpreterExecState*) KJS_FAST_CALL;
+ virtual double evaluateToNumber(OldInterpreterExecState*) KJS_FAST_CALL;
+ virtual int32_t evaluateToInt32(OldInterpreterExecState*) KJS_FAST_CALL;
+ virtual uint32_t evaluateToUInt32(OldInterpreterExecState*) KJS_FAST_CALL;
virtual void streamTo(SourceStream&) const KJS_FAST_CALL;
virtual Precedence precedence() const { return PrecAdditive; }
private:
- ALWAYS_INLINE double inlineEvaluateToNumber(ExecState*);
+ ALWAYS_INLINE double inlineEvaluateToNumber(OldInterpreterExecState*);
RefPtr<ExpressionNode> m_term1;
RefPtr<ExpressionNode> m_term2;
@@ -1706,16 +1826,17 @@
{
}
- virtual void optimizeVariableAccess(ExecState*, const SymbolTable&, const LocalStorage&, NodeStack&) KJS_FAST_CALL;
- virtual JSValue* evaluate(ExecState*) KJS_FAST_CALL;
- virtual double evaluateToNumber(ExecState*) KJS_FAST_CALL;
- virtual int32_t evaluateToInt32(ExecState*) KJS_FAST_CALL;
- virtual uint32_t evaluateToUInt32(ExecState*) KJS_FAST_CALL;
+ virtual RegisterID* emitCode(CodeGenerator&, RegisterID* = 0) KJS_FAST_CALL;
+ virtual void optimizeVariableAccess(OldInterpreterExecState*, const SymbolTable&, const LocalStorage&, NodeStack&) KJS_FAST_CALL;
+ virtual JSValue* evaluate(OldInterpreterExecState*) KJS_FAST_CALL;
+ virtual double evaluateToNumber(OldInterpreterExecState*) KJS_FAST_CALL;
+ virtual int32_t evaluateToInt32(OldInterpreterExecState*) KJS_FAST_CALL;
+ virtual uint32_t evaluateToUInt32(OldInterpreterExecState*) KJS_FAST_CALL;
virtual void streamTo(SourceStream&) const KJS_FAST_CALL;
virtual Precedence precedence() const { return PrecShift; }
private:
- ALWAYS_INLINE int32_t inlineEvaluateToInt32(ExecState*);
+ ALWAYS_INLINE int32_t inlineEvaluateToInt32(OldInterpreterExecState*);
RefPtr<ExpressionNode> m_term1;
RefPtr<ExpressionNode> m_term2;
@@ -1730,16 +1851,17 @@
{
}
- virtual void optimizeVariableAccess(ExecState*, const SymbolTable&, const LocalStorage&, NodeStack&) KJS_FAST_CALL;
- virtual JSValue* evaluate(ExecState*) KJS_FAST_CALL;
- virtual double evaluateToNumber(ExecState*) KJS_FAST_CALL;
- virtual int32_t evaluateToInt32(ExecState*) KJS_FAST_CALL;
- virtual uint32_t evaluateToUInt32(ExecState*) KJS_FAST_CALL;
+ virtual RegisterID* emitCode(CodeGenerator&, RegisterID* = 0) KJS_FAST_CALL;
+ virtual void optimizeVariableAccess(OldInterpreterExecState*, const SymbolTable&, const LocalStorage&, NodeStack&) KJS_FAST_CALL;
+ virtual JSValue* evaluate(OldInterpreterExecState*) KJS_FAST_CALL;
+ virtual double evaluateToNumber(OldInterpreterExecState*) KJS_FAST_CALL;
+ virtual int32_t evaluateToInt32(OldInterpreterExecState*) KJS_FAST_CALL;
+ virtual uint32_t evaluateToUInt32(OldInterpreterExecState*) KJS_FAST_CALL;
virtual void streamTo(SourceStream&) const KJS_FAST_CALL;
virtual Precedence precedence() const { return PrecShift; }
private:
- ALWAYS_INLINE int32_t inlineEvaluateToInt32(ExecState*);
+ ALWAYS_INLINE int32_t inlineEvaluateToInt32(OldInterpreterExecState*);
RefPtr<ExpressionNode> m_term1;
RefPtr<ExpressionNode> m_term2;
@@ -1754,15 +1876,16 @@
{
}
- virtual void optimizeVariableAccess(ExecState*, const SymbolTable&, const LocalStorage&, NodeStack&) KJS_FAST_CALL;
- virtual JSValue* evaluate(ExecState*) KJS_FAST_CALL;
- virtual double evaluateToNumber(ExecState*) KJS_FAST_CALL;
- virtual int32_t evaluateToInt32(ExecState*) KJS_FAST_CALL;
- virtual uint32_t evaluateToUInt32(ExecState*) KJS_FAST_CALL;
+ virtual RegisterID* emitCode(CodeGenerator&, RegisterID* = 0) KJS_FAST_CALL;
+ virtual void optimizeVariableAccess(OldInterpreterExecState*, const SymbolTable&, const LocalStorage&, NodeStack&) KJS_FAST_CALL;
+ virtual JSValue* evaluate(OldInterpreterExecState*) KJS_FAST_CALL;
+ virtual double evaluateToNumber(OldInterpreterExecState*) KJS_FAST_CALL;
+ virtual int32_t evaluateToInt32(OldInterpreterExecState*) KJS_FAST_CALL;
+ virtual uint32_t evaluateToUInt32(OldInterpreterExecState*) KJS_FAST_CALL;
virtual void streamTo(SourceStream&) const KJS_FAST_CALL;
virtual Precedence precedence() const { return PrecShift; }
private:
- ALWAYS_INLINE uint32_t inlineEvaluateToUInt32(ExecState*);
+ ALWAYS_INLINE uint32_t inlineEvaluateToUInt32(OldInterpreterExecState*);
RefPtr<ExpressionNode> m_term1;
RefPtr<ExpressionNode> m_term2;
@@ -1777,14 +1900,15 @@
{
}
- virtual void optimizeVariableAccess(ExecState*, const SymbolTable&, const LocalStorage&, NodeStack&) KJS_FAST_CALL;
- virtual JSValue* evaluate(ExecState*) KJS_FAST_CALL;
- virtual bool evaluateToBoolean(ExecState*) KJS_FAST_CALL;
+ virtual RegisterID* emitCode(CodeGenerator&, RegisterID* = 0) KJS_FAST_CALL;
+ virtual void optimizeVariableAccess(OldInterpreterExecState*, const SymbolTable&, const LocalStorage&, NodeStack&) KJS_FAST_CALL;
+ virtual JSValue* evaluate(OldInterpreterExecState*) KJS_FAST_CALL;
+ virtual bool evaluateToBoolean(OldInterpreterExecState*) KJS_FAST_CALL;
virtual void streamTo(SourceStream&) const KJS_FAST_CALL;
virtual Precedence precedence() const { return PrecRelational; }
private:
- ALWAYS_INLINE bool inlineEvaluateToBoolean(ExecState*);
+ ALWAYS_INLINE bool inlineEvaluateToBoolean(OldInterpreterExecState*);
protected:
RefPtr<ExpressionNode> m_expr1;
@@ -1798,11 +1922,11 @@
{
}
- virtual JSValue* evaluate(ExecState*) KJS_FAST_CALL;
- virtual bool evaluateToBoolean(ExecState*) KJS_FAST_CALL;
+ virtual JSValue* evaluate(OldInterpreterExecState*) KJS_FAST_CALL;
+ virtual bool evaluateToBoolean(OldInterpreterExecState*) KJS_FAST_CALL;
private:
- ALWAYS_INLINE bool inlineEvaluateToBoolean(ExecState*);
+ ALWAYS_INLINE bool inlineEvaluateToBoolean(OldInterpreterExecState*);
};
class LessStringsNode : public LessNode {
@@ -1812,11 +1936,11 @@
{
}
- virtual JSValue* evaluate(ExecState*) KJS_FAST_CALL;
- virtual bool evaluateToBoolean(ExecState*) KJS_FAST_CALL;
+ virtual JSValue* evaluate(OldInterpreterExecState*) KJS_FAST_CALL;
+ virtual bool evaluateToBoolean(OldInterpreterExecState*) KJS_FAST_CALL;
private:
- ALWAYS_INLINE bool inlineEvaluateToBoolean(ExecState*);
+ ALWAYS_INLINE bool inlineEvaluateToBoolean(OldInterpreterExecState*);
};
class GreaterNode : public ExpressionNode {
@@ -1827,14 +1951,15 @@
{
}
- virtual void optimizeVariableAccess(ExecState*, const SymbolTable&, const LocalStorage&, NodeStack&) KJS_FAST_CALL;
- virtual JSValue* evaluate(ExecState*) KJS_FAST_CALL;
- virtual bool evaluateToBoolean(ExecState*) KJS_FAST_CALL;
+ virtual RegisterID* emitCode(CodeGenerator&, RegisterID* = 0) KJS_FAST_CALL;
+ virtual void optimizeVariableAccess(OldInterpreterExecState*, const SymbolTable&, const LocalStorage&, NodeStack&) KJS_FAST_CALL;
+ virtual JSValue* evaluate(OldInterpreterExecState*) KJS_FAST_CALL;
+ virtual bool evaluateToBoolean(OldInterpreterExecState*) KJS_FAST_CALL;
virtual void streamTo(SourceStream&) const KJS_FAST_CALL;
virtual Precedence precedence() const { return PrecRelational; }
private:
- ALWAYS_INLINE bool inlineEvaluateToBoolean(ExecState*);
+ ALWAYS_INLINE bool inlineEvaluateToBoolean(OldInterpreterExecState*);
RefPtr<ExpressionNode> m_expr1;
RefPtr<ExpressionNode> m_expr2;
@@ -1848,14 +1973,15 @@
{
}
- virtual void optimizeVariableAccess(ExecState*, const SymbolTable&, const LocalStorage&, NodeStack&) KJS_FAST_CALL;
- virtual JSValue* evaluate(ExecState*) KJS_FAST_CALL;
- virtual bool evaluateToBoolean(ExecState*) KJS_FAST_CALL;
+ virtual RegisterID* emitCode(CodeGenerator&, RegisterID* = 0) KJS_FAST_CALL;
+ virtual void optimizeVariableAccess(OldInterpreterExecState*, const SymbolTable&, const LocalStorage&, NodeStack&) KJS_FAST_CALL;
+ virtual JSValue* evaluate(OldInterpreterExecState*) KJS_FAST_CALL;
+ virtual bool evaluateToBoolean(OldInterpreterExecState*) KJS_FAST_CALL;
virtual void streamTo(SourceStream&) const KJS_FAST_CALL;
virtual Precedence precedence() const { return PrecRelational; }
private:
- ALWAYS_INLINE bool inlineEvaluateToBoolean(ExecState*);
+ ALWAYS_INLINE bool inlineEvaluateToBoolean(OldInterpreterExecState*);
RefPtr<ExpressionNode> m_expr1;
RefPtr<ExpressionNode> m_expr2;
@@ -1869,14 +1995,15 @@
{
}
- virtual void optimizeVariableAccess(ExecState*, const SymbolTable&, const LocalStorage&, NodeStack&) KJS_FAST_CALL;
- virtual JSValue* evaluate(ExecState*) KJS_FAST_CALL;
- virtual bool evaluateToBoolean(ExecState*) KJS_FAST_CALL;
+ virtual RegisterID* emitCode(CodeGenerator&, RegisterID* = 0) KJS_FAST_CALL;
+ virtual void optimizeVariableAccess(OldInterpreterExecState*, const SymbolTable&, const LocalStorage&, NodeStack&) KJS_FAST_CALL;
+ virtual JSValue* evaluate(OldInterpreterExecState*) KJS_FAST_CALL;
+ virtual bool evaluateToBoolean(OldInterpreterExecState*) KJS_FAST_CALL;
virtual void streamTo(SourceStream&) const KJS_FAST_CALL;
virtual Precedence precedence() const { return PrecRelational; }
private:
- ALWAYS_INLINE bool inlineEvaluateToBoolean(ExecState*);
+ ALWAYS_INLINE bool inlineEvaluateToBoolean(OldInterpreterExecState*);
RefPtr<ExpressionNode> m_expr1;
RefPtr<ExpressionNode> m_expr2;
@@ -1891,9 +2018,10 @@
{
}
- virtual void optimizeVariableAccess(ExecState*, const SymbolTable&, const LocalStorage&, NodeStack&) KJS_FAST_CALL;
- virtual JSValue* evaluate(ExecState*) KJS_FAST_CALL;
- virtual bool evaluateToBoolean(ExecState*) KJS_FAST_CALL;
+ virtual RegisterID* emitCode(CodeGenerator&, RegisterID* = 0) KJS_FAST_CALL;
+ virtual void optimizeVariableAccess(OldInterpreterExecState*, const SymbolTable&, const LocalStorage&, NodeStack&) KJS_FAST_CALL;
+ virtual JSValue* evaluate(OldInterpreterExecState*) KJS_FAST_CALL;
+ virtual bool evaluateToBoolean(OldInterpreterExecState*) KJS_FAST_CALL;
virtual void streamTo(SourceStream&) const KJS_FAST_CALL;
virtual Precedence precedence() const { return PrecRelational; }
@@ -1910,9 +2038,11 @@
{
}
- virtual void optimizeVariableAccess(ExecState*, const SymbolTable&, const LocalStorage&, NodeStack&) KJS_FAST_CALL;
- virtual JSValue* evaluate(ExecState*) KJS_FAST_CALL;
- virtual bool evaluateToBoolean(ExecState*) KJS_FAST_CALL;
+ virtual RegisterID* emitCode(CodeGenerator&, RegisterID* = 0) KJS_FAST_CALL;
+
+ virtual void optimizeVariableAccess(OldInterpreterExecState*, const SymbolTable&, const LocalStorage&, NodeStack&) KJS_FAST_CALL;
+ virtual JSValue* evaluate(OldInterpreterExecState*) KJS_FAST_CALL;
+ virtual bool evaluateToBoolean(OldInterpreterExecState*) KJS_FAST_CALL;
virtual void streamTo(SourceStream&) const KJS_FAST_CALL;
virtual Precedence precedence() const { return PrecRelational; }
@@ -1930,14 +2060,15 @@
{
}
- virtual void optimizeVariableAccess(ExecState*, const SymbolTable&, const LocalStorage&, NodeStack&) KJS_FAST_CALL;
- virtual JSValue* evaluate(ExecState*) KJS_FAST_CALL;
- virtual bool evaluateToBoolean(ExecState*) KJS_FAST_CALL;
+ virtual RegisterID* emitCode(CodeGenerator&, RegisterID* = 0) KJS_FAST_CALL;
+ virtual void optimizeVariableAccess(OldInterpreterExecState*, const SymbolTable&, const LocalStorage&, NodeStack&) KJS_FAST_CALL;
+ virtual JSValue* evaluate(OldInterpreterExecState*) KJS_FAST_CALL;
+ virtual bool evaluateToBoolean(OldInterpreterExecState*) KJS_FAST_CALL;
virtual void streamTo(SourceStream&) const KJS_FAST_CALL;
virtual Precedence precedence() const { return PrecEquality; }
private:
- ALWAYS_INLINE bool inlineEvaluateToBoolean(ExecState*);
+ ALWAYS_INLINE bool inlineEvaluateToBoolean(OldInterpreterExecState*);
RefPtr<ExpressionNode> m_expr1;
RefPtr<ExpressionNode> m_expr2;
@@ -1952,14 +2083,15 @@
{
}
- virtual void optimizeVariableAccess(ExecState*, const SymbolTable&, const LocalStorage&, NodeStack&) KJS_FAST_CALL;
- virtual JSValue* evaluate(ExecState*) KJS_FAST_CALL;
- virtual bool evaluateToBoolean(ExecState*) KJS_FAST_CALL;
+ virtual RegisterID* emitCode(CodeGenerator&, RegisterID* = 0) KJS_FAST_CALL;
+ virtual void optimizeVariableAccess(OldInterpreterExecState*, const SymbolTable&, const LocalStorage&, NodeStack&) KJS_FAST_CALL;
+ virtual JSValue* evaluate(OldInterpreterExecState*) KJS_FAST_CALL;
+ virtual bool evaluateToBoolean(OldInterpreterExecState*) KJS_FAST_CALL;
virtual void streamTo(SourceStream&) const KJS_FAST_CALL;
virtual Precedence precedence() const { return PrecEquality; }
private:
- ALWAYS_INLINE bool inlineEvaluateToBoolean(ExecState*);
+ ALWAYS_INLINE bool inlineEvaluateToBoolean(OldInterpreterExecState*);
RefPtr<ExpressionNode> m_expr1;
RefPtr<ExpressionNode> m_expr2;
@@ -1974,14 +2106,15 @@
{
}
- virtual void optimizeVariableAccess(ExecState*, const SymbolTable&, const LocalStorage&, NodeStack&) KJS_FAST_CALL;
- virtual JSValue* evaluate(ExecState*) KJS_FAST_CALL;
- virtual bool evaluateToBoolean(ExecState*) KJS_FAST_CALL;
+ virtual RegisterID* emitCode(CodeGenerator&, RegisterID* = 0) KJS_FAST_CALL;
+ virtual void optimizeVariableAccess(OldInterpreterExecState*, const SymbolTable&, const LocalStorage&, NodeStack&) KJS_FAST_CALL;
+ virtual JSValue* evaluate(OldInterpreterExecState*) KJS_FAST_CALL;
+ virtual bool evaluateToBoolean(OldInterpreterExecState*) KJS_FAST_CALL;
virtual void streamTo(SourceStream&) const KJS_FAST_CALL;
virtual Precedence precedence() const { return PrecEquality; }
private:
- ALWAYS_INLINE bool inlineEvaluateToBoolean(ExecState*);
+ ALWAYS_INLINE bool inlineEvaluateToBoolean(OldInterpreterExecState*);
RefPtr<ExpressionNode> m_expr1;
RefPtr<ExpressionNode> m_expr2;
@@ -1996,14 +2129,15 @@
{
}
- virtual void optimizeVariableAccess(ExecState*, const SymbolTable&, const LocalStorage&, NodeStack&) KJS_FAST_CALL;
- virtual JSValue* evaluate(ExecState*) KJS_FAST_CALL;
- virtual bool evaluateToBoolean(ExecState*) KJS_FAST_CALL;
+ virtual RegisterID* emitCode(CodeGenerator&, RegisterID* = 0) KJS_FAST_CALL;
+ virtual void optimizeVariableAccess(OldInterpreterExecState*, const SymbolTable&, const LocalStorage&, NodeStack&) KJS_FAST_CALL;
+ virtual JSValue* evaluate(OldInterpreterExecState*) KJS_FAST_CALL;
+ virtual bool evaluateToBoolean(OldInterpreterExecState*) KJS_FAST_CALL;
virtual void streamTo(SourceStream&) const KJS_FAST_CALL;
virtual Precedence precedence() const { return PrecEquality; }
private:
- ALWAYS_INLINE bool inlineEvaluateToBoolean(ExecState*);
+ ALWAYS_INLINE bool inlineEvaluateToBoolean(OldInterpreterExecState*);
RefPtr<ExpressionNode> m_expr1;
RefPtr<ExpressionNode> m_expr2;
@@ -2018,17 +2152,18 @@
{
}
- virtual void optimizeVariableAccess(ExecState*, const SymbolTable&, const LocalStorage&, NodeStack&) KJS_FAST_CALL;
- virtual JSValue* evaluate(ExecState*) KJS_FAST_CALL;
- virtual double evaluateToNumber(ExecState*) KJS_FAST_CALL;
- virtual bool evaluateToBoolean(ExecState*) KJS_FAST_CALL;
- virtual int32_t evaluateToInt32(ExecState*) KJS_FAST_CALL;
- virtual uint32_t evaluateToUInt32(ExecState*) KJS_FAST_CALL;
+ virtual RegisterID* emitCode(CodeGenerator&, RegisterID* = 0) KJS_FAST_CALL;
+ virtual void optimizeVariableAccess(OldInterpreterExecState*, const SymbolTable&, const LocalStorage&, NodeStack&) KJS_FAST_CALL;
+ virtual JSValue* evaluate(OldInterpreterExecState*) KJS_FAST_CALL;
+ virtual double evaluateToNumber(OldInterpreterExecState*) KJS_FAST_CALL;
+ virtual bool evaluateToBoolean(OldInterpreterExecState*) KJS_FAST_CALL;
+ virtual int32_t evaluateToInt32(OldInterpreterExecState*) KJS_FAST_CALL;
+ virtual uint32_t evaluateToUInt32(OldInterpreterExecState*) KJS_FAST_CALL;
virtual void streamTo(SourceStream&) const KJS_FAST_CALL;
virtual Precedence precedence() const { return PrecBitwiseAnd; }
private:
- ALWAYS_INLINE int32_t inlineEvaluateToInt32(ExecState*);
+ ALWAYS_INLINE int32_t inlineEvaluateToInt32(OldInterpreterExecState*);
RefPtr<ExpressionNode> m_expr1;
RefPtr<ExpressionNode> m_expr2;
@@ -2043,17 +2178,18 @@
{
}
- virtual void optimizeVariableAccess(ExecState*, const SymbolTable&, const LocalStorage&, NodeStack&) KJS_FAST_CALL;
- virtual JSValue* evaluate(ExecState*) KJS_FAST_CALL;
- virtual double evaluateToNumber(ExecState*) KJS_FAST_CALL;
- virtual bool evaluateToBoolean(ExecState*) KJS_FAST_CALL;
- virtual int32_t evaluateToInt32(ExecState*) KJS_FAST_CALL;
- virtual uint32_t evaluateToUInt32(ExecState*) KJS_FAST_CALL;
+ virtual RegisterID* emitCode(CodeGenerator&, RegisterID* = 0) KJS_FAST_CALL;
+ virtual void optimizeVariableAccess(OldInterpreterExecState*, const SymbolTable&, const LocalStorage&, NodeStack&) KJS_FAST_CALL;
+ virtual JSValue* evaluate(OldInterpreterExecState*) KJS_FAST_CALL;
+ virtual double evaluateToNumber(OldInterpreterExecState*) KJS_FAST_CALL;
+ virtual bool evaluateToBoolean(OldInterpreterExecState*) KJS_FAST_CALL;
+ virtual int32_t evaluateToInt32(OldInterpreterExecState*) KJS_FAST_CALL;
+ virtual uint32_t evaluateToUInt32(OldInterpreterExecState*) KJS_FAST_CALL;
virtual void streamTo(SourceStream&) const KJS_FAST_CALL;
virtual Precedence precedence() const { return PrecBitwiseOr; }
private:
- ALWAYS_INLINE int32_t inlineEvaluateToInt32(ExecState*);
+ ALWAYS_INLINE int32_t inlineEvaluateToInt32(OldInterpreterExecState*);
RefPtr<ExpressionNode> m_expr1;
RefPtr<ExpressionNode> m_expr2;
@@ -2068,17 +2204,18 @@
{
}
- virtual void optimizeVariableAccess(ExecState*, const SymbolTable&, const LocalStorage&, NodeStack&) KJS_FAST_CALL;
- virtual JSValue* evaluate(ExecState*) KJS_FAST_CALL;
- virtual double evaluateToNumber(ExecState*) KJS_FAST_CALL;
- virtual bool evaluateToBoolean(ExecState*) KJS_FAST_CALL;
- virtual int32_t evaluateToInt32(ExecState*) KJS_FAST_CALL;
- virtual uint32_t evaluateToUInt32(ExecState*) KJS_FAST_CALL;
+ virtual RegisterID* emitCode(CodeGenerator&, RegisterID* = 0) KJS_FAST_CALL;
+ virtual void optimizeVariableAccess(OldInterpreterExecState*, const SymbolTable&, const LocalStorage&, NodeStack&) KJS_FAST_CALL;
+ virtual JSValue* evaluate(OldInterpreterExecState*) KJS_FAST_CALL;
+ virtual double evaluateToNumber(OldInterpreterExecState*) KJS_FAST_CALL;
+ virtual bool evaluateToBoolean(OldInterpreterExecState*) KJS_FAST_CALL;
+ virtual int32_t evaluateToInt32(OldInterpreterExecState*) KJS_FAST_CALL;
+ virtual uint32_t evaluateToUInt32(OldInterpreterExecState*) KJS_FAST_CALL;
virtual void streamTo(SourceStream&) const KJS_FAST_CALL;
virtual Precedence precedence() const { return PrecBitwiseXor; }
private:
- ALWAYS_INLINE int32_t inlineEvaluateToInt32(ExecState*);
+ ALWAYS_INLINE int32_t inlineEvaluateToInt32(OldInterpreterExecState*);
RefPtr<ExpressionNode> m_expr1;
RefPtr<ExpressionNode> m_expr2;
@@ -2096,14 +2233,15 @@
{
}
- virtual void optimizeVariableAccess(ExecState*, const SymbolTable&, const LocalStorage&, NodeStack&) KJS_FAST_CALL;
- virtual JSValue* evaluate(ExecState*) KJS_FAST_CALL;
- virtual bool evaluateToBoolean(ExecState*) KJS_FAST_CALL;
+ virtual RegisterID* emitCode(CodeGenerator&, RegisterID* = 0) KJS_FAST_CALL;
+ virtual void optimizeVariableAccess(OldInterpreterExecState*, const SymbolTable&, const LocalStorage&, NodeStack&) KJS_FAST_CALL;
+ virtual JSValue* evaluate(OldInterpreterExecState*) KJS_FAST_CALL;
+ virtual bool evaluateToBoolean(OldInterpreterExecState*) KJS_FAST_CALL;
virtual void streamTo(SourceStream&) const KJS_FAST_CALL;
virtual Precedence precedence() const { return PrecLogicalAnd; }
private:
- ALWAYS_INLINE bool inlineEvaluateToBoolean(ExecState*);
+ ALWAYS_INLINE bool inlineEvaluateToBoolean(OldInterpreterExecState*);
RefPtr<ExpressionNode> m_expr1;
RefPtr<ExpressionNode> m_expr2;
@@ -2118,14 +2256,15 @@
{
}
- virtual void optimizeVariableAccess(ExecState*, const SymbolTable&, const LocalStorage&, NodeStack&) KJS_FAST_CALL;
- virtual JSValue* evaluate(ExecState*) KJS_FAST_CALL;
- virtual bool evaluateToBoolean(ExecState*) KJS_FAST_CALL;
+ virtual RegisterID* emitCode(CodeGenerator&, RegisterID* = 0) KJS_FAST_CALL;
+ virtual void optimizeVariableAccess(OldInterpreterExecState*, const SymbolTable&, const LocalStorage&, NodeStack&) KJS_FAST_CALL;
+ virtual JSValue* evaluate(OldInterpreterExecState*) KJS_FAST_CALL;
+ virtual bool evaluateToBoolean(OldInterpreterExecState*) KJS_FAST_CALL;
virtual void streamTo(SourceStream&) const KJS_FAST_CALL;
virtual Precedence precedence() const { return PrecLogicalOr; }
private:
- ALWAYS_INLINE bool inlineEvaluateToBoolean(ExecState*);
+ ALWAYS_INLINE bool inlineEvaluateToBoolean(OldInterpreterExecState*);
RefPtr<ExpressionNode> m_expr1;
RefPtr<ExpressionNode> m_expr2;
@@ -2143,12 +2282,13 @@
{
}
- virtual void optimizeVariableAccess(ExecState*, const SymbolTable&, const LocalStorage&, NodeStack&) KJS_FAST_CALL;
- virtual JSValue* evaluate(ExecState*) KJS_FAST_CALL;
- virtual bool evaluateToBoolean(ExecState*) KJS_FAST_CALL;
- virtual double evaluateToNumber(ExecState*) KJS_FAST_CALL;
- virtual int32_t evaluateToInt32(ExecState*) KJS_FAST_CALL;
- virtual uint32_t evaluateToUInt32(ExecState*) KJS_FAST_CALL;
+ virtual RegisterID* emitCode(CodeGenerator&, RegisterID* = 0) KJS_FAST_CALL;
+ virtual void optimizeVariableAccess(OldInterpreterExecState*, const SymbolTable&, const LocalStorage&, NodeStack&) KJS_FAST_CALL;
+ virtual JSValue* evaluate(OldInterpreterExecState*) KJS_FAST_CALL;
+ virtual bool evaluateToBoolean(OldInterpreterExecState*) KJS_FAST_CALL;
+ virtual double evaluateToNumber(OldInterpreterExecState*) KJS_FAST_CALL;
+ virtual int32_t evaluateToInt32(OldInterpreterExecState*) KJS_FAST_CALL;
+ virtual uint32_t evaluateToUInt32(OldInterpreterExecState*) KJS_FAST_CALL;
virtual void streamTo(SourceStream&) const KJS_FAST_CALL;
virtual Precedence precedence() const { return PrecConditional; }
@@ -2160,10 +2300,11 @@
class ReadModifyResolveNode : public ExpressionNode {
public:
- ReadModifyResolveNode(const Identifier& ident, Operator oper, ExpressionNode* right) KJS_FAST_CALL
+ ReadModifyResolveNode(const Identifier& ident, Operator oper, ExpressionNode* right, bool rightHasAssignments) KJS_FAST_CALL
: m_ident(ident)
- , m_operator(oper)
, m_right(right)
+ , m_operator(oper)
+ , m_rightHasAssignments(rightHasAssignments)
{
}
@@ -2171,50 +2312,55 @@
: ExpressionNode(PlacementNewAdopt)
, m_ident(PlacementNewAdopt)
, m_right(PlacementNewAdopt)
+ , m_rightHasAssignments(true)
{
}
- virtual void optimizeVariableAccess(ExecState*, const SymbolTable&, const LocalStorage&, NodeStack&) KJS_FAST_CALL;
- virtual JSValue* evaluate(ExecState*) KJS_FAST_CALL;
+ virtual RegisterID* emitCode(CodeGenerator&, RegisterID* = 0) KJS_FAST_CALL;
+
+ virtual void optimizeVariableAccess(OldInterpreterExecState*, const SymbolTable&, const LocalStorage&, NodeStack&) KJS_FAST_CALL;
+ virtual JSValue* evaluate(OldInterpreterExecState*) KJS_FAST_CALL;
virtual void streamTo(SourceStream&) const KJS_FAST_CALL;
virtual Precedence precedence() const { return PrecAssignment; }
protected:
Identifier m_ident;
- Operator m_operator;
RefPtr<ExpressionNode> m_right;
size_t m_index; // Used by ReadModifyLocalVarNode.
+ Operator m_operator : 31;
+ bool m_rightHasAssignments : 1;
};
class ReadModifyLocalVarNode : public ReadModifyResolveNode {
public:
- ReadModifyLocalVarNode(size_t i) KJS_FAST_CALL
+ ReadModifyLocalVarNode(int i) KJS_FAST_CALL
: ReadModifyResolveNode(PlacementNewAdopt)
{
ASSERT(i != missingSymbolMarker());
m_index = i;
}
- virtual JSValue* evaluate(ExecState*) KJS_FAST_CALL;
+ virtual JSValue* evaluate(OldInterpreterExecState*) KJS_FAST_CALL;
};
class ReadModifyConstNode : public ReadModifyResolveNode {
public:
- ReadModifyConstNode(size_t i) KJS_FAST_CALL
+ ReadModifyConstNode(int i) KJS_FAST_CALL
: ReadModifyResolveNode(PlacementNewAdopt)
{
ASSERT(i != missingSymbolMarker());
m_index = i;
}
- virtual JSValue* evaluate(ExecState*) KJS_FAST_CALL;
+ virtual JSValue* evaluate(OldInterpreterExecState*) KJS_FAST_CALL;
};
class AssignResolveNode : public ExpressionNode {
public:
- AssignResolveNode(const Identifier& ident, ExpressionNode* right) KJS_FAST_CALL
+ AssignResolveNode(const Identifier& ident, ExpressionNode* right, bool rightHasAssignments) KJS_FAST_CALL
: m_ident(ident)
, m_right(right)
+ , m_rightHasAssignments(rightHasAssignments)
{
}
@@ -2224,9 +2370,11 @@
, m_right(PlacementNewAdopt)
{
}
+
+ virtual RegisterID* emitCode(CodeGenerator&, RegisterID* = 0) KJS_FAST_CALL;
- virtual void optimizeVariableAccess(ExecState*, const SymbolTable&, const LocalStorage&, NodeStack&) KJS_FAST_CALL;
- virtual JSValue* evaluate(ExecState*) KJS_FAST_CALL;
+ virtual void optimizeVariableAccess(OldInterpreterExecState*, const SymbolTable&, const LocalStorage&, NodeStack&) KJS_FAST_CALL;
+ virtual JSValue* evaluate(OldInterpreterExecState*) KJS_FAST_CALL;
virtual void streamTo(SourceStream&) const KJS_FAST_CALL;
virtual Precedence precedence() const { return PrecAssignment; }
@@ -2234,18 +2382,19 @@
Identifier m_ident;
RefPtr<ExpressionNode> m_right;
size_t m_index; // Used by ReadModifyLocalVarNode.
+ bool m_rightHasAssignments;
};
class AssignLocalVarNode : public AssignResolveNode {
public:
- AssignLocalVarNode(size_t i) KJS_FAST_CALL
+ AssignLocalVarNode(int i) KJS_FAST_CALL
: AssignResolveNode(PlacementNewAdopt)
{
ASSERT(i != missingSymbolMarker());
m_index = i;
}
- virtual JSValue* evaluate(ExecState*) KJS_FAST_CALL;
+ virtual JSValue* evaluate(OldInterpreterExecState*) KJS_FAST_CALL;
};
class AssignConstNode : public AssignResolveNode {
@@ -2255,42 +2404,52 @@
{
}
- virtual JSValue* evaluate(ExecState*) KJS_FAST_CALL;
+ virtual JSValue* evaluate(OldInterpreterExecState*) KJS_FAST_CALL;
};
class ReadModifyBracketNode : public ExpressionNode {
public:
- ReadModifyBracketNode(ExpressionNode* base, ExpressionNode* subscript, Operator oper, ExpressionNode* right) KJS_FAST_CALL
+ ReadModifyBracketNode(ExpressionNode* base, ExpressionNode* subscript, Operator oper, ExpressionNode* right, bool subscriptHasAssignments, bool rightHasAssignments) KJS_FAST_CALL
: m_base(base)
, m_subscript(subscript)
- , m_operator(oper)
, m_right(right)
+ , m_operator(oper)
+ , m_subscriptHasAssignments(subscriptHasAssignments)
+ , m_rightHasAssignments(rightHasAssignments)
{
}
- virtual void optimizeVariableAccess(ExecState*, const SymbolTable&, const LocalStorage&, NodeStack&) KJS_FAST_CALL;
- virtual JSValue* evaluate(ExecState*) KJS_FAST_CALL;
+ virtual RegisterID* emitCode(CodeGenerator&, RegisterID* = 0) KJS_FAST_CALL;
+
+ virtual void optimizeVariableAccess(OldInterpreterExecState*, const SymbolTable&, const LocalStorage&, NodeStack&) KJS_FAST_CALL;
+ virtual JSValue* evaluate(OldInterpreterExecState*) KJS_FAST_CALL;
virtual void streamTo(SourceStream&) const KJS_FAST_CALL;
virtual Precedence precedence() const { return PrecAssignment; }
protected:
RefPtr<ExpressionNode> m_base;
RefPtr<ExpressionNode> m_subscript;
- Operator m_operator;
RefPtr<ExpressionNode> m_right;
+ Operator m_operator : 30;
+ bool m_subscriptHasAssignments : 1;
+ bool m_rightHasAssignments : 1;
};
class AssignBracketNode : public ExpressionNode {
public:
- AssignBracketNode(ExpressionNode* base, ExpressionNode* subscript, ExpressionNode* right) KJS_FAST_CALL
+ AssignBracketNode(ExpressionNode* base, ExpressionNode* subscript, ExpressionNode* right, bool subscriptHasAssignments, bool rightHasAssignments) KJS_FAST_CALL
: m_base(base)
, m_subscript(subscript)
, m_right(right)
+ , m_subscriptHasAssignments(subscriptHasAssignments)
+ , m_rightHasAssignments(rightHasAssignments)
{
}
- virtual void optimizeVariableAccess(ExecState*, const SymbolTable&, const LocalStorage&, NodeStack&) KJS_FAST_CALL;
- virtual JSValue* evaluate(ExecState*) KJS_FAST_CALL;
+ virtual RegisterID* emitCode(CodeGenerator&, RegisterID* = 0) KJS_FAST_CALL;
+
+ virtual void optimizeVariableAccess(OldInterpreterExecState*, const SymbolTable&, const LocalStorage&, NodeStack&) KJS_FAST_CALL;
+ virtual JSValue* evaluate(OldInterpreterExecState*) KJS_FAST_CALL;
virtual void streamTo(SourceStream&) const KJS_FAST_CALL;
virtual Precedence precedence() const { return PrecAssignment; }
@@ -2298,19 +2457,23 @@
RefPtr<ExpressionNode> m_base;
RefPtr<ExpressionNode> m_subscript;
RefPtr<ExpressionNode> m_right;
+ bool m_subscriptHasAssignments : 1;
+ bool m_rightHasAssignments : 1;
};
class AssignDotNode : public ExpressionNode {
public:
- AssignDotNode(ExpressionNode* base, const Identifier& ident, ExpressionNode* right) KJS_FAST_CALL
+ AssignDotNode(ExpressionNode* base, const Identifier& ident, ExpressionNode* right, bool rightHasAssignments) KJS_FAST_CALL
: m_base(base)
, m_ident(ident)
, m_right(right)
+ , m_rightHasAssignments(rightHasAssignments)
{
}
- virtual void optimizeVariableAccess(ExecState*, const SymbolTable&, const LocalStorage&, NodeStack&) KJS_FAST_CALL;
- virtual JSValue* evaluate(ExecState*) KJS_FAST_CALL;
+ virtual RegisterID* emitCode(CodeGenerator&, RegisterID* = 0) KJS_FAST_CALL;
+ virtual void optimizeVariableAccess(OldInterpreterExecState*, const SymbolTable&, const LocalStorage&, NodeStack&) KJS_FAST_CALL;
+ virtual JSValue* evaluate(OldInterpreterExecState*) KJS_FAST_CALL;
virtual void streamTo(SourceStream&) const KJS_FAST_CALL;
virtual Precedence precedence() const { return PrecAssignment; }
@@ -2318,28 +2481,33 @@
RefPtr<ExpressionNode> m_base;
Identifier m_ident;
RefPtr<ExpressionNode> m_right;
+ bool m_rightHasAssignments;
};
class ReadModifyDotNode : public ExpressionNode {
public:
- ReadModifyDotNode(ExpressionNode* base, const Identifier& ident, Operator oper, ExpressionNode* right) KJS_FAST_CALL
+ ReadModifyDotNode(ExpressionNode* base, const Identifier& ident, Operator oper, ExpressionNode* right, bool rightHasAssignments) KJS_FAST_CALL
: m_base(base)
, m_ident(ident)
- , m_operator(oper)
, m_right(right)
+ , m_operator(oper)
+ , m_rightHasAssignments(rightHasAssignments)
{
}
- virtual void optimizeVariableAccess(ExecState*, const SymbolTable&, const LocalStorage&, NodeStack&) KJS_FAST_CALL;
- virtual JSValue* evaluate(ExecState*) KJS_FAST_CALL;
+ virtual RegisterID* emitCode(CodeGenerator&, RegisterID* = 0) KJS_FAST_CALL;
+
+ virtual void optimizeVariableAccess(OldInterpreterExecState*, const SymbolTable&, const LocalStorage&, NodeStack&) KJS_FAST_CALL;
+ virtual JSValue* evaluate(OldInterpreterExecState*) KJS_FAST_CALL;
virtual void streamTo(SourceStream&) const KJS_FAST_CALL;
virtual Precedence precedence() const { return PrecAssignment; }
protected:
RefPtr<ExpressionNode> m_base;
Identifier m_ident;
- Operator m_operator;
RefPtr<ExpressionNode> m_right;
+ Operator m_operator : 31;
+ bool m_rightHasAssignments : 1;
};
class AssignErrorNode : public ExpressionNode {
@@ -2351,7 +2519,8 @@
{
}
- virtual JSValue* evaluate(ExecState*) KJS_FAST_CALL;
+ virtual RegisterID* emitCode(CodeGenerator&, RegisterID* = 0) KJS_FAST_CALL;
+ virtual JSValue* evaluate(OldInterpreterExecState*) KJS_FAST_CALL;
virtual void streamTo(SourceStream&) const KJS_FAST_CALL;
virtual Precedence precedence() const { return PrecAssignment; }
@@ -2370,8 +2539,9 @@
m_expr1->optimizeForUnnecessaryResult();
}
- virtual void optimizeVariableAccess(ExecState*, const SymbolTable&, const LocalStorage&, NodeStack&) KJS_FAST_CALL;
- virtual JSValue* evaluate(ExecState*) KJS_FAST_CALL;
+ virtual RegisterID* emitCode(CodeGenerator&, RegisterID* = 0) KJS_FAST_CALL;
+ virtual void optimizeVariableAccess(OldInterpreterExecState*, const SymbolTable&, const LocalStorage&, NodeStack&) KJS_FAST_CALL;
+ virtual JSValue* evaluate(OldInterpreterExecState*) KJS_FAST_CALL;
virtual void streamTo(SourceStream&) const KJS_FAST_CALL;
virtual Precedence precedence() const { return PrecExpression; }
@@ -2393,9 +2563,9 @@
public:
ConstDeclNode(const Identifier& ident, ExpressionNode* in) KJS_FAST_CALL;
- virtual void optimizeVariableAccess(ExecState*, const SymbolTable&, const LocalStorage&, NodeStack&) KJS_FAST_CALL;
- virtual KJS::JSValue* evaluate(ExecState*) KJS_FAST_CALL;
- void evaluateSingle(ExecState*) KJS_FAST_CALL;
+ virtual void optimizeVariableAccess(OldInterpreterExecState*, const SymbolTable&, const LocalStorage&, NodeStack&) KJS_FAST_CALL;
+ virtual KJS::JSValue* evaluate(OldInterpreterExecState*) KJS_FAST_CALL;
+ void evaluateSingle(OldInterpreterExecState*) KJS_FAST_CALL;
virtual void streamTo(SourceStream&) const KJS_FAST_CALL;
virtual Precedence precedence() const { ASSERT_NOT_REACHED(); return PrecExpression; }
PassRefPtr<ConstDeclNode> releaseNext() KJS_FAST_CALL { return m_next.release(); }
@@ -2403,9 +2573,11 @@
Identifier m_ident;
ListRefPtr<ConstDeclNode> m_next;
RefPtr<ExpressionNode> m_init;
-
+
+ virtual RegisterID* emitCode(CodeGenerator&, RegisterID* = 0) KJS_FAST_CALL;
+ virtual RegisterID* emitCodeSingle(CodeGenerator&) KJS_FAST_CALL;
private:
- void handleSlowCase(ExecState*, const ScopeChain&, JSValue*) KJS_FAST_CALL NEVER_INLINE;
+ void handleSlowCase(OldInterpreterExecState*, const ScopeChain&, JSValue*) KJS_FAST_CALL NEVER_INLINE;
};
class ConstStatementNode : public StatementNode {
@@ -2415,10 +2587,11 @@
{
}
- virtual void optimizeVariableAccess(ExecState*, const SymbolTable&, const LocalStorage&, NodeStack&) KJS_FAST_CALL;
- virtual JSValue* execute(ExecState*) KJS_FAST_CALL;
+ virtual void optimizeVariableAccess(OldInterpreterExecState*, const SymbolTable&, const LocalStorage&, NodeStack&) KJS_FAST_CALL;
+ virtual JSValue* execute(OldInterpreterExecState*) KJS_FAST_CALL;
virtual void streamTo(SourceStream&) const KJS_FAST_CALL;
-
+
+ virtual RegisterID* emitCode(CodeGenerator&, RegisterID* = 0) KJS_FAST_CALL;
private:
RefPtr<ConstDeclNode> m_next;
};
@@ -2442,8 +2615,9 @@
public:
BlockNode(SourceElements* children) KJS_FAST_CALL;
- virtual void optimizeVariableAccess(ExecState*, const SymbolTable&, const LocalStorage&, NodeStack&) KJS_FAST_CALL;
- virtual JSValue* execute(ExecState*) KJS_FAST_CALL;
+ virtual RegisterID* emitCode(CodeGenerator&, RegisterID* = 0) KJS_FAST_CALL;
+ virtual void optimizeVariableAccess(OldInterpreterExecState*, const SymbolTable&, const LocalStorage&, NodeStack&) KJS_FAST_CALL;
+ virtual JSValue* execute(OldInterpreterExecState*) KJS_FAST_CALL;
virtual void streamTo(SourceStream&) const KJS_FAST_CALL;
protected:
@@ -2456,7 +2630,9 @@
{
}
- virtual JSValue* execute(ExecState*) KJS_FAST_CALL;
+ virtual RegisterID* emitCode(CodeGenerator&, RegisterID* = 0) KJS_FAST_CALL;
+
+ virtual JSValue* execute(OldInterpreterExecState*) KJS_FAST_CALL;
virtual void streamTo(SourceStream&) const KJS_FAST_CALL;
virtual bool isEmptyStatement() const KJS_FAST_CALL { return true; }
};
@@ -2468,8 +2644,9 @@
{
}
- virtual void optimizeVariableAccess(ExecState*, const SymbolTable&, const LocalStorage&, NodeStack&) KJS_FAST_CALL;
- virtual JSValue* execute(ExecState*) KJS_FAST_CALL;
+ virtual RegisterID* emitCode(CodeGenerator&, RegisterID* = 0) KJS_FAST_CALL;
+ virtual void optimizeVariableAccess(OldInterpreterExecState*, const SymbolTable&, const LocalStorage&, NodeStack&) KJS_FAST_CALL;
+ virtual JSValue* execute(OldInterpreterExecState*) KJS_FAST_CALL;
virtual void streamTo(SourceStream&) const KJS_FAST_CALL;
private:
@@ -2482,9 +2659,11 @@
: m_expr(expr)
{
}
+
+ virtual RegisterID* emitCode(CodeGenerator&, RegisterID* = 0) KJS_FAST_CALL;
- virtual void optimizeVariableAccess(ExecState*, const SymbolTable&, const LocalStorage&, NodeStack&) KJS_FAST_CALL;
- virtual JSValue* execute(ExecState*) KJS_FAST_CALL;
+ virtual void optimizeVariableAccess(OldInterpreterExecState*, const SymbolTable&, const LocalStorage&, NodeStack&) KJS_FAST_CALL;
+ virtual JSValue* execute(OldInterpreterExecState*) KJS_FAST_CALL;
virtual void streamTo(SourceStream&) const KJS_FAST_CALL;
private:
@@ -2499,8 +2678,9 @@
{
}
- virtual void optimizeVariableAccess(ExecState*, const SymbolTable&, const LocalStorage&, NodeStack&) KJS_FAST_CALL;
- virtual JSValue* execute(ExecState*) KJS_FAST_CALL;
+ virtual RegisterID* emitCode(CodeGenerator&, RegisterID* = 0) KJS_FAST_CALL;
+ virtual void optimizeVariableAccess(OldInterpreterExecState*, const SymbolTable&, const LocalStorage&, NodeStack&) KJS_FAST_CALL;
+ virtual JSValue* execute(OldInterpreterExecState*) KJS_FAST_CALL;
virtual void streamTo(SourceStream&) const KJS_FAST_CALL;
protected:
@@ -2516,8 +2696,9 @@
{
}
- virtual void optimizeVariableAccess(ExecState*, const SymbolTable&, const LocalStorage&, NodeStack&) KJS_FAST_CALL;
- virtual JSValue* execute(ExecState*) KJS_FAST_CALL;
+ virtual RegisterID* emitCode(CodeGenerator&, RegisterID* = 0) KJS_FAST_CALL;
+ virtual void optimizeVariableAccess(OldInterpreterExecState*, const SymbolTable&, const LocalStorage&, NodeStack&) KJS_FAST_CALL;
+ virtual JSValue* execute(OldInterpreterExecState*) KJS_FAST_CALL;
virtual void streamTo(SourceStream&) const KJS_FAST_CALL;
private:
@@ -2532,8 +2713,9 @@
{
}
- virtual void optimizeVariableAccess(ExecState*, const SymbolTable&, const LocalStorage&, NodeStack&) KJS_FAST_CALL;
- virtual JSValue* execute(ExecState*) KJS_FAST_CALL;
+ virtual RegisterID* emitCode(CodeGenerator&, RegisterID* = 0) KJS_FAST_CALL;
+ virtual void optimizeVariableAccess(OldInterpreterExecState*, const SymbolTable&, const LocalStorage&, NodeStack&) KJS_FAST_CALL;
+ virtual JSValue* execute(OldInterpreterExecState*) KJS_FAST_CALL;
virtual void streamTo(SourceStream&) const KJS_FAST_CALL;
private:
@@ -2549,8 +2731,9 @@
{
}
- virtual void optimizeVariableAccess(ExecState*, const SymbolTable&, const LocalStorage&, NodeStack&) KJS_FAST_CALL;
- virtual JSValue* execute(ExecState*) KJS_FAST_CALL;
+ virtual RegisterID* emitCode(CodeGenerator&, RegisterID* = 0) KJS_FAST_CALL;
+ virtual void optimizeVariableAccess(OldInterpreterExecState*, const SymbolTable&, const LocalStorage&, NodeStack&) KJS_FAST_CALL;
+ virtual JSValue* execute(OldInterpreterExecState*) KJS_FAST_CALL;
virtual void streamTo(SourceStream&) const KJS_FAST_CALL;
private:
@@ -2576,8 +2759,9 @@
m_expr3->optimizeForUnnecessaryResult();
}
- virtual void optimizeVariableAccess(ExecState*, const SymbolTable&, const LocalStorage&, NodeStack&) KJS_FAST_CALL;
- virtual JSValue* execute(ExecState*) KJS_FAST_CALL;
+ virtual RegisterID* emitCode(CodeGenerator&, RegisterID* = 0) KJS_FAST_CALL;
+ virtual void optimizeVariableAccess(OldInterpreterExecState*, const SymbolTable&, const LocalStorage&, NodeStack&) KJS_FAST_CALL;
+ virtual JSValue* execute(OldInterpreterExecState*) KJS_FAST_CALL;
virtual void streamTo(SourceStream&) const KJS_FAST_CALL;
private:
@@ -2592,9 +2776,10 @@
public:
ForInNode(ExpressionNode*, ExpressionNode*, StatementNode*) KJS_FAST_CALL;
ForInNode(const Identifier&, ExpressionNode*, ExpressionNode*, StatementNode*) KJS_FAST_CALL;
-
- virtual void optimizeVariableAccess(ExecState*, const SymbolTable&, const LocalStorage&, NodeStack&) KJS_FAST_CALL;
- virtual JSValue* execute(ExecState*) KJS_FAST_CALL;
+
+ virtual RegisterID* emitCode(CodeGenerator&, RegisterID* = 0) KJS_FAST_CALL;
+ virtual void optimizeVariableAccess(OldInterpreterExecState*, const SymbolTable&, const LocalStorage&, NodeStack&) KJS_FAST_CALL;
+ virtual JSValue* execute(OldInterpreterExecState*) KJS_FAST_CALL;
virtual void streamTo(SourceStream&) const KJS_FAST_CALL;
private:
@@ -2616,8 +2801,9 @@
: m_ident(ident)
{
}
-
- virtual JSValue* execute(ExecState*) KJS_FAST_CALL;
+
+ virtual RegisterID* emitCode(CodeGenerator&, RegisterID* = 0) KJS_FAST_CALL;
+ virtual JSValue* execute(OldInterpreterExecState*) KJS_FAST_CALL;
virtual void streamTo(SourceStream&) const KJS_FAST_CALL;
private:
@@ -2634,8 +2820,9 @@
: m_ident(ident)
{
}
-
- virtual JSValue* execute(ExecState*) KJS_FAST_CALL;
+
+ virtual RegisterID* emitCode(CodeGenerator&, RegisterID* = 0) KJS_FAST_CALL;
+ virtual JSValue* execute(OldInterpreterExecState*) KJS_FAST_CALL;
virtual void streamTo(SourceStream&) const KJS_FAST_CALL;
private:
@@ -2649,9 +2836,11 @@
{
}
- virtual void optimizeVariableAccess(ExecState*, const SymbolTable&, const LocalStorage&, NodeStack&) KJS_FAST_CALL;
- virtual JSValue* execute(ExecState*) KJS_FAST_CALL;
+ virtual RegisterID* emitCode(CodeGenerator&, RegisterID* = 0) KJS_FAST_CALL;
+ virtual void optimizeVariableAccess(OldInterpreterExecState*, const SymbolTable&, const LocalStorage&, NodeStack&) KJS_FAST_CALL;
+ virtual JSValue* execute(OldInterpreterExecState*) KJS_FAST_CALL;
virtual void streamTo(SourceStream&) const KJS_FAST_CALL;
+ virtual bool isReturnNode() const KJS_FAST_CALL { return true; }
private:
RefPtr<ExpressionNode> m_value;
@@ -2665,8 +2854,9 @@
{
}
- virtual void optimizeVariableAccess(ExecState*, const SymbolTable&, const LocalStorage&, NodeStack&) KJS_FAST_CALL;
- virtual JSValue* execute(ExecState*) KJS_FAST_CALL;
+ virtual RegisterID* emitCode(CodeGenerator&, RegisterID* = 0) KJS_FAST_CALL;
+ virtual void optimizeVariableAccess(OldInterpreterExecState*, const SymbolTable&, const LocalStorage&, NodeStack&) KJS_FAST_CALL;
+ virtual JSValue* execute(OldInterpreterExecState*) KJS_FAST_CALL;
virtual void streamTo(SourceStream&) const KJS_FAST_CALL;
private:
@@ -2682,8 +2872,9 @@
{
}
- virtual void optimizeVariableAccess(ExecState*, const SymbolTable&, const LocalStorage&, NodeStack&) KJS_FAST_CALL;
- virtual JSValue* execute(ExecState*) KJS_FAST_CALL;
+ virtual RegisterID* emitCode(CodeGenerator&, RegisterID* = 0) KJS_FAST_CALL;
+ virtual void optimizeVariableAccess(OldInterpreterExecState*, const SymbolTable&, const LocalStorage&, NodeStack&) KJS_FAST_CALL;
+ virtual JSValue* execute(OldInterpreterExecState*) KJS_FAST_CALL;
virtual void streamTo(SourceStream&) const KJS_FAST_CALL;
virtual void pushLabel(const Identifier& ident) KJS_FAST_CALL { m_statement->pushLabel(ident); }
@@ -2699,8 +2890,9 @@
{
}
- virtual void optimizeVariableAccess(ExecState*, const SymbolTable&, const LocalStorage&, NodeStack&) KJS_FAST_CALL;
- virtual JSValue* execute(ExecState*) KJS_FAST_CALL;
+ virtual RegisterID* emitCode(CodeGenerator&, RegisterID* = 0) KJS_FAST_CALL;
+ virtual void optimizeVariableAccess(OldInterpreterExecState*, const SymbolTable&, const LocalStorage&, NodeStack&) KJS_FAST_CALL;
+ virtual JSValue* execute(OldInterpreterExecState*) KJS_FAST_CALL;
virtual void streamTo(SourceStream&) const KJS_FAST_CALL;
private:
@@ -2717,10 +2909,12 @@
{
}
- virtual void optimizeVariableAccess(ExecState*, const SymbolTable&, const LocalStorage&, NodeStack&) KJS_FAST_CALL;
- virtual JSValue* execute(ExecState*) KJS_FAST_CALL;
+ virtual void optimizeVariableAccess(OldInterpreterExecState*, const SymbolTable&, const LocalStorage&, NodeStack&) KJS_FAST_CALL;
+ virtual JSValue* execute(OldInterpreterExecState*) KJS_FAST_CALL;
virtual void streamTo(SourceStream&) const KJS_FAST_CALL;
+ virtual RegisterID* emitCode(CodeGenerator&, RegisterID* dst = 0) KJS_FAST_CALL;
+
private:
RefPtr<StatementNode> m_tryBlock;
Identifier m_exceptionIdent;
@@ -2764,12 +2958,13 @@
bool usesEval() const { return m_usesEval; }
bool needsClosure() const { return m_needsClosure; }
-
+
protected:
- void optimizeVariableAccess(ExecState*) KJS_FAST_CALL;
+ void optimizeVariableAccess(OldInterpreterExecState*) KJS_FAST_CALL;
VarStack m_varStack;
FunctionStack m_functionStack;
+
private:
UString m_sourceURL;
int m_sourceId;
@@ -2780,69 +2975,119 @@
class ProgramNode : public ScopeNode {
public:
static ProgramNode* create(SourceElements*, VarStack*, FunctionStack*, bool usesEval, bool needsClosure) KJS_FAST_CALL;
+ virtual ~ProgramNode();
+
+ virtual JSValue* execute(OldInterpreterExecState*) KJS_FAST_CALL;
- virtual JSValue* execute(ExecState*) KJS_FAST_CALL;
+ ProgramCodeBlock& code(ScopeChainNode* scopeChain, bool canCreateGlobals) KJS_FAST_CALL
+ {
+ if (!m_code)
+ generateCode(scopeChain, canCreateGlobals);
+ return *m_code;
+ }
private:
ProgramNode(SourceElements*, VarStack*, FunctionStack*, bool usesEval, bool needsClosure) KJS_FAST_CALL;
- void initializeSymbolTable(ExecState*) KJS_FAST_CALL;
- ALWAYS_INLINE void processDeclarations(ExecState*) KJS_FAST_CALL;
+ void generateCode(ScopeChainNode*, bool) KJS_FAST_CALL;
+ virtual RegisterID* emitCode(CodeGenerator&, RegisterID* = 0) KJS_FAST_CALL;
+
+ void initializeSymbolTable(OldInterpreterExecState*) KJS_FAST_CALL;
+ ALWAYS_INLINE void processDeclarations(OldInterpreterExecState*) KJS_FAST_CALL;
Vector<size_t> m_varIndexes; // Storage indexes belonging to the nodes in m_varStack. (Recorded to avoid double lookup.)
Vector<size_t> m_functionIndexes; // Storage indexes belonging to the nodes in m_functionStack. (Recorded to avoid double lookup.)
+
+ OwnPtr<ProgramCodeBlock> m_code;
};
class EvalNode : public ScopeNode {
public:
static EvalNode* create(SourceElements*, VarStack*, FunctionStack*, bool usesEval, bool needsClosure) KJS_FAST_CALL;
+ virtual ~EvalNode();
+
+ virtual JSValue* execute(OldInterpreterExecState*) KJS_FAST_CALL;
- virtual JSValue* execute(ExecState*) KJS_FAST_CALL;
+ EvalCodeBlock& code(ScopeChainNode* scopeChain) KJS_FAST_CALL
+ {
+ if (!m_code)
+ generateCode(scopeChain);
+ return *m_code;
+ }
private:
EvalNode(SourceElements*, VarStack*, FunctionStack*, bool usesEval, bool needsClosure) KJS_FAST_CALL;
- ALWAYS_INLINE void processDeclarations(ExecState*) KJS_FAST_CALL;
+ ALWAYS_INLINE void processDeclarations(OldInterpreterExecState*) KJS_FAST_CALL;
+ void generateCode(ScopeChainNode*) KJS_FAST_CALL;
+ virtual RegisterID* emitCode(CodeGenerator&, RegisterID* = 0) KJS_FAST_CALL;
+
+ OwnPtr<EvalCodeBlock> m_code;
};
class FunctionBodyNode : public ScopeNode {
public:
static FunctionBodyNode* create(SourceElements*, VarStack*, FunctionStack*, bool usesEval, bool needsClosure) KJS_FAST_CALL;
-
- virtual JSValue* execute(ExecState*) KJS_FAST_CALL;
-
- SymbolTable& symbolTable() KJS_FAST_CALL { return m_symbolTable; }
-
+ virtual ~FunctionBodyNode();
+
Vector<Identifier>& parameters() KJS_FAST_CALL { return m_parameters; }
UString paramString() const KJS_FAST_CALL;
+ virtual RegisterID* emitCode(CodeGenerator&, RegisterID* = 0) KJS_FAST_CALL;
+
+ SymbolTable& symbolTable() { return m_symbolTable; } // FIXME: Remove this
+
+ CodeBlock& code(ScopeChainNode* scopeChain) KJS_FAST_CALL
+ {
+ ASSERT(scopeChain);
+ if (!m_code)
+ generateCode(scopeChain);
+ return *m_code;
+ }
+
+ CodeBlock& generatedCode() KJS_FAST_CALL
+ {
+ ASSERT(m_code);
+ return *m_code;
+ }
+
+ void mark();
+
+ void setSource(const SourceRange& source) { m_source = source; }
+ UString toSourceString() const KJS_FAST_CALL { return UString("{") + m_source.toString() + UString("}"); }
+
protected:
FunctionBodyNode(SourceElements*, VarStack*, FunctionStack*, bool usesEval, bool needsClosure) KJS_FAST_CALL;
private:
- void initializeSymbolTable(ExecState*) KJS_FAST_CALL;
- ALWAYS_INLINE void processDeclarations(ExecState*) KJS_FAST_CALL;
-
- bool m_initialized;
+ void generateCode(ScopeChainNode*) KJS_FAST_CALL;
+
Vector<Identifier> m_parameters;
SymbolTable m_symbolTable;
+ OwnPtr<CodeBlock> m_code;
+ SourceRange m_source;
};
class FuncExprNode : public ExpressionNode {
public:
- FuncExprNode(const Identifier& ident, FunctionBodyNode* body, ParameterNode* parameter = 0) KJS_FAST_CALL
+ FuncExprNode(const Identifier& ident, FunctionBodyNode* body, const SourceRange& source, ParameterNode* parameter = 0) KJS_FAST_CALL
: m_ident(ident)
, m_parameter(parameter)
, m_body(body)
{
addParams();
+ m_body->setSource(source);
}
- virtual JSValue* evaluate(ExecState*) KJS_FAST_CALL;
+ virtual RegisterID* emitCode(CodeGenerator&, RegisterID* = 0) KJS_FAST_CALL;
+ FunctionImp* makeFunction(ExecState*, ScopeChainNode*) KJS_FAST_CALL;
+ virtual JSValue* evaluate(OldInterpreterExecState*) KJS_FAST_CALL;
virtual void streamTo(SourceStream&) const KJS_FAST_CALL;
virtual Precedence precedence() const { return PrecMember; }
virtual bool needsParensIfLeftmost() const { return true; }
+ FunctionBodyNode* body() { return m_body.get(); }
+
private:
void addParams() KJS_FAST_CALL;
@@ -2855,27 +3100,25 @@
class FuncDeclNode : public StatementNode {
public:
- FuncDeclNode(const Identifier& ident, FunctionBodyNode* body) KJS_FAST_CALL
- : m_ident(ident)
- , m_body(body)
- {
- addParams();
- }
-
- FuncDeclNode(const Identifier& ident, ParameterNode* parameter, FunctionBodyNode* body) KJS_FAST_CALL
+ FuncDeclNode(const Identifier& ident, FunctionBodyNode* body, const SourceRange& source, ParameterNode* parameter = 0) KJS_FAST_CALL
: m_ident(ident)
, m_parameter(parameter)
, m_body(body)
{
addParams();
+ m_body->setSource(source);
}
- virtual JSValue* execute(ExecState*) KJS_FAST_CALL;
+ virtual RegisterID* emitCode(CodeGenerator&, RegisterID* = 0) KJS_FAST_CALL;
+
+ virtual JSValue* execute(OldInterpreterExecState*) KJS_FAST_CALL;
virtual void streamTo(SourceStream&) const KJS_FAST_CALL;
- ALWAYS_INLINE FunctionImp* makeFunction(ExecState*) KJS_FAST_CALL;
+ FunctionImp* makeFunction(ExecState*, ScopeChainNode*) KJS_FAST_CALL;
Identifier m_ident;
+ FunctionBodyNode* body() { return m_body.get(); }
+
private:
void addParams() KJS_FAST_CALL;
@@ -2897,12 +3140,15 @@
children->releaseContentsIntoVector(m_children);
}
- virtual void optimizeVariableAccess(ExecState*, const SymbolTable&, const LocalStorage&, NodeStack&) KJS_FAST_CALL;
+ virtual void optimizeVariableAccess(OldInterpreterExecState*, const SymbolTable&, const LocalStorage&, NodeStack&) KJS_FAST_CALL;
virtual void streamTo(SourceStream&) const KJS_FAST_CALL;
virtual Precedence precedence() const { ASSERT_NOT_REACHED(); return PrecExpression; }
- JSValue* evaluate(ExecState*) KJS_FAST_CALL;
- JSValue* executeStatements(ExecState*) KJS_FAST_CALL;
+ JSValue* evaluate(OldInterpreterExecState*) KJS_FAST_CALL;
+ JSValue* executeStatements(OldInterpreterExecState*) KJS_FAST_CALL;
+
+ ExpressionNode* expr() const { return m_expr.get(); }
+ StatementVector& children() { return m_children; }
private:
RefPtr<ExpressionNode> m_expr;
@@ -2922,7 +3168,7 @@
clauseList->m_next = this;
}
- virtual void optimizeVariableAccess(ExecState*, const SymbolTable&, const LocalStorage&, NodeStack&) KJS_FAST_CALL;
+ virtual void optimizeVariableAccess(OldInterpreterExecState*, const SymbolTable&, const LocalStorage&, NodeStack&) KJS_FAST_CALL;
CaseClauseNode* getClause() const KJS_FAST_CALL { return m_clause.get(); }
ClauseListNode* getNext() const KJS_FAST_CALL { return m_next.get(); }
virtual void streamTo(SourceStream&) const KJS_FAST_CALL;
@@ -2937,10 +3183,17 @@
class CaseBlockNode : public Node {
public:
- CaseBlockNode(ClauseListNode* list1, CaseClauseNode* defaultClause, ClauseListNode* list2) KJS_FAST_CALL;
+ CaseBlockNode(ClauseListNode* list1, CaseClauseNode* defaultClause, ClauseListNode* list2) KJS_FAST_CALL
+ : m_list1(list1)
+ , m_defaultClause(defaultClause)
+ , m_list2(list2)
+ {
+ }
- virtual void optimizeVariableAccess(ExecState*, const SymbolTable&, const LocalStorage&, NodeStack&) KJS_FAST_CALL;
- JSValue* executeBlock(ExecState*, JSValue *input) KJS_FAST_CALL;
+ RegisterID* emitCodeForBlock(CodeGenerator&, RegisterID* input, RegisterID* dst = 0) KJS_FAST_CALL;
+
+ virtual void optimizeVariableAccess(OldInterpreterExecState*, const SymbolTable&, const LocalStorage&, NodeStack&) KJS_FAST_CALL;
+ JSValue* executeBlock(OldInterpreterExecState*, JSValue *input) KJS_FAST_CALL;
virtual void streamTo(SourceStream&) const KJS_FAST_CALL;
virtual Precedence precedence() const { ASSERT_NOT_REACHED(); return PrecExpression; }
@@ -2958,8 +3211,10 @@
{
}
- virtual void optimizeVariableAccess(ExecState*, const SymbolTable&, const LocalStorage&, NodeStack&) KJS_FAST_CALL;
- virtual JSValue* execute(ExecState*) KJS_FAST_CALL;
+ virtual RegisterID* emitCode(CodeGenerator&, RegisterID* = 0) KJS_FAST_CALL;
+
+ virtual void optimizeVariableAccess(OldInterpreterExecState*, const SymbolTable&, const LocalStorage&, NodeStack&) KJS_FAST_CALL;
+ virtual JSValue* execute(OldInterpreterExecState*) KJS_FAST_CALL;
virtual void streamTo(SourceStream&) const KJS_FAST_CALL;
private:
@@ -2971,9 +3226,9 @@
public:
BreakpointCheckStatement(PassRefPtr<StatementNode>) KJS_FAST_CALL;
- virtual JSValue* execute(ExecState*) KJS_FAST_CALL;
+ virtual JSValue* execute(OldInterpreterExecState*) KJS_FAST_CALL;
virtual void streamTo(SourceStream&) const KJS_FAST_CALL;
- virtual void optimizeVariableAccess(ExecState*, const SymbolTable&, const LocalStorage&, NodeStack&) KJS_FAST_CALL;
+ virtual void optimizeVariableAccess(OldInterpreterExecState*, const SymbolTable&, const LocalStorage&, NodeStack&) KJS_FAST_CALL;
private:
RefPtr<StatementNode> m_statement;
diff --git a/JavaScriptCore/kjs/number_object.cpp b/JavaScriptCore/kjs/number_object.cpp
index b72c0e6..2a3eeb7 100644
--- a/JavaScriptCore/kjs/number_object.cpp
+++ b/JavaScriptCore/kjs/number_object.cpp
@@ -495,9 +495,9 @@
return jsNull();
}
-bool NumberObjectImp::implementsConstruct() const
+ConstructType NumberObjectImp::getConstructData(ConstructData&)
{
- return true;
+ return ConstructTypeNative;
}
// ECMA 15.7.1
diff --git a/JavaScriptCore/kjs/number_object.h b/JavaScriptCore/kjs/number_object.h
index 36befed..0fc20ee 100644
--- a/JavaScriptCore/kjs/number_object.h
+++ b/JavaScriptCore/kjs/number_object.h
@@ -55,7 +55,7 @@
public:
NumberObjectImp(ExecState*, FunctionPrototype*, NumberPrototype*);
- virtual bool implementsConstruct() const;
+ virtual ConstructType getConstructData(ConstructData&);
virtual JSObject* construct(ExecState*, const List&);
virtual JSValue* callAsFunction(ExecState*, JSObject*, const List&);
diff --git a/JavaScriptCore/kjs/object.cpp b/JavaScriptCore/kjs/object.cpp
index 096675f..1a5b8d6 100644
--- a/JavaScriptCore/kjs/object.cpp
+++ b/JavaScriptCore/kjs/object.cpp
@@ -164,43 +164,6 @@
return "Object";
}
-JSValue *JSObject::get(ExecState *exec, const Identifier &propertyName) const
-{
- PropertySlot slot;
-
- if (const_cast<JSObject *>(this)->getPropertySlot(exec, propertyName, slot))
- return slot.getValue(exec, const_cast<JSObject *>(this), propertyName);
-
- return jsUndefined();
-}
-
-JSValue *JSObject::get(ExecState *exec, unsigned propertyName) const
-{
- PropertySlot slot;
- if (const_cast<JSObject *>(this)->getPropertySlot(exec, propertyName, slot))
- return slot.getValue(exec, const_cast<JSObject *>(this), propertyName);
-
- return jsUndefined();
-}
-
-bool JSObject::getPropertySlot(ExecState *exec, unsigned propertyName, PropertySlot& slot)
-{
- JSObject *imp = this;
-
- while (true) {
- if (imp->getOwnPropertySlot(exec, propertyName, slot))
- return true;
-
- JSValue *proto = imp->_proto;
- if (!proto->isObject())
- break;
-
- imp = static_cast<JSObject *>(proto);
- }
-
- return false;
-}
-
bool JSObject::getOwnPropertySlot(ExecState *exec, unsigned propertyName, PropertySlot& slot)
{
return getOwnPropertySlot(exec, Identifier::from(propertyName), slot);
@@ -303,7 +266,6 @@
putWithAttributes(exec, Identifier::from(propertyName), value, attributes);
}
-// ECMA 8.6.2.4
bool JSObject::hasProperty(ExecState *exec, const Identifier &propertyName) const
{
PropertySlot slot;
@@ -350,16 +312,19 @@
}
static ALWAYS_INLINE JSValue *tryGetAndCallProperty(ExecState *exec, const JSObject *object, const Identifier &propertyName) {
- JSValue *v = object->get(exec, propertyName);
+ JSValue* v = object->get(exec, propertyName);
if (v->isObject()) {
- JSObject *o = static_cast<JSObject*>(v);
- if (o->implementsCall()) { // spec says "not primitive type" but ...
- JSObject *thisObj = const_cast<JSObject*>(object);
- JSValue* def = o->call(exec, thisObj->toThisObject(exec), exec->emptyList());
- JSType defType = def->type();
- ASSERT(defType != GetterSetterType);
- if (defType != ObjectType)
- return def;
+ JSObject* o = static_cast<JSObject*>(v);
+ CallData data;
+ CallType callType = o->getCallData(data);
+ // spec says "not primitive type" but ...
+ if (callType != CallTypeNone) {
+ JSObject* thisObj = const_cast<JSObject*>(object);
+ JSValue* def = o->call(exec, thisObj->toThisObject(exec), exec->emptyList());
+ JSType defType = def->type();
+ ASSERT(defType != GetterSetterType);
+ if (defType != ObjectType)
+ return def;
}
}
return NULL;
@@ -375,6 +340,11 @@
// ECMA 8.6.2.6
JSValue* JSObject::defaultValue(ExecState* exec, JSType hint) const
{
+ // We need this check to guard against the case where this object is rhs of
+ // a binary expression where lhs threw an exception in its conversion to
+ // primitive
+ if (exec->hadException())
+ return exec->exception();
/* Prefer String for Date objects */
if ((hint == StringType) || (hint != NumberType && _proto == exec->lexicalGlobalObject()->datePrototype())) {
if (JSValue* v = tryGetAndCallProperty(exec, this, exec->propertyNames().toString))
@@ -477,11 +447,6 @@
}
}
-bool JSObject::implementsConstruct() const
-{
- return false;
-}
-
JSObject* JSObject::construct(ExecState*, const List& /*args*/)
{
ASSERT(false);
@@ -493,9 +458,10 @@
return construct(exec, args);
}
-bool JSObject::implementsCall() const
+bool JSObject::implementsCall()
{
- return false;
+ CallData callData;
+ return getCallData(callData) != CallTypeNone;
}
JSValue *JSObject::callAsFunction(ExecState* /*exec*/, JSObject* /*thisObj*/, const List &/*args*/)
@@ -613,16 +579,6 @@
return 0;
}
-void JSObject::putDirect(const Identifier &propertyName, JSValue *value, int attr)
-{
- _prop.put(propertyName, value, attr);
-}
-
-void JSObject::putDirect(const Identifier &propertyName, int value, int attr)
-{
- _prop.put(propertyName, jsNumber(value), attr);
-}
-
void JSObject::removeDirect(const Identifier &propertyName)
{
_prop.remove(propertyName);
diff --git a/JavaScriptCore/kjs/object.h b/JavaScriptCore/kjs/object.h
index 90f5c32..aebc4d0 100644
--- a/JavaScriptCore/kjs/object.h
+++ b/JavaScriptCore/kjs/object.h
@@ -234,14 +234,14 @@
*
* @return The specified property, or Undefined
*/
- JSValue *get(ExecState *exec, const Identifier &propertyName) const;
- JSValue *get(ExecState *exec, unsigned propertyName) const;
+ JSValue* get(ExecState* exec, const Identifier& propertyName) const;
+ JSValue* get(ExecState* exec, unsigned propertyName) const;
- bool getPropertySlot(ExecState *, const Identifier&, PropertySlot&);
- bool getPropertySlot(ExecState *, unsigned, PropertySlot&);
+ bool getPropertySlot(ExecState*, const Identifier&, PropertySlot&);
+ bool getPropertySlot(ExecState*, unsigned, PropertySlot&);
- virtual bool getOwnPropertySlot(ExecState *, const Identifier&, PropertySlot&);
- virtual bool getOwnPropertySlot(ExecState *, unsigned index, PropertySlot&);
+ virtual bool getOwnPropertySlot(ExecState*, const Identifier&, PropertySlot&);
+ virtual bool getOwnPropertySlot(ExecState*, unsigned index, PropertySlot&);
/**
* Sets the specified property.
@@ -316,16 +316,6 @@
virtual JSValue *defaultValue(ExecState *exec, JSType hint) const;
/**
- * Whether or not the object implements the construct() method. If this
- * returns false you should not call the construct() method on this
- * object (typically, an assertion will fail to indicate this).
- *
- * @return true if this object implements the construct() method, otherwise
- * false
- */
- virtual bool implementsConstruct() const;
-
- /**
* Creates a new object based on this object. Typically this means the
* following:
* 1. A new object is created
@@ -342,8 +332,8 @@
* will be set. This can be tested for with ExecState::hadException().
* Under some circumstances, the exception object may also be returned.
*
- * Note: This function should not be called if implementsConstruct() returns
- * false, in which case it will result in an assertion failure.
+ * Note: This function should not be called if getConstructData() returns
+ * ConstructTypeNone, in which case it will result in an assertion failure.
*
* @param exec The current execution state
* @param args The arguments to be passed to call() once the new object has
@@ -357,16 +347,6 @@
virtual JSObject* construct(ExecState* exec, const List& args, const Identifier& functionName, const UString& sourceURL, int lineNumber);
/**
- * Whether or not the object implements the call() method. If this returns
- * false you should not call the call() method on this object (typically,
- * an assertion will fail to indicate this).
- *
- * @return true if this object implements the call() method, otherwise
- * false
- */
- virtual bool implementsCall() const;
-
- /**
* Calls this object as if it is a function.
*
* Note: This function should not be called if implementsCall() returns
@@ -383,7 +363,9 @@
* @param args List of arguments to be passed to the function
* @return The return value from the function
*/
+ bool implementsCall();
JSValue *call(ExecState *exec, JSObject *thisObj, const List &args);
+
virtual JSValue *callAsFunction(ExecState *exec, JSObject *thisObj, const List &args);
/**
@@ -431,6 +413,8 @@
{ return _prop.get(propertyName); }
JSValue **getDirectLocation(const Identifier& propertyName)
{ return _prop.getLocation(propertyName); }
+ JSValue **getDirectLocation(const Identifier& propertyName, bool& isWriteable)
+ { return _prop.getLocation(propertyName, isWriteable); }
void putDirect(const Identifier &propertyName, JSValue *value, int attr = 0);
void putDirect(const Identifier &propertyName, int value, int attr = 0);
void removeDirect(const Identifier &propertyName);
@@ -451,6 +435,7 @@
protected:
PropertyMap _prop;
+ bool getOwnPropertySlotForWrite(ExecState*, const Identifier&, PropertySlot&, bool& slotIsWriteable);
private:
const HashEntry* findPropertyHashEntry(ExecState*, const Identifier& propertyName) const;
@@ -540,6 +525,25 @@
return !JSImmediate::isImmediate(this) && asCell()->isObject(c);
}
+inline JSValue *JSObject::get(ExecState *exec, const Identifier &propertyName) const
+{
+ PropertySlot slot;
+
+ if (const_cast<JSObject *>(this)->getPropertySlot(exec, propertyName, slot))
+ return slot.getValue(exec, const_cast<JSObject *>(this), propertyName);
+
+ return jsUndefined();
+}
+
+inline JSValue *JSObject::get(ExecState *exec, unsigned propertyName) const
+{
+ PropertySlot slot;
+ if (const_cast<JSObject *>(this)->getPropertySlot(exec, propertyName, slot))
+ return slot.getValue(exec, const_cast<JSObject *>(this), propertyName);
+
+ return jsUndefined();
+}
+
// It may seem crazy to inline a function this large but it makes a big difference
// since this is function very hot in variable lookup
inline bool JSObject::getPropertySlot(ExecState *exec, const Identifier& propertyName, PropertySlot& slot)
@@ -557,6 +561,48 @@
}
}
+inline bool JSObject::getPropertySlot(ExecState *exec, unsigned propertyName, PropertySlot& slot)
+{
+ JSObject *imp = this;
+
+ while (true) {
+ if (imp->getOwnPropertySlot(exec, propertyName, slot))
+ return true;
+
+ JSValue *proto = imp->_proto;
+ if (!proto->isObject())
+ break;
+
+ imp = static_cast<JSObject *>(proto);
+ }
+
+ return false;
+}
+
+// It may seem crazy to inline a function this large, especially a virtual function,
+// but it makes a big difference to property lookup that derived classes can inline their
+// base class call to this.
+ALWAYS_INLINE bool JSObject::getOwnPropertySlotForWrite(ExecState* exec, const Identifier& propertyName, PropertySlot& slot, bool& slotIsWriteable)
+{
+ if (JSValue **location = getDirectLocation(propertyName, slotIsWriteable)) {
+ if (_prop.hasGetterSetterProperties() && location[0]->type() == GetterSetterType) {
+ slotIsWriteable = false;
+ fillGetterPropertySlot(slot, location);
+ } else
+ slot.setValueSlot(this, location);
+ return true;
+ }
+
+ // non-standard Netscape extension
+ if (propertyName == exec->propertyNames().underscoreProto) {
+ slot.setValueSlot(this, &_proto);
+ slotIsWriteable = true;
+ return true;
+ }
+
+ return false;
+}
+
// It may seem crazy to inline a function this large, especially a virtual function,
// but it makes a big difference to property lookup that derived classes can inline their
// base class call to this.
@@ -579,17 +625,14 @@
return false;
}
-inline void ScopeChain::release()
+inline void JSObject::putDirect(const Identifier &propertyName, JSValue *value, int attr)
{
- // This function is only called by deref(),
- // Deref ensures these conditions are true.
- ASSERT(_node && _node->refCount == 0);
- ScopeChainNode *n = _node;
- do {
- ScopeChainNode *next = n->next;
- delete n;
- n = next;
- } while (n && --n->refCount == 0);
+ _prop.put(propertyName, value, attr);
+}
+
+inline void JSObject::putDirect(const Identifier &propertyName, int value, int attr)
+{
+ _prop.put(propertyName, jsNumber(value), attr);
}
inline JSValue* JSObject::toPrimitive(ExecState* exec, JSType preferredType) const
diff --git a/JavaScriptCore/kjs/object_object.cpp b/JavaScriptCore/kjs/object_object.cpp
index 9bc1fe2..24ca3fd 100644
--- a/JavaScriptCore/kjs/object_object.cpp
+++ b/JavaScriptCore/kjs/object_object.cpp
@@ -143,10 +143,9 @@
putDirect(exec->propertyNames().length, jsNumber(1), ReadOnly|DontDelete|DontEnum);
}
-
-bool ObjectObjectImp::implementsConstruct() const
+ConstructType ObjectObjectImp::getConstructData(ConstructData&)
{
- return true;
+ return ConstructTypeNative;
}
// ECMA 15.2.2
diff --git a/JavaScriptCore/kjs/object_object.h b/JavaScriptCore/kjs/object_object.h
index 0ee5482..c3348e9 100644
--- a/JavaScriptCore/kjs/object_object.h
+++ b/JavaScriptCore/kjs/object_object.h
@@ -47,8 +47,9 @@
public:
ObjectObjectImp(ExecState*, ObjectPrototype*, FunctionPrototype*);
- virtual bool implementsConstruct() const;
+ virtual ConstructType getConstructData(ConstructData&);
virtual JSObject* construct(ExecState*, const List&);
+
virtual JSValue* callAsFunction(ExecState*, JSObject*, const List&);
};
diff --git a/JavaScriptCore/kjs/operations.cpp b/JavaScriptCore/kjs/operations.cpp
index d2b3892..81da680 100644
--- a/JavaScriptCore/kjs/operations.cpp
+++ b/JavaScriptCore/kjs/operations.cpp
@@ -98,31 +98,28 @@
return v1 == v2;
}
-bool strictEqual(ExecState *exec, JSValue *v1, JSValue *v2)
+bool strictEqual(JSValue* v1, JSValue* v2)
{
JSType t1 = v1->type();
JSType t2 = v2->type();
if (t1 != t2)
return false;
- if (t1 == UndefinedType || t1 == NullType)
- return true;
- if (t1 == NumberType) {
- double n1 = v1->toNumber(exec);
- double n2 = v2->toNumber(exec);
- if (n1 == n2)
- return true;
- return false;
- } else if (t1 == StringType)
- return v1->toString(exec) == v2->toString(exec);
- else if (t2 == BooleanType)
- return v1->toBoolean(exec) == v2->toBoolean(exec);
+
+ if (t1 == NumberType)
+ return v1->getNumber() == v2->getNumber();
- if (v1 == v2)
- return true;
- /* TODO: joined objects */
+ if (t1 == StringType)
+ return static_cast<StringImp*>(v1)->value() == static_cast<StringImp*>(v2)->value();
- return false;
+ return v1 == v2; // covers object, boolean, null, and undefined types
+}
+
+JSValue* throwOutOfMemoryError(ExecState* exec)
+{
+ JSObject* error = Error::create(exec, GeneralError, "Out of memory");
+ exec->setException(error);
+ return error;
}
}
diff --git a/JavaScriptCore/kjs/operations.h b/JavaScriptCore/kjs/operations.h
index 96656f0..55f3ae9 100644
--- a/JavaScriptCore/kjs/operations.h
+++ b/JavaScriptCore/kjs/operations.h
@@ -29,7 +29,8 @@
class JSValue;
bool equal(ExecState *exec, JSValue *v1, JSValue *v2);
- bool strictEqual(ExecState *exec, JSValue *v1, JSValue *v2);
+ bool strictEqual(JSValue*, JSValue*);
+ JSValue* throwOutOfMemoryError(ExecState*);
}
#endif
diff --git a/JavaScriptCore/kjs/property_map.cpp b/JavaScriptCore/kjs/property_map.cpp
index 41d141a..0ecc8ab 100644
--- a/JavaScriptCore/kjs/property_map.cpp
+++ b/JavaScriptCore/kjs/property_map.cpp
@@ -327,6 +327,61 @@
}
}
+JSValue** PropertyMap::getLocation(const Identifier& name, bool& isWriteable)
+{
+ ASSERT(!name.isNull());
+
+ UString::Rep* rep = name._ustring.rep();
+
+ if (!m_usingTable) {
+#if USE_SINGLE_ENTRY
+ if (rep == m_singleEntryKey) {
+ isWriteable = !(m_singleEntryAttributes & ReadOnly);
+ return &m_u.singleEntryValue;
+ }
+#endif
+ return 0;
+ }
+
+ unsigned i = rep->computedHash();
+
+#if DUMP_PROPERTYMAP_STATS
+ ++numProbes;
+#endif
+
+ unsigned entryIndex = m_u.table->entryIndicies[i & m_u.table->sizeMask];
+ if (entryIndex == emptyEntryIndex)
+ return 0;
+
+ if (rep == m_u.table->entries()[entryIndex - 1].key) {
+ isWriteable = !(m_u.table->entries()[entryIndex - 1].attributes & ReadOnly);
+ return &m_u.table->entries()[entryIndex - 1].value;
+ }
+
+#if DUMP_PROPERTYMAP_STATS
+ ++numCollisions;
+#endif
+
+ unsigned k = 1 | doubleHash(rep->computedHash());
+
+ while (1) {
+ i += k;
+
+#if DUMP_PROPERTYMAP_STATS
+ ++numRehashes;
+#endif
+
+ entryIndex = m_u.table->entryIndicies[i & m_u.table->sizeMask];
+ if (entryIndex == emptyEntryIndex)
+ return 0;
+
+ if (rep == m_u.table->entries()[entryIndex - 1].key) {
+ isWriteable = !(m_u.table->entries()[entryIndex - 1].attributes & ReadOnly);
+ return &m_u.table->entries()[entryIndex - 1].value;
+ }
+ }
+}
+
void PropertyMap::put(const Identifier& name, JSValue* value, unsigned attributes, bool checkReadOnly)
{
ASSERT(!name.isNull());
diff --git a/JavaScriptCore/kjs/property_map.h b/JavaScriptCore/kjs/property_map.h
index 30f3612..e64071f 100644
--- a/JavaScriptCore/kjs/property_map.h
+++ b/JavaScriptCore/kjs/property_map.h
@@ -68,6 +68,7 @@
JSValue* get(const Identifier&) const;
JSValue* get(const Identifier&, unsigned& attributes) const;
JSValue** getLocation(const Identifier& name);
+ JSValue** getLocation(const Identifier& name, bool& isWriteable);
void mark() const;
void getEnumerablePropertyNames(PropertyNameArray&) const;
diff --git a/JavaScriptCore/kjs/property_slot.cpp b/JavaScriptCore/kjs/property_slot.cpp
index ef2525f..595965db 100644
--- a/JavaScriptCore/kjs/property_slot.cpp
+++ b/JavaScriptCore/kjs/property_slot.cpp
@@ -23,7 +23,10 @@
#include "config.h"
#include "property_slot.h"
+
+#include "JSGlobalObject.h"
#include "object.h"
+#include "RegisterFileStack.h"
namespace KJS {
@@ -40,7 +43,16 @@
JSValue *PropertySlot::functionGetter(ExecState* exec, JSObject* originalObject, const Identifier&, const PropertySlot& slot)
{
- return slot.m_data.getterFunc->call(exec, originalObject, exec->emptyList());
+ CallData data;
+ CallType callType = slot.m_data.getterFunc->getCallData(data);
+ if (callType == CallTypeNative)
+ return slot.m_data.getterFunc->call(exec, originalObject, exec->emptyList());
+ ASSERT(callType == CallTypeJS);
+ RegisterFileStack* stack = &exec->dynamicGlobalObject()->registerFileStack();
+ stack->pushFunctionRegisterFile();
+ JSValue* result = slot.m_data.getterFunc->call(exec, originalObject, exec->emptyList());
+ stack->popFunctionRegisterFile();
+ return result;
}
}
diff --git a/JavaScriptCore/kjs/property_slot.h b/JavaScriptCore/kjs/property_slot.h
index 4ec8b46..41ff671 100644
--- a/JavaScriptCore/kjs/property_slot.h
+++ b/JavaScriptCore/kjs/property_slot.h
@@ -57,6 +57,12 @@
return m_data.numericFunc(exec, originalObject, propertyName, *this);
return m_getValue(exec, originalObject, Identifier::from(propertyName), *this);
}
+
+ void putValue(JSValue* value)
+ {
+ ASSERT(m_getValue == KJS_VALUE_SLOT_MARKER);
+ *m_data.valueSlot = value;
+ }
void setValueSlot(JSObject* slotBase, JSValue** valueSlot)
{
diff --git a/JavaScriptCore/kjs/regexp_object.cpp b/JavaScriptCore/kjs/regexp_object.cpp
index b723798..196d967 100644
--- a/JavaScriptCore/kjs/regexp_object.cpp
+++ b/JavaScriptCore/kjs/regexp_object.cpp
@@ -230,9 +230,9 @@
: jsNull();
}
-bool RegExpImp::implementsCall() const
+CallType RegExpImp::getCallData(CallData&)
{
- return true;
+ return CallTypeNative;
}
JSValue* RegExpImp::callAsFunction(ExecState* exec, JSObject*, const List& args)
@@ -425,9 +425,9 @@
}
}
-bool RegExpObjectImp::implementsConstruct() const
+ConstructType RegExpObjectImp::getConstructData(ConstructData&)
{
- return true;
+ return ConstructTypeNative;
}
// ECMA 15.10.4
@@ -445,14 +445,10 @@
UString pattern = arg0->isUndefined() ? UString("") : arg0->toString(exec);
UString flags = arg1->isUndefined() ? UString("") : arg1->toString(exec);
- return createRegExpImp(exec, RegExp::create(pattern, flags));
-}
-
-JSObject* RegExpObjectImp::createRegExpImp(ExecState* exec, PassRefPtr<RegExp> regExp)
-{
- return regExp->isValid()
- ? new RegExpImp(static_cast<RegExpPrototype*>(exec->lexicalGlobalObject()->regExpPrototype()), regExp)
- : throwError(exec, SyntaxError, UString("Invalid regular expression: ").append(regExp->errorMessage()));
+ RefPtr<RegExp> regExp = RegExp::create(pattern, flags);
+ return regExp->isValid()
+ ? new RegExpImp(exec->lexicalGlobalObject()->regExpPrototype(), regExp.release())
+ : throwError(exec, SyntaxError, UString("Invalid regular expression: ").append(regExp->errorMessage()));
}
// ECMA 15.10.3
diff --git a/JavaScriptCore/kjs/regexp_object.h b/JavaScriptCore/kjs/regexp_object.h
index c69e8f7..8157c0d 100644
--- a/JavaScriptCore/kjs/regexp_object.h
+++ b/JavaScriptCore/kjs/regexp_object.h
@@ -49,8 +49,9 @@
JSValue* test(ExecState*, const List& args);
JSValue* exec(ExecState*, const List& args);
- virtual bool implementsCall() const;
+ virtual CallType getCallData(CallData&);
virtual JSValue* callAsFunction(ExecState*, JSObject*, const List&);
+
bool getOwnPropertySlot(ExecState*, const Identifier&, PropertySlot&);
JSValue* getValueProperty(ExecState*, int token) const;
void put(ExecState*, const Identifier&, JSValue*);
@@ -75,15 +76,18 @@
RegExpObjectImp(ExecState*, FunctionPrototype*, RegExpPrototype*);
- virtual bool implementsConstruct() const;
+ virtual ConstructType getConstructData(ConstructData&);
virtual JSObject* construct(ExecState*, const List&);
- JSObject* createRegExpImp(ExecState*, PassRefPtr<RegExp>);
+
virtual JSValue* callAsFunction(ExecState*, JSObject*, const List&);
+
virtual void put(ExecState*, const Identifier&, JSValue*);
void putValueProperty(ExecState*, int token, JSValue*);
virtual bool getOwnPropertySlot(ExecState*, const Identifier&, PropertySlot&);
JSValue* getValueProperty(ExecState*, int token) const;
+
virtual const ClassInfo* classInfo() const { return &info; }
+ static const ClassInfo info;
void performMatch(RegExp*, const UString&, int startOffset, int& position, int& length, int** ovector = 0);
JSObject* arrayOfMatches(ExecState*) const;
@@ -96,8 +100,6 @@
JSValue* getRightContext() const;
OwnPtr<RegExpObjectImpPrivate> d;
-
- static const ClassInfo info;
};
} // namespace
diff --git a/JavaScriptCore/kjs/scope_chain.cpp b/JavaScriptCore/kjs/scope_chain.cpp
index aba066a..9b8e976 100644
--- a/JavaScriptCore/kjs/scope_chain.cpp
+++ b/JavaScriptCore/kjs/scope_chain.cpp
@@ -1,6 +1,6 @@
/*
* This file is part of the KDE libraries
- * Copyright (C) 2003, 2006 Apple Inc.
+ * Copyright (C) 2003, 2006, 2008 Apple Inc.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Library General Public
@@ -21,25 +21,16 @@
#include "config.h"
#include "scope_chain.h"
+
#include "PropertyNameArray.h"
-#include <stdio.h>
#include "object.h"
+#include <stdio.h>
namespace KJS {
-void ScopeChain::push(const ScopeChain &c)
-{
- ScopeChainNode **tail = &_node;
- for (ScopeChainNode *n = c._node; n; n = n->next) {
- ScopeChainNode *newNode = new ScopeChainNode(*tail, n->object);
- *tail = newNode;
- tail = &newNode->next;
- }
-}
-
#ifndef NDEBUG
-void ScopeChain::print()
+void ScopeChainNode::print() const
{
ScopeChainIterator scopeEnd = end();
for (ScopeChainIterator scopeIter = begin(); scopeIter != scopeEnd; ++scopeIter) {
diff --git a/JavaScriptCore/kjs/scope_chain.h b/JavaScriptCore/kjs/scope_chain.h
index b409417..5383932 100644
--- a/JavaScriptCore/kjs/scope_chain.h
+++ b/JavaScriptCore/kjs/scope_chain.h
@@ -1,6 +1,6 @@
/*
* This file is part of the KDE libraries
- * Copyright (C) 2003 Apple Computer, Inc.
+ * Copyright (C) 2003, 2008 Apple Computer, Inc.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Library General Public
@@ -19,32 +19,106 @@
*
*/
-#ifndef KJS_SCOPE_CHAIN_H
-#define KJS_SCOPE_CHAIN_H
+#ifndef ScopeChain_h
+#define ScopeChain_h
#include <wtf/Assertions.h>
namespace KJS {
+ class JSGlobalObject;
class JSObject;
- class ExecState;
+ class ScopeChainIterator;
class ScopeChainNode {
public:
- ScopeChainNode(ScopeChainNode *n, JSObject *o)
- : next(n), object(o), refCount(1) { }
+ ScopeChainNode(ScopeChainNode* n, JSObject* o)
+ : next(n)
+ , object(o)
+ , refCount(1)
+ {
+ }
- ScopeChainNode *next;
- JSObject *object;
+ ScopeChainNode* next;
+ JSObject* object;
int refCount;
+
+ void deref() { if (--refCount == 0) release(); }
+ void ref() { ++refCount; }
+ void release();
+
+ // Before calling "push" on a bare ScopeChainNode, a client should
+ // logically "copy" the node. Later, the client can "deref" the head
+ // of its chain of ScopeChainNodes to reclaim all the nodes it added
+ // after the logical copy, leaving nodes added before the logical copy
+ // (nodes shared with other clients) untouched.
+ ScopeChainNode* copy()
+ {
+ ref();
+ return this;
+ }
+
+ JSObject* bottom() const;
+
+ ScopeChainNode* push(JSObject*);
+ ScopeChainNode* pop();
+
+ ScopeChainIterator begin() const;
+ ScopeChainIterator end() const;
+
+ JSGlobalObject* globalObject() const; // defined in JSGlobalObject.h
+
+#ifndef NDEBUG
+ void print() const;
+#endif
};
+ inline ScopeChainNode* ScopeChainNode::push(JSObject* o)
+ {
+ ASSERT(o);
+ return new ScopeChainNode(this, o);
+ }
+
+ inline ScopeChainNode* ScopeChainNode::pop()
+ {
+ ASSERT(next);
+ ScopeChainNode* result = next;
+
+ if (--refCount != 0)
+ ++result->refCount;
+ else
+ delete this;
+
+ return result;
+ }
+
+ inline JSObject* ScopeChainNode::bottom() const
+ {
+ const ScopeChainNode* n = this;
+ while (n->next)
+ n = n->next;
+ return n->object;
+ }
+
+ inline void ScopeChainNode::release()
+ {
+ // This function is only called by deref(),
+ // Deref ensures these conditions are true.
+ ASSERT(refCount == 0);
+ ScopeChainNode* n = this;
+ do {
+ ScopeChainNode* next = n->next;
+ delete n;
+ n = next;
+ } while (n && --n->refCount == 0);
+ }
+
class ScopeChainIterator {
public:
- ScopeChainIterator(ScopeChainNode *node) : m_node(node) {}
+ ScopeChainIterator(const ScopeChainNode* node) : m_node(node) {}
- JSObject * const & operator*() const { return m_node->object; }
- JSObject * const * operator->() const { return &(operator*()); }
+ JSObject* const & operator*() const { return m_node->object; }
+ JSObject* const * operator->() const { return &(operator*()); }
ScopeChainIterator& operator++() { m_node = m_node->next; return *this; }
@@ -54,129 +128,81 @@
bool operator!=(const ScopeChainIterator& other) const { return m_node != other.m_node; }
private:
- ScopeChainNode *m_node;
+ const ScopeChainNode* m_node;
};
+ inline ScopeChainIterator ScopeChainNode::begin() const
+ {
+ return ScopeChainIterator(this);
+ }
+
+ inline ScopeChainIterator ScopeChainNode::end() const
+ {
+ return ScopeChainIterator(0);
+ }
+
class ScopeChain {
public:
- typedef ScopeChainIterator const_iterator;
- typedef JSObject* ValueType;
-
- ScopeChain() : _node(0) { }
- ~ScopeChain() { deref(); }
-
- ScopeChain(const ScopeChain& c)
- : _node(c._node)
- {
- if (_node)
- ++_node->refCount;
- }
-
ScopeChain(JSObject* o)
: _node(new ScopeChainNode(0, o))
{
}
- ScopeChain &operator=(const ScopeChain &);
+ ScopeChain(const ScopeChain& c)
+ : _node(c._node->copy())
+ {
+ }
- bool isEmpty() const { return !_node; }
- JSObject *top() const { return _node->object; }
+ ScopeChain& operator=(const ScopeChain& c);
- JSObject *bottom() const;
+ explicit ScopeChain(ScopeChainNode* node)
+ : _node(node->copy())
+ {
+ }
+
+ ~ScopeChain() { _node->deref(); }
- ScopeChainIterator begin() const { return ScopeChainIterator(_node); }
- ScopeChainIterator end() const { return ScopeChainIterator(0); }
+ void swap(ScopeChain&);
- void clear() { deref(); _node = 0; }
- void push(JSObject *);
- void push(const ScopeChain &);
- void push(ScopeChainNode*);
- void replaceTop(JSObject*);
- void pop();
- void popInlineScopeNode();
+ ScopeChainNode* node() const { return _node; }
- void mark();
+ JSObject* top() const { return _node->object; }
+ JSObject* bottom() const { return _node->bottom(); }
+
+ ScopeChainIterator begin() const { return _node->begin(); }
+ ScopeChainIterator end() const { return _node->end(); }
+
+ void push(JSObject* o) { _node = _node->push(o); }
+
+ void pop() { _node = _node->pop(); }
+ void clear() { _node->deref(); _node = 0; }
+
+ JSGlobalObject* globalObject() const { return _node->globalObject(); }
+
+ void mark() const;
#ifndef NDEBUG
- void print();
+ void print() const { _node->print(); }
#endif
private:
- ScopeChainNode *_node;
-
- void deref() { if (_node && --_node->refCount == 0) release(); }
- void ref() const;
-
- void release();
+ ScopeChainNode* _node;
};
-inline void ScopeChain::ref() const
-{
- for (ScopeChainNode *n = _node; n; n = n->next) {
- if (n->refCount++ != 0)
- break;
+ inline void ScopeChain::swap(ScopeChain& o)
+ {
+ ScopeChainNode* tmp = _node;
+ _node = o._node;
+ o._node = tmp;
}
-}
-inline ScopeChain &ScopeChain::operator=(const ScopeChain &c)
-{
- c.ref();
- deref();
- _node = c._node;
- return *this;
-}
-
-inline JSObject *ScopeChain::bottom() const
-{
- ScopeChainNode *last = 0;
- for (ScopeChainNode *n = _node; n; n = n->next)
- last = n;
- if (!last)
- return 0;
- return last->object;
-}
-
-inline void ScopeChain::push(JSObject *o)
-{
- ASSERT(o);
- _node = new ScopeChainNode(_node, o);
-}
-
-inline void ScopeChain::push(ScopeChainNode *node)
-{
- ASSERT(node);
- ASSERT(node->object);
- node->refCount++;
- node->next = _node;
- _node = node;
-}
-
-inline void ScopeChain::replaceTop(JSObject* o)
-{
- ASSERT(o);
- _node->object = o;
-}
-
-inline void ScopeChain::pop()
-{
- ScopeChainNode *oldNode = _node;
- ASSERT(oldNode);
- ScopeChainNode *newNode = oldNode->next;
- _node = newNode;
-
- if (--oldNode->refCount != 0) {
- if (newNode)
- ++newNode->refCount;
- } else {
- delete oldNode;
+ inline ScopeChain& ScopeChain::operator=(const ScopeChain& c)
+ {
+ ScopeChain tmp(c);
+ swap(tmp);
+ return *this;
}
-}
-
-inline void ScopeChain::popInlineScopeNode()
-{
- _node = _node->next;
-}
} // namespace KJS
-#endif // KJS_SCOPE_CHAIN_H
+#endif // ScopeChain_h
diff --git a/JavaScriptCore/kjs/scope_chain_mark.h b/JavaScriptCore/kjs/scope_chain_mark.h
index bc4d5f8..a60fdd7 100644
--- a/JavaScriptCore/kjs/scope_chain_mark.h
+++ b/JavaScriptCore/kjs/scope_chain_mark.h
@@ -21,25 +21,15 @@
#ifndef scope_chain_mark_h
#define scope_chain_mark_h
-#include "Activation.h"
#include "scope_chain.h"
namespace KJS {
- inline void ScopeChain::mark()
+ inline void ScopeChain::mark() const
{
for (ScopeChainNode* n = _node; n; n = n->next) {
JSObject* o = n->object;
-
- // An ActivationImp that is on the activation stack can't have the
- // JSObject::marked() method called on it, because it doesn't have an
- // entry in a GC mark bitmap, so we check here whether it is on the
- // stack and directly call the portion of the marking code that is
- // still relevant.
-
- if (o->isActivationObject() && static_cast<ActivationImp*>(o)->isOnStack())
- static_cast<ActivationImp*>(o)->markChildren();
- else if (!o->marked())
+ if (!o->marked())
o->mark();
}
}
diff --git a/JavaScriptCore/kjs/string_object.cpp b/JavaScriptCore/kjs/string_object.cpp
index 415ae37..8a55e53 100644
--- a/JavaScriptCore/kjs/string_object.cpp
+++ b/JavaScriptCore/kjs/string_object.cpp
@@ -972,9 +972,9 @@
}
-bool StringObjectImp::implementsConstruct() const
+ConstructType StringObjectImp::getConstructData(ConstructData&)
{
- return true;
+ return ConstructTypeNative;
}
// ECMA 15.5.2
diff --git a/JavaScriptCore/kjs/string_object.h b/JavaScriptCore/kjs/string_object.h
index 8508788..d53b1db 100644
--- a/JavaScriptCore/kjs/string_object.h
+++ b/JavaScriptCore/kjs/string_object.h
@@ -126,13 +126,12 @@
*/
class StringObjectImp : public InternalFunctionImp {
public:
- StringObjectImp(ExecState *exec,
- FunctionPrototype *funcProto,
- StringPrototype *stringProto);
+ StringObjectImp(ExecState*, FunctionPrototype*, StringPrototype*);
- virtual bool implementsConstruct() const;
- virtual JSObject *construct(ExecState *exec, const List &args);
- virtual JSValue *callAsFunction(ExecState *exec, JSObject *thisObj, const List &args);
+ virtual ConstructType getConstructData(ConstructData&);
+ virtual JSObject* construct(ExecState*, const List&);
+
+ virtual JSValue* callAsFunction(ExecState*, JSObject* thisObj, const List& args);
};
/**
diff --git a/JavaScriptCore/kjs/testkjs.cpp b/JavaScriptCore/kjs/testkjs.cpp
index 153bdf9..26f5d2e 100644
--- a/JavaScriptCore/kjs/testkjs.cpp
+++ b/JavaScriptCore/kjs/testkjs.cpp
@@ -22,6 +22,7 @@
#include "config.h"
+#include "CodeGenerator.h"
#include "JSGlobalObject.h"
#include "JSLock.h"
#include "Parser.h"
@@ -183,8 +184,10 @@
if (!fillBufferWithContentsOfFile(fileName, script))
return throwError(exec, GeneralError, "Could not open file.");
+ JSGlobalObject* globalObject = exec->dynamicGlobalObject();
+
stopWatch.start();
- Interpreter::evaluate(exec->dynamicGlobalObject()->globalExec(), fileName, 0, script.data());
+ Interpreter::evaluate(globalObject->globalExec(), globalObject->globalScopeChain(), fileName, 0, script.data());
stopWatch.stop();
return jsNumber(stopWatch.getElapsedMS());
@@ -197,7 +200,8 @@
if (!fillBufferWithContentsOfFile(fileName, script))
return throwError(exec, GeneralError, "Could not open file.");
- Interpreter::evaluate(exec->dynamicGlobalObject()->globalExec(), fileName, 0, script.data());
+ JSGlobalObject* globalObject = exec->dynamicGlobalObject();
+ Interpreter::evaluate(globalObject->globalExec(), globalObject->globalScopeChain(), fileName, 0, script.data());
return jsUndefined();
}
@@ -258,12 +262,12 @@
return res;
}
-static bool prettyPrintScript(const UString& fileName, const Vector<char>& script)
+static bool prettyPrintScript(ExecState* exec, const UString& fileName, const Vector<char>& script)
{
int errLine = 0;
UString errMsg;
UString scriptUString(script.data());
- RefPtr<ProgramNode> programNode = parser().parse<ProgramNode>(fileName, 0, scriptUString.data(), scriptUString.size(), 0, &errLine, &errMsg);
+ RefPtr<ProgramNode> programNode = parser().parse<ProgramNode>(exec, fileName, 0, UStringSourceProvider::create(scriptUString), 0, &errLine, &errMsg);
if (!programNode) {
fprintf(stderr, "%s:%d: %s.\n", fileName.UTF8String().c_str(), errLine, errMsg.UTF8String().c_str());
return false;
@@ -273,11 +277,14 @@
return true;
}
-static bool runWithScripts(const Vector<UString>& fileNames, Vector<UString>& arguments, bool prettyPrint)
+static bool runWithScripts(const Vector<UString>& fileNames, Vector<UString>& arguments, bool prettyPrint, bool dump)
{
GlobalObject* globalObject = new GlobalObject(arguments);
Vector<char> script;
+ if (dump)
+ CodeGenerator::setDumpsGeneratedCode(true);
+
bool success = true;
for (size_t i = 0; i < fileNames.size(); i++) {
@@ -287,10 +294,16 @@
return false; // fail early so we can catch missing files
if (prettyPrint)
- prettyPrintScript(fileName, script);
+ prettyPrintScript(globalObject->globalExec(), fileName, script);
else {
- Completion completion = Interpreter::evaluate(globalObject->globalExec(), fileName, 0, script.data());
+ Completion completion = Interpreter::evaluate(globalObject->globalExec(), globalObject->globalScopeChain(), fileName, 0, script.data());
success = success && completion.complType() != Throw;
+ if (dump) {
+ if (success)
+ printf("End: %s\n", completion.value()->toString(globalObject->globalExec()).ascii());
+ else
+ printf("Exception: %s\n", completion.value()->toString(globalObject->globalExec()).ascii());
+ }
}
}
return success;
@@ -302,7 +315,7 @@
exit(-1);
}
-static void parseArguments(int argc, char** argv, Vector<UString>& fileNames, Vector<UString>& arguments, bool& prettyPrint)
+static void parseArguments(int argc, char** argv, Vector<UString>& fileNames, Vector<UString>& arguments, bool& prettyPrint, bool& dump)
{
if (argc < 3)
printUsageStatement();
@@ -320,6 +333,19 @@
prettyPrint = true;
continue;
}
+ if (strcmp(arg, "-d") == 0) {
+ dump = true;
+ continue;
+ }
+ if (strcmp(arg, "-s") == 0) {
+#if PLATFORM(UNIX)
+ signal(SIGILL, _exit);
+ signal(SIGFPE, _exit);
+ signal(SIGBUS, _exit);
+ signal(SIGSEGV, _exit);
+#endif
+ continue;
+ }
if (strcmp(arg, "--") == 0) {
++i;
break;
@@ -338,11 +364,12 @@
JSLock lock;
bool prettyPrint = false;
+ bool dump = false;
Vector<UString> fileNames;
Vector<UString> arguments;
- parseArguments(argc, argv, fileNames, arguments, prettyPrint);
+ parseArguments(argc, argv, fileNames, arguments, prettyPrint, dump);
- bool success = runWithScripts(fileNames, arguments, prettyPrint);
+ bool success = runWithScripts(fileNames, arguments, prettyPrint, dump);
#ifndef NDEBUG
Collector::collect();
diff --git a/JavaScriptCore/kjs/testkjs.pro b/JavaScriptCore/kjs/testkjs.pro
index cabeace..3886f20 100644
--- a/JavaScriptCore/kjs/testkjs.pro
+++ b/JavaScriptCore/kjs/testkjs.pro
@@ -4,7 +4,12 @@
SOURCES = testkjs.cpp
QT -= gui
DEFINES -= KJS_IDENTIFIER_HIDE_GLOBALS
-INCLUDEPATH += $$PWD/.. $$PWD $$PWD/../bindings $$PWD/../bindings/c $$PWD/../wtf
+INCLUDEPATH += $$PWD/.. \
+ $$PWD \
+ $$PWD/../bindings \
+ $$PWD/../bindings/c \
+ $$PWD/../wtf \
+ $$PWD/../VM
CONFIG -= app_bundle
DEFINES += BUILDING_QT__
diff --git a/JavaScriptCore/kjs/value.cpp b/JavaScriptCore/kjs/value.cpp
index 55da40b..0b67849 100644
--- a/JavaScriptCore/kjs/value.cpp
+++ b/JavaScriptCore/kjs/value.cpp
@@ -207,6 +207,16 @@
return isObject() ? static_cast<const JSObject *>(this) : 0;
}
+CallType JSCell::getCallData(CallData&)
+{
+ return CallTypeNone;
+}
+
+ConstructType JSCell::getConstructData(ConstructData&)
+{
+ return ConstructTypeNone;
+}
+
JSCell* jsString(const char* s)
{
return new StringImp(s ? s : "");
@@ -222,11 +232,4 @@
return s.isNull() ? new StringImp("", StringImp::HasOtherOwner) : new StringImp(s, StringImp::HasOtherOwner);
}
-// This method includes a PIC branch to set up the NumberImp's vtable, so we quarantine
-// it in a separate function to keep the normal case speedy.
-JSValue *jsNumberCell(double d)
-{
- return new NumberImp(d);
-}
-
} // namespace KJS
diff --git a/JavaScriptCore/kjs/value.h b/JavaScriptCore/kjs/value.h
index dfbeee4..916bea9 100644
--- a/JavaScriptCore/kjs/value.h
+++ b/JavaScriptCore/kjs/value.h
@@ -23,6 +23,8 @@
#ifndef KJS_VALUE_H
#define KJS_VALUE_H
+#include "CallData.h"
+#include "ConstructData.h"
#include "JSImmediate.h"
#include "collector.h"
#include "ustring.h"
@@ -35,6 +37,7 @@
class JSCell;
struct ClassInfo;
+struct Instruction;
/**
* JSValue is the base type for all primitives (Undefined, Null, Boolean,
@@ -69,21 +72,28 @@
bool getBoolean() const; // false if not a boolean
bool getNumber(double&) const;
double getNumber() const; // NaN if not a number
+ double uncheckedGetNumber() const;
bool getString(UString&) const;
UString getString() const; // null string if not a string
JSObject *getObject(); // NULL if not an object
const JSObject *getObject() const; // NULL if not an object
+ CallType getCallData(CallData&);
+ ConstructType getConstructData(ConstructData&);
+
// Extracting integer values.
bool getUInt32(uint32_t&) const;
bool getTruncatedInt32(int32_t&) const;
bool getTruncatedUInt32(uint32_t&) const;
-
+
// Basic conversions.
JSValue* toPrimitive(ExecState* exec, JSType preferredType = UnspecifiedType) const;
bool getPrimitiveNumber(ExecState* exec, double& number, JSValue*& value);
bool toBoolean(ExecState *exec) const;
+
+ // toNumber conversion is expected to be side effect free if an exception has
+ // been set in the ExecState already.
double toNumber(ExecState *exec) const;
JSValue* toJSNumber(ExecState*) const; // Fast path for when you expect that the value is an immediate number.
UString toString(ExecState *exec) const;
@@ -130,6 +140,7 @@
friend class StringImp;
friend class JSObject;
friend class GetterSetterImp;
+ friend class JSPropertyNameIterator;
private:
JSCell();
virtual ~JSCell();
@@ -148,6 +159,9 @@
UString getString() const; // null string if not a string
JSObject *getObject(); // NULL if not an object
const JSObject *getObject() const; // NULL if not an object
+
+ virtual CallType getCallData(CallData&);
+ virtual ConstructType getConstructData(ConstructData&);
// Extracting integer values.
virtual bool getUInt32(uint32_t&) const;
@@ -168,7 +182,35 @@
bool marked() const;
};
-JSValue *jsNumberCell(double);
+class NumberImp : public JSCell {
+ friend JSValue* jsNumberCell(double);
+
+public:
+ double value() const { return val; }
+
+ virtual JSType type() const;
+
+ virtual JSValue* toPrimitive(ExecState*, JSType preferred = UnspecifiedType) const;
+ virtual bool getPrimitiveNumber(ExecState*, double& number, JSValue*& value);
+ virtual bool toBoolean(ExecState* exec) const;
+ virtual double toNumber(ExecState* exec) const;
+ virtual UString toString(ExecState* exec) const;
+ virtual JSObject* toObject(ExecState* exec) const;
+
+ void* operator new(size_t size)
+ {
+ return Collector::allocateNumber(size);
+ }
+
+private:
+ NumberImp(double v) : val(v) { }
+
+ virtual bool getUInt32(uint32_t&) const;
+ virtual bool getTruncatedInt32(int32_t&) const;
+ virtual bool getTruncatedUInt32(uint32_t&) const;
+
+ double val;
+};
JSCell *jsString(const UString&); // returns empty string if passed null string
JSCell *jsString(const char* = ""); // returns empty string if passed 0
@@ -181,7 +223,14 @@
extern const double NaN;
extern const double Inf;
-inline JSValue *jsUndefined()
+// Beware marking this function ALWAYS_INLINE: It takes a PIC branch, so
+// inlining it may not always be a win.
+inline JSValue* jsNumberCell(double d)
+{
+ return new NumberImp(d);
+}
+
+ALWAYS_INLINE JSValue *jsUndefined()
{
return JSImmediate::undefinedImmediate();
}
@@ -367,6 +416,12 @@
return JSImmediate::isImmediate(this) ? JSImmediate::toDouble(this) : asCell()->getNumber();
}
+inline double JSValue::uncheckedGetNumber() const
+{
+ ASSERT(JSImmediate::isImmediate(this) || asCell()->isNumber());
+ return JSImmediate::isImmediate(this) ? JSImmediate::toDouble(this) : static_cast<const NumberImp*>(this)->value();
+}
+
inline bool JSValue::getString(UString& s) const
{
return !JSImmediate::isImmediate(this) && asCell()->getString(s);
@@ -387,6 +442,16 @@
return JSImmediate::isImmediate(this) ? 0 : asCell()->getObject();
}
+inline CallType JSValue::getCallData(CallData& callData)
+{
+ return JSImmediate::isImmediate(this) ? CallTypeNone : asCell()->getCallData(callData);
+}
+
+inline ConstructType JSValue::getConstructData(ConstructData& constructData)
+{
+ return JSImmediate::isImmediate(this) ? ConstructTypeNone : asCell()->getConstructData(constructData);
+}
+
ALWAYS_INLINE bool JSValue::getUInt32(uint32_t& v) const
{
return JSImmediate::isImmediate(this) ? JSImmediate::getUInt32(this, v) : asCell()->getUInt32(v);