Commit afeead10 authored by mark.lam@apple.com's avatar mark.lam@apple.com

Make the C Loop LLINT work with callToJavaScript.

https://bugs.webkit.org/show_bug.cgi?id=125294.

Reviewed by Michael Saboff.

1. Changed the C Loop LLINT to dispatch to an Executable via its JITCode
   instance which is consistent with how the ASM LLINT works.
2. Changed CLoop::execute() to take an Opcode instead of an OpcodeID.
   This makes it play nice with the use of JITCode for dispatching.
3. Introduce a callToJavaScript and callToNativeFunction for the C Loop
   LLINT. These will call JSStack::pushFrame() and popFrame() to setup
   and teardown the CallFrame.
4. Also introduced a C Loop returnFromJavaScript which is just a
   replacement for ctiOpThrowNotCaught which had the same function.
5. Remove a lot of #if ENABLE(LLINT_C_LOOP) code now that the dispatch
   mechanism is consistent.

This patch has been tested with both configurations of COMPUTED_GOTOs
on and off.

* interpreter/CachedCall.h:
(JSC::CachedCall::CachedCall):
(JSC::CachedCall::call):
(JSC::CachedCall::setArgument):
* interpreter/CallFrameClosure.h:
(JSC::CallFrameClosure::setThis):
(JSC::CallFrameClosure::setArgument):
(JSC::CallFrameClosure::resetCallFrame):
* interpreter/Interpreter.cpp:
(JSC::Interpreter::execute):
(JSC::Interpreter::executeCall):
(JSC::Interpreter::executeConstruct):
(JSC::Interpreter::prepareForRepeatCall):
* interpreter/Interpreter.h:
* interpreter/JSStack.h:
* interpreter/JSStackInlines.h:
(JSC::JSStack::pushFrame):
* interpreter/ProtoCallFrame.h:
(JSC::ProtoCallFrame::scope):
(JSC::ProtoCallFrame::callee):
(JSC::ProtoCallFrame::thisValue):
(JSC::ProtoCallFrame::argument):
(JSC::ProtoCallFrame::setArgument):
* jit/JITCode.cpp:
(JSC::JITCode::execute):
* jit/JITCode.h:
* jit/JITExceptions.cpp:
(JSC::genericUnwind):
* llint/LLIntCLoop.cpp:
(JSC::LLInt::CLoop::initialize):
* llint/LLIntCLoop.h:
* llint/LLIntEntrypoint.cpp:
(JSC::LLInt::setFunctionEntrypoint):
(JSC::LLInt::setEvalEntrypoint):
(JSC::LLInt::setProgramEntrypoint):
- Inverted the check for vm.canUseJIT(). This allows the JIT case to be
  #if'd out nicely when building the C Loop LLINT.
* llint/LLIntOpcode.h:
* llint/LLIntThunks.cpp:
(JSC::doCallToJavaScript):
(JSC::executeJS):
(JSC::callToJavaScript):
(JSC::executeNative):
(JSC::callToNativeFunction):
* llint/LLIntThunks.h:
* llint/LowLevelInterpreter.cpp:
(JSC::CLoop::execute):
* runtime/Executable.h:
(JSC::ExecutableBase::offsetOfNumParametersFor):
(JSC::ExecutableBase::hostCodeEntryFor):
(JSC::ExecutableBase::jsCodeEntryFor):
(JSC::ExecutableBase::jsCodeWithArityCheckEntryFor):
(JSC::NativeExecutable::create):
(JSC::NativeExecutable::finishCreation):
(JSC::ProgramExecutable::generatedJITCode):
* runtime/JSArray.cpp:
(JSC::AVLTreeAbstractorForArrayCompare::compare_key_key):
* runtime/StringPrototype.cpp:
(JSC::replaceUsingRegExpSearch):
* runtime/VM.cpp:
(JSC::VM::getHostFunction):



git-svn-id: http://svn.webkit.org/repository/webkit/trunk@160186 268f45cc-cd09-0410-ab3c-d52691b4dbfc
parent d882a076
2013-12-05 Mark Lam <mark.lam@apple.com>
Make the C Loop LLINT work with callToJavaScript.
https://bugs.webkit.org/show_bug.cgi?id=125294.
Reviewed by Michael Saboff.
1. Changed the C Loop LLINT to dispatch to an Executable via its JITCode
instance which is consistent with how the ASM LLINT works.
2. Changed CLoop::execute() to take an Opcode instead of an OpcodeID.
This makes it play nice with the use of JITCode for dispatching.
3. Introduce a callToJavaScript and callToNativeFunction for the C Loop
LLINT. These will call JSStack::pushFrame() and popFrame() to setup
and teardown the CallFrame.
4. Also introduced a C Loop returnFromJavaScript which is just a
replacement for ctiOpThrowNotCaught which had the same function.
5. Remove a lot of #if ENABLE(LLINT_C_LOOP) code now that the dispatch
mechanism is consistent.
This patch has been tested with both configurations of COMPUTED_GOTOs
on and off.
* interpreter/CachedCall.h:
(JSC::CachedCall::CachedCall):
(JSC::CachedCall::call):
(JSC::CachedCall::setArgument):
* interpreter/CallFrameClosure.h:
(JSC::CallFrameClosure::setThis):
(JSC::CallFrameClosure::setArgument):
(JSC::CallFrameClosure::resetCallFrame):
* interpreter/Interpreter.cpp:
(JSC::Interpreter::execute):
(JSC::Interpreter::executeCall):
(JSC::Interpreter::executeConstruct):
(JSC::Interpreter::prepareForRepeatCall):
* interpreter/Interpreter.h:
* interpreter/JSStack.h:
* interpreter/JSStackInlines.h:
(JSC::JSStack::pushFrame):
* interpreter/ProtoCallFrame.h:
(JSC::ProtoCallFrame::scope):
(JSC::ProtoCallFrame::callee):
(JSC::ProtoCallFrame::thisValue):
(JSC::ProtoCallFrame::argument):
(JSC::ProtoCallFrame::setArgument):
* jit/JITCode.cpp:
(JSC::JITCode::execute):
* jit/JITCode.h:
* jit/JITExceptions.cpp:
(JSC::genericUnwind):
* llint/LLIntCLoop.cpp:
(JSC::LLInt::CLoop::initialize):
* llint/LLIntCLoop.h:
* llint/LLIntEntrypoint.cpp:
(JSC::LLInt::setFunctionEntrypoint):
(JSC::LLInt::setEvalEntrypoint):
(JSC::LLInt::setProgramEntrypoint):
- Inverted the check for vm.canUseJIT(). This allows the JIT case to be
#if'd out nicely when building the C Loop LLINT.
* llint/LLIntOpcode.h:
* llint/LLIntThunks.cpp:
(JSC::doCallToJavaScript):
(JSC::executeJS):
(JSC::callToJavaScript):
(JSC::executeNative):
(JSC::callToNativeFunction):
* llint/LLIntThunks.h:
* llint/LowLevelInterpreter.cpp:
(JSC::CLoop::execute):
* runtime/Executable.h:
(JSC::ExecutableBase::offsetOfNumParametersFor):
(JSC::ExecutableBase::hostCodeEntryFor):
(JSC::ExecutableBase::jsCodeEntryFor):
(JSC::ExecutableBase::jsCodeWithArityCheckEntryFor):
(JSC::NativeExecutable::create):
(JSC::NativeExecutable::finishCreation):
(JSC::ProgramExecutable::generatedJITCode):
* runtime/JSArray.cpp:
(JSC::AVLTreeAbstractorForArrayCompare::compare_key_key):
* runtime/StringPrototype.cpp:
(JSC::replaceUsingRegExpSearch):
* runtime/VM.cpp:
(JSC::VM::getHostFunction):
2013-12-05 Laszlo Vidacs <lac@inf.u-szeged.hu>
Fix JavaScriptCore build if cloop is enabled after r160094
......
/*
* Copyright (C) 2009 Apple Inc. All rights reserved.
* Copyright (C) 2009, 2013 Apple Inc. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
......@@ -45,12 +45,8 @@ namespace JSC {
{
ASSERT(!function->isHostFunction());
if (callFrame->vm().isSafeToRecurse()) {
#if !ENABLE(LLINT_C_LOOP)
m_arguments.resize(argumentCount);
m_closure = m_interpreter->prepareForRepeatCall(function->jsExecutable(), callFrame, &m_protoCallFrame, function, argumentCount + 1, function->scope(), m_arguments.data());
#else
m_closure = m_interpreter->prepareForRepeatCall(function->jsExecutable(), callFrame, function, argumentCount + 1, function->scope());
#endif
} else
throwStackOverflowError(callFrame);
m_valid = !callFrame->hadException();
......@@ -61,35 +57,15 @@ namespace JSC {
ASSERT(m_valid);
return m_interpreter->execute(m_closure);
}
#if !ENABLE(LLINT_C_LOOP)
void setThis(JSValue v) { m_protoCallFrame.setThisValue(v); }
void setArgument(int n, JSValue v) { m_protoCallFrame.setArgument(n, v); }
#else
void setThis(JSValue v) { m_closure.setThis(v); }
void setArgument(int n, JSValue v) { m_closure.setArgument(n, v); }
CallFrame* newCallFrame(ExecState* exec)
{
CallFrame* callFrame = m_closure.newCallFrame;
callFrame->setScope(exec->scope());
return callFrame;
}
~CachedCall()
{
if (m_valid)
m_interpreter->endRepeatCall(m_closure);
}
#endif
private:
bool m_valid;
Interpreter* m_interpreter;
VMEntryScope m_entryScope;
#if !ENABLE(LLINT_C_LOOP)
ProtoCallFrame m_protoCallFrame;
Vector<JSValue> m_arguments;
#endif
CallFrameClosure m_closure;
};
}
......
/*
* Copyright (C) 2009 Apple Inc. All rights reserved.
* Copyright (C) 2009, 2013 Apple Inc. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
......@@ -32,11 +32,7 @@ namespace JSC {
struct CallFrameClosure {
CallFrame* oldCallFrame;
#if ENABLE(LLINT_C_LOOP)
CallFrame* newCallFrame;
#else
ProtoCallFrame* newCallFrame;
#endif
ProtoCallFrame* protoCallFrame;
JSFunction* function;
FunctionExecutable* functionExecutable;
VM* vm;
......@@ -46,25 +42,17 @@ struct CallFrameClosure {
void setThis(JSValue value)
{
newCallFrame->setThisValue(value);
protoCallFrame->setThisValue(value);
}
void setArgument(int argument, JSValue value)
{
newCallFrame->setArgument(argument, value);
protoCallFrame->setArgument(argument, value);
}
void resetCallFrame()
{
newCallFrame->setScope(scope);
#if ENABLE(LLINT_C_LOOP)
// setArgument() takes an arg index that starts from 0 for the first
// argument after the 'this' value. Since both argumentCountIncludingThis
// and parameterCountIncludingThis includes the 'this' value, we need to
// subtract 1 from them to make it a valid argument index for setArgument().
for (int i = argumentCountIncludingThis-1; i < parameterCountIncludingThis-1; ++i)
newCallFrame->setArgument(i, jsUndefined());
#endif
protoCallFrame->setScope(scope);
}
};
......
......@@ -257,12 +257,8 @@ namespace JSC {
private:
enum ExecutionFlag { Normal, InitializeAndReturn };
#if !ENABLE(LLINT_C_LOOP)
CallFrameClosure prepareForRepeatCall(FunctionExecutable*, CallFrame*, ProtoCallFrame*, JSFunction*, int argumentCountIncludingThis, JSScope*, JSValue*);
#else
CallFrameClosure prepareForRepeatCall(FunctionExecutable*, CallFrame*, JSFunction*, int argumentCountIncludingThis, JSScope*);
void endRepeatCall(CallFrameClosure&);
#endif
JSValue execute(CallFrameClosure&);
void getStackTrace(Vector<StackFrame>& results, size_t maxStackSize = std::numeric_limits<size_t>::max());
......
......@@ -102,8 +102,7 @@ namespace JSC {
bool entryCheck(class CodeBlock*, int);
CallFrame* pushFrame(CallFrame* callerFrame, class CodeBlock*,
JSScope*, int argsCount, JSObject* callee);
CallFrame* pushFrame(class CodeBlock*, JSScope*, int argsCount, JSObject* callee);
void popFrame(CallFrame*);
......
......@@ -80,8 +80,7 @@ inline bool JSStack::entryCheck(class CodeBlock* codeBlock, int argsCount)
return true;
}
inline CallFrame* JSStack::pushFrame(CallFrame* callerFrame,
class CodeBlock* codeBlock, JSScope* scope, int argsCount, JSObject* callee)
inline CallFrame* JSStack::pushFrame(class CodeBlock* codeBlock, JSScope* scope, int argsCount, JSObject* callee)
{
ASSERT(!!scope);
Register* oldEnd = getTopOfStack();
......@@ -119,7 +118,7 @@ inline CallFrame* JSStack::pushFrame(CallFrame* callerFrame,
// The caller frame should always be the real previous frame on the stack,
// and not a potential GlobalExec that was passed in. Point callerFrame to
// the top frame on the stack.
callerFrame = m_topCallFrame;
CallFrame* callerFrame = m_topCallFrame;
// Initialize the VM sentinel frame header:
newVMEntrySentinelFrame->initializeVMEntrySentinelFrame(callerFrame);
......
......@@ -40,21 +40,35 @@ struct ProtoCallFrame {
JSValue *args;
void init(CodeBlock*, JSScope*, JSObject*, JSValue, int, JSValue* otherArgs = 0);
CodeBlock* codeBlock() const { return codeBlockValue.Register::codeBlock(); }
void setCodeBlock(CodeBlock* codeBlock) { codeBlockValue = codeBlock; }
JSScope* scope() const { return scopeChainValue.Register::scope(); }
void setScope(JSScope* scope) { scopeChainValue = scope; }
JSObject* callee() const { return calleeValue.Register::function(); }
void setCallee(JSObject* callee) { calleeValue = Register::withCallee(callee); }
int argumentCountIncludingThis() const { return argCountAndCodeOriginValue.payload(); }
int argumentCount() const { return argumentCountIncludingThis() - 1; }
void setArgumentCountIncludingThis(int count) { argCountAndCodeOriginValue.payload() = count; }
void setPaddedArgsCount(size_t argCount) { paddedArgCount = argCount; }
void clearCurrentVPC() { argCountAndCodeOriginValue.tag() = 0; }
JSValue thisValue() const { return thisArg.Register::jsValue(); }
void setThisValue(JSValue value) { thisArg = value; }
void setArgument(size_t argument, JSValue value)
JSValue argument(size_t argumentIndex)
{
ASSERT(static_cast<int>(argumentIndex) < argumentCount());
return args[argumentIndex];
}
void setArgument(size_t argumentIndex, JSValue value)
{
ASSERT(static_cast<int>(argument) < argumentCount());
args[argument] = value;
ASSERT(static_cast<int>(argumentIndex) < argumentCount());
args[argumentIndex] = value;
}
};
......
......@@ -41,7 +41,6 @@ JITCode::~JITCode()
{
}
#if ENABLE(JIT)
JSValue JITCode::execute(VM* vm, ProtoCallFrame* protoCallFrame, Register* topOfStack)
{
ASSERT(!vm->topCallFrame || ((Register*)(vm->topCallFrame) >= topOfStack));
......@@ -49,7 +48,6 @@ JSValue JITCode::execute(VM* vm, ProtoCallFrame* protoCallFrame, Register* topOf
JSValue result = JSValue::decode(callToJavaScript(executableAddress(), &vm->topCallFrame, protoCallFrame, topOfStack));
return vm->exception() ? jsNull() : result;
}
#endif
DFG::CommonData* JITCode::dfgCommon()
{
......
......@@ -47,11 +47,7 @@ class JITCode;
}
struct ProtoCallFrame;
#if ENABLE(JIT)
class VM;
class JSStack;
#endif
class JITCode : public ThreadSafeRefCounted<JITCode> {
public:
......
/*
* Copyright (C) 2012 Apple Inc. All rights reserved.
* Copyright (C) 2012, 2013 Apple Inc. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
......@@ -39,8 +39,6 @@
#include "Operations.h"
#include "VM.h"
#if ENABLE(JIT) || ENABLE(LLINT)
namespace JSC {
void genericUnwind(VM* vm, ExecState* callFrame, JSValue exceptionValue)
......@@ -52,14 +50,13 @@ void genericUnwind(VM* vm, ExecState* callFrame, JSValue exceptionValue)
Instruction* catchPCForInterpreter = 0;
if (handler) {
catchPCForInterpreter = &callFrame->codeBlock()->instructions()[handler->target];
catchRoutine = ExecutableBase::catchRoutineFor(handler, catchPCForInterpreter);
} else {
#if ENABLE(LLINT_C_LOOP)
catchRoutine = LLInt::getCodePtr(ctiOpThrowNotCaught);
#if ENABLE(JIT)
catchRoutine = handler->nativeCode.executableAddress();
#else
catchRoutine = FunctionPtr(LLInt::getCodePtr(returnFromJavaScript)).value();
catchRoutine = catchPCForInterpreter->u.pointer;
#endif
}
} else
catchRoutine = LLInt::getCodePtr(returnFromJavaScript);
vm->callFrameForThrow = callFrame;
vm->targetMachinePCForThrow = catchRoutine;
......@@ -68,6 +65,4 @@ void genericUnwind(VM* vm, ExecState* callFrame, JSValue exceptionValue)
RELEASE_ASSERT(catchRoutine);
}
}
#endif
} // namespace JSC
/*
* Copyright (C) 2011, 2012 Apple Inc. All rights reserved.
* Copyright (C) 2012, 2013 Apple Inc. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
......@@ -26,51 +26,19 @@
#include "config.h"
#include "LLIntCLoop.h"
#include "Instruction.h"
#if ENABLE(LLINT_C_LOOP)
namespace JSC {
#include "LLIntData.h"
namespace JSC {
namespace LLInt {
#if ENABLE(LLINT_C_LOOP)
void CLoop::initialize()
{
execute(0, llint_unused, true);
execute(0, getOpcode(llint_unused), true);
}
void* CLoop::catchRoutineFor(Instruction* catchPCForInterpreter)
{
return reinterpret_cast<Instruction*>(catchPCForInterpreter->u.opcode);
}
MacroAssemblerCodePtr CLoop::hostCodeEntryFor(CodeSpecializationKind kind)
{
MacroAssemblerCodePtr codePtr;
codePtr = (kind == CodeForCall) ?
MacroAssemblerCodePtr::createLLIntCodePtr(llint_native_call_trampoline) :
MacroAssemblerCodePtr::createLLIntCodePtr(llint_native_construct_trampoline);
return codePtr;
}
MacroAssemblerCodePtr CLoop::jsCodeEntryWithArityCheckFor(CodeSpecializationKind kind)
{
MacroAssemblerCodePtr codePtr;
codePtr = (kind == CodeForCall) ?
MacroAssemblerCodePtr::createLLIntCodePtr(llint_function_for_call_arity_check) :
MacroAssemblerCodePtr::createLLIntCodePtr(llint_function_for_construct_arity_check);
return codePtr;
}
MacroAssemblerCodePtr CLoop::jsCodeEntryFor(CodeSpecializationKind kind)
{
MacroAssemblerCodePtr codePtr;
codePtr = (kind == CodeForCall) ?
MacroAssemblerCodePtr::createLLIntCodePtr(llint_function_for_call_prologue) :
MacroAssemblerCodePtr::createLLIntCodePtr(llint_function_for_construct_prologue);
return codePtr;
}
} // namespace LLInt
} // namespace JSC
#endif // ENABLE(LLINT_C_LOOP)
} } // namespace JSC::LLInt
/*
* Copyright (C) 2011, 2012 Apple Inc. All rights reserved.
* Copyright (C) 2012, 2013 Apple Inc. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
......@@ -28,14 +28,11 @@
#if ENABLE(LLINT_C_LOOP)
#include "CodeSpecializationKind.h"
#include "CallFrame.h"
#include "JSCJSValue.h"
#include "MacroAssemblerCodeRef.h"
#include "Opcode.h"
#include "Register.h"
namespace JSC {
namespace LLInt {
const OpcodeID llint_unused = llint_end;
......@@ -43,17 +40,13 @@ const OpcodeID llint_unused = llint_end;
class CLoop {
public:
static void initialize();
static JSValue execute(CallFrame*, OpcodeID bootstrapOpcodeId, bool isInitializationPass = false);
static void* catchRoutineFor(Instruction* catchPCForInterpreter);
static MacroAssemblerCodePtr hostCodeEntryFor(CodeSpecializationKind);
static MacroAssemblerCodePtr jsCodeEntryWithArityCheckFor(CodeSpecializationKind);
static MacroAssemblerCodePtr jsCodeEntryFor(CodeSpecializationKind);
static JSValue execute(CallFrame*, Opcode entryOpcode, bool isInitializationPass = false);
};
} } // namespace JSC::LLInt
using JSC::LLInt::CLoop;
#endif // ENABLE(LLINT_C_LOOP)
#endif // LLIntCLoop_h
......@@ -35,71 +35,73 @@
#include "LowLevelInterpreter.h"
#include "VM.h"
namespace JSC { namespace LLInt {
static void setFunctionEntrypoint(VM& vm, CodeBlock* codeBlock)
{
CodeSpecializationKind kind = codeBlock->specializationKind();
if (!vm.canUseJIT()) {
#if ENABLE(JIT)
if (vm.canUseJIT()) {
if (kind == CodeForCall) {
codeBlock->setJITCode(
adoptRef(new DirectJITCode(MacroAssemblerCodeRef::createLLIntCodeRef(llint_function_for_call_prologue), JITCode::InterpreterThunk)),
MacroAssemblerCodePtr::createLLIntCodePtr(llint_function_for_call_arity_check));
adoptRef(new DirectJITCode(vm.getCTIStub(functionForCallEntryThunkGenerator), JITCode::InterpreterThunk)),
vm.getCTIStub(functionForCallArityCheckThunkGenerator).code());
return;
}
ASSERT(kind == CodeForConstruct);
codeBlock->setJITCode(
adoptRef(new DirectJITCode(MacroAssemblerCodeRef::createLLIntCodeRef(llint_function_for_construct_prologue), JITCode::InterpreterThunk)),
MacroAssemblerCodePtr::createLLIntCodePtr(llint_function_for_construct_arity_check));
adoptRef(new DirectJITCode(vm.getCTIStub(functionForConstructEntryThunkGenerator), JITCode::InterpreterThunk)),
vm.getCTIStub(functionForConstructArityCheckThunkGenerator).code());
return;
}
#if ENABLE(JIT)
#endif // ENABLE(JIT)
UNUSED_PARAM(vm);
if (kind == CodeForCall) {
codeBlock->setJITCode(
adoptRef(new DirectJITCode(vm.getCTIStub(functionForCallEntryThunkGenerator), JITCode::InterpreterThunk)),
vm.getCTIStub(functionForCallArityCheckThunkGenerator).code());
adoptRef(new DirectJITCode(MacroAssemblerCodeRef::createLLIntCodeRef(llint_function_for_call_prologue), JITCode::InterpreterThunk)),
MacroAssemblerCodePtr::createLLIntCodePtr(llint_function_for_call_arity_check));
return;
}
ASSERT(kind == CodeForConstruct);
codeBlock->setJITCode(
adoptRef(new DirectJITCode(vm.getCTIStub(functionForConstructEntryThunkGenerator), JITCode::InterpreterThunk)),
vm.getCTIStub(functionForConstructArityCheckThunkGenerator).code());
#endif // ENABLE(JIT)
adoptRef(new DirectJITCode(MacroAssemblerCodeRef::createLLIntCodeRef(llint_function_for_construct_prologue), JITCode::InterpreterThunk)),
MacroAssemblerCodePtr::createLLIntCodePtr(llint_function_for_construct_arity_check));
}
static void setEvalEntrypoint(VM& vm, CodeBlock* codeBlock)
{
if (!vm.canUseJIT()) {
#if ENABLE(JIT)
if (vm.canUseJIT()) {
codeBlock->setJITCode(
adoptRef(new DirectJITCode(MacroAssemblerCodeRef::createLLIntCodeRef(llint_eval_prologue), JITCode::InterpreterThunk)),
adoptRef(new DirectJITCode(vm.getCTIStub(evalEntryThunkGenerator), JITCode::InterpreterThunk)),
MacroAssemblerCodePtr());
return;
}
#if ENABLE(JIT)
#endif // ENABLE(JIT)
UNUSED_PARAM(vm);
codeBlock->setJITCode(
adoptRef(new DirectJITCode(vm.getCTIStub(evalEntryThunkGenerator), JITCode::InterpreterThunk)),
adoptRef(new DirectJITCode(MacroAssemblerCodeRef::createLLIntCodeRef(llint_eval_prologue), JITCode::InterpreterThunk)),
MacroAssemblerCodePtr());
#endif
}
static void setProgramEntrypoint(VM& vm, CodeBlock* codeBlock)
{
if (!vm.canUseJIT()) {
#if ENABLE(JIT)
if (vm.canUseJIT()) {
codeBlock->setJITCode(
adoptRef(new DirectJITCode(MacroAssemblerCodeRef::createLLIntCodeRef(llint_program_prologue), JITCode::InterpreterThunk)),
adoptRef(new DirectJITCode(vm.getCTIStub(programEntryThunkGenerator), JITCode::InterpreterThunk)),
MacroAssemblerCodePtr());
return;
}
#if ENABLE(JIT)
#endif // ENABLE(JIT)
UNUSED_PARAM(vm);
codeBlock->setJITCode(
adoptRef(new DirectJITCode(vm.getCTIStub(programEntryThunkGenerator), JITCode::InterpreterThunk)),
adoptRef(new DirectJITCode(MacroAssemblerCodeRef::createLLIntCodeRef(llint_program_prologue), JITCode::InterpreterThunk)),
MacroAssemblerCodePtr());
#endif
}
void setEntrypoint(VM& vm, CodeBlock* codeBlock)
......
/*
* Copyright (C) 2012 Apple Inc. All rights reserved.
* Copyright (C) 2012, 2013 Apple Inc. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
......@@ -34,7 +34,7 @@
#define FOR_EACH_LLINT_NOJIT_NATIVE_HELPER(macro) \
macro(getHostCallReturnValue, 1) \
macro(ctiOpThrowNotCaught, 1)
macro(returnFromJavaScript, 1)
#else // !ENABLE(LLINT_C_LOOP)
......
/*
* Copyright (C) 2012 Apple Inc. All rights reserved.
* Copyright (C) 2012, 2013 Apple Inc. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
......@@ -26,15 +26,24 @@
#include "config.h"
#include "LLIntThunks.h"
#if ENABLE(LLINT) && ENABLE(JIT)
#include "CallData.h"
#include "ExceptionHelpers.h"
#include "Interpreter.h"
#include "JSInterfaceJIT.h"
#include "JSObject.h"
#include "JSStackInlines.h"
#include "LLIntCLoop.h"
#include "LinkBuffer.h"
#include "LowLevelInterpreter.h"
#include "ProtoCallFrame.h"
#include "VM.h"
namespace JSC {
#if ENABLE(JIT)
#if ENABLE(LLINT)
namespace JSC { namespace LLInt {
namespace LLInt {
static MacroAssemblerCodeRef generateThunkWithJumpTo(VM* vm, void (*target)(), const char *thunkKind)
{
......@@ -78,6 +87,67 @@ MacroAssemblerCodeRef programEntryThunkGenerator(VM* vm)
return generateThunkWithJumpTo(vm, llint_program_prologue, "program");
}
} } // namespace JSC::LLInt
} // namespace LLInt
#endif // ENABLE(LLINT)
#else // ENABLE(JIT)
// Non-JIT (i.e. C Loop LLINT) case:
typedef JSValue (*ExecuteCode) (CallFrame*, void* executableAddress);
template<ExecuteCode execute>
EncodedJSValue doCallToJavaScript(void* executableAddress, ProtoCallFrame* protoCallFrame)
{
CodeBlock* codeBlock = protoCallFrame->codeBlock();
JSScope* scope = protoCallFrame->scope();
JSObject* callee = protoCallFrame->callee();
int argCountIncludingThis = protoCallFrame->argumentCountIncludingThis();
int argCount = protoCallFrame->argumentCount();
JSValue thisValue = protoCallFrame->thisValue();
JSStack& stack = scope->vm()->interpreter->stack();
CallFrame* newCallFrame = stack.pushFrame(codeBlock, scope, argCountIncludingThis, callee);
if (UNLIKELY(!newCallFrame)) {
JSGlobalObject* globalObject = scope->globalObject();
ExecState* exec = globalObject->globalExec();
return JSValue::encode(throwStackOverflowError(exec));
}
// Set the arguments for the callee:
newCallFrame->setThisValue(thisValue);
for (int i = 0; i < argCount; ++i)
newCallFrame->setArgument(i, protoCallFrame->argument(i));
JSValue result = execute(newCallFrame, executableAddress);
stack.popFrame(newCallFrame);
return JSValue::encode(result);
}
static inline JSValue executeJS(CallFrame* newCallFrame, void* executableAddress)
{
Opcode entryOpcode = *reinterpret_cast<Opcode*>(&executableAddress);
return CLoop::execute(newCallFrame, entryOpcode);
}
EncodedJSValue callToJavaScript(void* executableAddress, ExecState**, ProtoCallFrame* protoCallFrame, Register*)
{
return doCallToJavaScript<executeJS>(executableAddress, protoCallFrame);
}
static inline JSValue executeNative(CallFrame* newCallFrame, void* executableAddress)
{
NativeFunction function = reinterpret_cast<NativeFunction>(executableAddress);
return JSValue::decode(function(newCallFrame));
}