summaryrefslogtreecommitdiff
path: root/Source/JavaScriptCore/interpreter/Interpreter.h
diff options
context:
space:
mode:
Diffstat (limited to 'Source/JavaScriptCore/interpreter/Interpreter.h')
-rw-r--r--Source/JavaScriptCore/interpreter/Interpreter.h193
1 files changed, 108 insertions, 85 deletions
diff --git a/Source/JavaScriptCore/interpreter/Interpreter.h b/Source/JavaScriptCore/interpreter/Interpreter.h
index e5eca0e1c..aba745f17 100644
--- a/Source/JavaScriptCore/interpreter/Interpreter.h
+++ b/Source/JavaScriptCore/interpreter/Interpreter.h
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2008, 2013 Apple Inc. All rights reserved.
+ * Copyright (C) 2008, 2013, 2015 Apple Inc. All rights reserved.
* Copyright (C) 2012 Research In Motion Limited. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -11,7 +11,7 @@
* 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
+ * 3. Neither the name of Apple 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.
*
@@ -33,11 +33,12 @@
#include "ArgList.h"
#include "JSCJSValue.h"
#include "JSCell.h"
-#include "JSFunction.h"
#include "JSObject.h"
#include "JSStack.h"
#include "LLIntData.h"
#include "Opcode.h"
+#include "SourceProvider.h"
+#include "StackAlignment.h"
#include <wtf/HashMap.h>
#include <wtf/text/StringBuilder.h>
@@ -49,16 +50,23 @@ namespace JSC {
class ExecutableBase;
class FunctionExecutable;
class VM;
+ class JSFunction;
class JSGlobalObject;
+ class JSModuleEnvironment;
+ class JSModuleRecord;
class LLIntOffsetsExtractor;
class ProgramExecutable;
+ class ModuleProgramExecutable;
class Register;
class JSScope;
class SamplingTool;
struct CallFrameClosure;
struct HandlerInfo;
struct Instruction;
-
+ struct ProtoCallFrame;
+
+ enum UnwindStart { UnwindFromCurrentFrame, UnwindFromCallerFrame };
+
enum DebugHookID {
WillExecuteProgram,
DidExecuteProgram,
@@ -71,6 +79,7 @@ namespace JSC {
enum StackFrameCodeType {
StackFrameGlobalCode,
StackFrameEvalCode,
+ StackFrameModuleCode,
StackFrameFunctionCode,
StackFrameNativeCode
};
@@ -78,7 +87,7 @@ namespace JSC {
struct StackFrame {
Strong<JSObject> callee;
StackFrameCodeType codeType;
- Strong<ExecutableBase> executable;
+ Strong<ScriptExecutable> executable;
Strong<UnlinkedCodeBlock> codeBlock;
RefPtr<SourceProvider> code;
int lineOffset;
@@ -87,58 +96,38 @@ namespace JSC {
unsigned bytecodeOffset;
String sourceURL;
JS_EXPORT_PRIVATE String toString(CallFrame*);
- String friendlySourceURL() const
- {
- String traceLine;
-
- switch (codeType) {
- case StackFrameEvalCode:
- case StackFrameFunctionCode:
- case StackFrameGlobalCode:
- if (!sourceURL.isEmpty())
- traceLine = sourceURL.impl();
- break;
- case StackFrameNativeCode:
- traceLine = "[native code]";
- break;
- }
- return traceLine.isNull() ? emptyString() : traceLine;
- }
- String friendlyFunctionName(CallFrame* callFrame) const
- {
- String traceLine;
- JSObject* stackFrameCallee = callee.get();
-
- switch (codeType) {
- case StackFrameEvalCode:
- traceLine = "eval code";
- break;
- case StackFrameNativeCode:
- if (callee)
- traceLine = getCalculatedDisplayName(callFrame, stackFrameCallee).impl();
- break;
- case StackFrameFunctionCode:
- traceLine = getCalculatedDisplayName(callFrame, stackFrameCallee).impl();
- break;
- case StackFrameGlobalCode:
- traceLine = "global code";
- break;
- }
- return traceLine.isNull() ? emptyString() : traceLine;
- }
+ String friendlySourceURL() const;
+ String friendlyFunctionName(CallFrame*) const;
JS_EXPORT_PRIVATE void computeLineAndColumn(unsigned& line, unsigned& column);
private:
void expressionInfo(int& divot, int& startOffset, int& endOffset, unsigned& line, unsigned& column);
};
+ class SuspendExceptionScope {
+ public:
+ SuspendExceptionScope(VM* vm)
+ : m_vm(vm)
+ {
+ oldException = vm->exception();
+ vm->clearException();
+ }
+ ~SuspendExceptionScope()
+ {
+ m_vm->restorePreviousException(oldException);
+ }
+ private:
+ Exception* oldException;
+ VM* m_vm;
+ };
+
class TopCallFrameSetter {
public:
- TopCallFrameSetter(VM& global, CallFrame* callFrame)
- : vm(global)
- , oldCallFrame(global.topCallFrame)
+ TopCallFrameSetter(VM& currentVM, CallFrame* callFrame)
+ : vm(currentVM)
+ , oldCallFrame(currentVM.topCallFrame)
{
- global.topCallFrame = callFrame;
+ currentVM.topCallFrame = callFrame;
}
~TopCallFrameSetter()
@@ -152,33 +141,52 @@ namespace JSC {
class NativeCallFrameTracer {
public:
- ALWAYS_INLINE NativeCallFrameTracer(VM* global, CallFrame* callFrame)
+ ALWAYS_INLINE NativeCallFrameTracer(VM* vm, CallFrame* callFrame)
{
- ASSERT(global);
+ ASSERT(vm);
ASSERT(callFrame);
- global->topCallFrame = callFrame;
+ ASSERT(callFrame < vm->topVMEntryFrame);
+ vm->topCallFrame = callFrame;
}
};
+ class NativeCallFrameTracerWithRestore {
+ public:
+ ALWAYS_INLINE NativeCallFrameTracerWithRestore(VM* vm, VMEntryFrame* vmEntryFrame, CallFrame* callFrame)
+ : m_vm(vm)
+ {
+ ASSERT(vm);
+ ASSERT(callFrame);
+ m_savedTopVMEntryFrame = vm->topVMEntryFrame;
+ m_savedTopCallFrame = vm->topCallFrame;
+ vm->topVMEntryFrame = vmEntryFrame;
+ vm->topCallFrame = callFrame;
+ }
+
+ ALWAYS_INLINE ~NativeCallFrameTracerWithRestore()
+ {
+ m_vm->topVMEntryFrame = m_savedTopVMEntryFrame;
+ m_vm->topCallFrame = m_savedTopCallFrame;
+ }
+
+ private:
+ VM* m_vm;
+ VMEntryFrame* m_savedTopVMEntryFrame;
+ CallFrame* m_savedTopCallFrame;
+ };
+
class Interpreter {
WTF_MAKE_FAST_ALLOCATED;
friend class CachedCall;
friend class LLIntOffsetsExtractor;
friend class JIT;
+ friend class VM;
public:
- class ErrorHandlingMode {
- public:
- JS_EXPORT_PRIVATE ErrorHandlingMode(ExecState*);
- JS_EXPORT_PRIVATE ~ErrorHandlingMode();
- private:
- Interpreter& m_interpreter;
- };
-
Interpreter(VM &);
~Interpreter();
- void initialize(bool canUseJIT);
+ void initialize();
JSStack& stack() { return m_stack; }
@@ -195,7 +203,7 @@ namespace JSC {
OpcodeID getOpcodeID(Opcode opcode)
{
ASSERT(m_initialized);
-#if ENABLE(COMPUTED_GOTO_OPCODES) && ENABLE(LLINT)
+#if ENABLE(COMPUTED_GOTO_OPCODES)
ASSERT(isOpcode(opcode));
return m_opcodeIDTable.get(opcode);
#else
@@ -207,24 +215,23 @@ namespace JSC {
JSValue execute(ProgramExecutable*, CallFrame*, JSObject* thisObj);
JSValue executeCall(CallFrame*, JSObject* function, CallType, const CallData&, JSValue thisValue, const ArgList&);
- JSObject* executeConstruct(CallFrame*, JSObject* function, ConstructType, const ConstructData&, const ArgList&);
+ JSObject* executeConstruct(CallFrame*, JSObject* function, ConstructType, const ConstructData&, const ArgList&, JSValue newTarget);
JSValue execute(EvalExecutable*, CallFrame*, JSValue thisValue, JSScope*);
+ JSValue execute(ModuleProgramExecutable*, CallFrame*, JSModuleEnvironment*);
- JSValue retrieveArgumentsFromVMCode(CallFrame*, JSFunction*) const;
- JSValue retrieveCallerFromVMCode(CallFrame*, JSFunction*) const;
- JS_EXPORT_PRIVATE void retrieveLastCaller(CallFrame*, int& lineNumber, intptr_t& sourceID, String& sourceURL, JSValue& function) const;
-
void getArgumentsData(CallFrame*, JSFunction*&, ptrdiff_t& firstParameterIndex, Register*& argv, int& argc);
SamplingTool* sampler() { return m_sampler.get(); }
- bool isInErrorHandlingMode() { return m_errorHandlingModeReentry; }
+ NEVER_INLINE HandlerInfo* unwind(VM&, CallFrame*&, Exception*, UnwindStart);
+ void notifyDebuggerOfExceptionToBeThrown(CallFrame*, Exception*);
+ NEVER_INLINE void debug(CallFrame*, DebugHookID);
+ JSString* stackTraceAsString(ExecState*, Vector<StackFrame>);
- NEVER_INLINE HandlerInfo* throwException(CallFrame*&, JSValue&, unsigned bytecodeOffset);
- NEVER_INLINE void debug(CallFrame*, DebugHookID, int firstLine, int lastLine, int column);
- static const String getTraceLine(CallFrame*, StackFrameCodeType, const String&, int);
- JS_EXPORT_PRIVATE static void getStackTrace(VM*, Vector<StackFrame>& results, size_t maxStackSize = std::numeric_limits<size_t>::max());
- static void addStackTraceIfNecessary(CallFrame*, JSValue error);
+ static EncodedJSValue JSC_HOST_CALL constructWithErrorConstructor(ExecState*);
+ static EncodedJSValue JSC_HOST_CALL callErrorConstructor(ExecState*);
+ static EncodedJSValue JSC_HOST_CALL constructWithNativeErrorConstructor(ExecState*);
+ static EncodedJSValue JSC_HOST_CALL callNativeErrorConstructor(ExecState*);
void dumpSampleData(ExecState* exec);
void startSampling();
@@ -232,29 +239,30 @@ namespace JSC {
JS_EXPORT_PRIVATE void dumpCallFrame(CallFrame*);
+ void getStackTrace(Vector<StackFrame>& results, size_t maxStackSize = std::numeric_limits<size_t>::max());
+
private:
enum ExecutionFlag { Normal, InitializeAndReturn };
- CallFrameClosure prepareForRepeatCall(FunctionExecutable*, CallFrame*, JSFunction*, int argumentCountIncludingThis, JSScope*);
- void endRepeatCall(CallFrameClosure&);
+ CallFrameClosure prepareForRepeatCall(FunctionExecutable*, CallFrame*, ProtoCallFrame*, JSFunction*, int argumentCountIncludingThis, JSScope*, JSValue*);
+
JSValue execute(CallFrameClosure&);
- NEVER_INLINE bool unwindCallFrame(CallFrame*&, JSValue, unsigned& bytecodeOffset, CodeBlock*&);
- static CallFrame* findFunctionCallFrameFromVMCode(CallFrame*, JSFunction*);
void dumpRegisters(CallFrame*);
- bool isCallBytecode(Opcode opcode) { return opcode == getOpcode(op_call) || opcode == getOpcode(op_construct) || opcode == getOpcode(op_call_eval); }
+ bool isCallBytecode(Opcode opcode) { return opcode == getOpcode(op_call) || opcode == getOpcode(op_construct) || opcode == getOpcode(op_call_eval) || opcode == getOpcode(op_tail_call); }
void enableSampler();
int m_sampleEntryDepth;
- OwnPtr<SamplingTool> m_sampler;
+ std::unique_ptr<SamplingTool> m_sampler;
+ VM& m_vm;
JSStack m_stack;
int m_errorHandlingModeReentry;
-#if ENABLE(COMPUTED_GOTO_OPCODES) && ENABLE(LLINT)
+#if ENABLE(COMPUTED_GOTO_OPCODES)
Opcode* m_opcodeTable; // Maps OpcodeID => Opcode for compiling
HashMap<Opcode, OpcodeID> m_opcodeIDTable; // Maps Opcode => OpcodeID for decompiling
#endif
@@ -264,15 +272,30 @@ namespace JSC {
#endif
};
- // This value must not be an object that would require this conversion (WebCore's global object).
- inline bool isValidThisObject(JSValue thisValue, ExecState* exec)
+ JSValue eval(CallFrame*);
+
+ inline CallFrame* calleeFrameForVarargs(CallFrame* callFrame, unsigned numUsedStackSlots, unsigned argumentCountIncludingThis)
{
- return !thisValue.isObject() || thisValue.toThisObject(exec) == thisValue;
+ // We want the new frame to be allocated on a stack aligned offset with a stack
+ // aligned size. Align the size here.
+ argumentCountIncludingThis = WTF::roundUpToMultipleOf(
+ stackAlignmentRegisters(),
+ argumentCountIncludingThis + JSStack::CallFrameHeaderSize) - JSStack::CallFrameHeaderSize;
+
+ // Align the frame offset here.
+ unsigned paddedCalleeFrameOffset = WTF::roundUpToMultipleOf(
+ stackAlignmentRegisters(),
+ numUsedStackSlots + argumentCountIncludingThis + JSStack::CallFrameHeaderSize);
+ return CallFrame::create(callFrame->registers() - paddedCalleeFrameOffset);
}
- JSValue eval(CallFrame*);
- CallFrame* loadVarargs(CallFrame*, JSStack*, JSValue thisValue, JSValue arguments, int firstFreeRegister);
-
+ unsigned sizeOfVarargs(CallFrame* exec, JSValue arguments, uint32_t firstVarArgOffset);
+ static const unsigned maxArguments = 0x10000;
+ unsigned sizeFrameForVarargs(CallFrame* exec, JSStack*, JSValue arguments, unsigned numUsedStackSlots, uint32_t firstVarArgOffset);
+ void loadVarargs(CallFrame* execCaller, VirtualRegister firstElementDest, JSValue source, uint32_t offset, uint32_t length);
+ void setupVarargsFrame(CallFrame* execCaller, CallFrame* execCallee, JSValue arguments, uint32_t firstVarArgOffset, uint32_t length);
+ void setupVarargsFrameAndSetThis(CallFrame* execCaller, CallFrame* execCallee, JSValue thisValue, JSValue arguments, uint32_t firstVarArgOffset, uint32_t length);
+
} // namespace JSC
#endif // Interpreter_h