Refactor LLInt and supporting code in preparation for the C Loop backend.

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

Patch by Mark Lam <mark.lam@apple.com> on 2012-08-31
Reviewed by Filip Pizlo.

* bytecode/GetByIdStatus.cpp:
(JSC::GetByIdStatus::computeFromLLInt):
* bytecode/PutByIdStatus.cpp:
(JSC::PutByIdStatus::computeFromLLInt):
* jit/JITExceptions.cpp:
(JSC::genericThrow): Use ExecutableBase::catchRoutineFor() to fetch
    fetch the catch routine for a thrown exception.  This will allow
    us to redefine that for the C loop later, and still keep this
    code readable.
* llint/LLIntOfflineAsmConfig.h: Moved ASM macros to
    LowLevelInterpreter.cpp which is the only place they are used. This
    will make it more convenient to redefine them for the C loop later.
* llint/LLIntSlowPaths.cpp:
(JSC::LLInt::setUpCall): Use ExecutableBase's hostCodeEntry()
    jsCodeEntryFor(), and jsCodeWithArityCheckEntryFor() for computing
    the entry points to functions being called.
* llint/LLIntSlowPaths.h:
(SlowPathReturnType):
(JSC::LLInt::encodeResult):
(LLInt):
(JSC::LLInt::decodeResult): Added.  Needed by LLInt C Loop later.
* llint/LowLevelInterpreter.asm:
* llint/LowLevelInterpreter.cpp:
* llint/LowLevelInterpreter32_64.asm:
* llint/LowLevelInterpreter64.asm:
* offlineasm/asm.rb: Disambiguate between opcodes and other labels.
* offlineasm/config.rb:
* runtime/Executable.h:
(JSC::ExecutableBase::hostCodeEntryFor): Added.
(ExecutableBase):
(JSC::ExecutableBase::jsCodeEntryFor): Added.
(JSC::ExecutableBase::jsCodeWithArityCheckEntryFor): Added.
(JSC::ExecutableBase::catchRoutineFor): Added.
* runtime/JSValueInlineMethods.h:
(JSC):

git-svn-id: http://svn.webkit.org/repository/webkit/trunk@127333 268f45cc-cd09-0410-ab3c-d52691b4dbfc
parent f007554b
2012-08-31 Mark Lam <mark.lam@apple.com>
Refactor LLInt and supporting code in preparation for the C Loop backend.
https://bugs.webkit.org/show_bug.cgi?id=95531.
Reviewed by Filip Pizlo.
* bytecode/GetByIdStatus.cpp:
(JSC::GetByIdStatus::computeFromLLInt):
* bytecode/PutByIdStatus.cpp:
(JSC::PutByIdStatus::computeFromLLInt):
* jit/JITExceptions.cpp:
(JSC::genericThrow): Use ExecutableBase::catchRoutineFor() to fetch
fetch the catch routine for a thrown exception. This will allow
us to redefine that for the C loop later, and still keep this
code readable.
* llint/LLIntOfflineAsmConfig.h: Moved ASM macros to
LowLevelInterpreter.cpp which is the only place they are used. This
will make it more convenient to redefine them for the C loop later.
* llint/LLIntSlowPaths.cpp:
(JSC::LLInt::setUpCall): Use ExecutableBase's hostCodeEntry()
jsCodeEntryFor(), and jsCodeWithArityCheckEntryFor() for computing
the entry points to functions being called.
* llint/LLIntSlowPaths.h:
(SlowPathReturnType):
(JSC::LLInt::encodeResult):
(LLInt):
(JSC::LLInt::decodeResult): Added. Needed by LLInt C Loop later.
* llint/LowLevelInterpreter.asm:
* llint/LowLevelInterpreter.cpp:
* llint/LowLevelInterpreter32_64.asm:
* llint/LowLevelInterpreter64.asm:
* offlineasm/asm.rb: Disambiguate between opcodes and other labels.
* offlineasm/config.rb:
* runtime/Executable.h:
(JSC::ExecutableBase::hostCodeEntryFor): Added.
(ExecutableBase):
(JSC::ExecutableBase::jsCodeEntryFor): Added.
(JSC::ExecutableBase::jsCodeWithArityCheckEntryFor): Added.
(JSC::ExecutableBase::catchRoutineFor): Added.
* runtime/JSValueInlineMethods.h:
(JSC):
2012-08-31 Tony Chang <tony@chromium.org>
Remove ENABLE_CSS3_FLEXBOX compile time flag
......
......@@ -28,6 +28,7 @@
#include "CodeBlock.h"
#include "JSScope.h"
#include "LLIntData.h"
#include "LowLevelInterpreter.h"
namespace JSC {
......@@ -40,7 +41,7 @@ GetByIdStatus GetByIdStatus::computeFromLLInt(CodeBlock* profiledBlock, unsigned
#if ENABLE(LLINT)
Instruction* instruction = profiledBlock->instructions().begin() + bytecodeIndex;
if (instruction[0].u.opcode == llint_op_method_check)
if (instruction[0].u.opcode == LLInt::getOpcode(llint_op_method_check))
instruction++;
Structure* structure = instruction[4].u.structure.get();
......
......@@ -27,6 +27,7 @@
#include "PutByIdStatus.h"
#include "CodeBlock.h"
#include "LLIntData.h"
#include "LowLevelInterpreter.h"
#include "Structure.h"
#include "StructureChain.h"
......@@ -45,8 +46,8 @@ PutByIdStatus PutByIdStatus::computeFromLLInt(CodeBlock* profiledBlock, unsigned
if (!structure)
return PutByIdStatus(NoInformation, 0, 0, 0, invalidOffset);
if (instruction[0].u.opcode == llint_op_put_by_id
|| instruction[0].u.opcode == llint_op_put_by_id_out_of_line) {
if (instruction[0].u.opcode == LLInt::getOpcode(llint_op_put_by_id)
|| instruction[0].u.opcode == LLInt::getOpcode(llint_op_put_by_id_out_of_line)) {
PropertyOffset offset = structure->get(*profiledBlock->globalData(), ident);
if (!isValidOffset(offset))
return PutByIdStatus(NoInformation, 0, 0, 0, invalidOffset);
......@@ -56,10 +57,10 @@ PutByIdStatus PutByIdStatus::computeFromLLInt(CodeBlock* profiledBlock, unsigned
ASSERT(structure->transitionWatchpointSetHasBeenInvalidated());
ASSERT(instruction[0].u.opcode == llint_op_put_by_id_transition_direct
|| instruction[0].u.opcode == llint_op_put_by_id_transition_normal
|| instruction[0].u.opcode == llint_op_put_by_id_transition_direct_out_of_line
|| instruction[0].u.opcode == llint_op_put_by_id_transition_normal_out_of_line);
ASSERT(instruction[0].u.opcode == LLInt::getOpcode(llint_op_put_by_id_transition_direct)
|| instruction[0].u.opcode == LLInt::getOpcode(llint_op_put_by_id_transition_normal)
|| instruction[0].u.opcode == LLInt::getOpcode(llint_op_put_by_id_transition_direct_out_of_line)
|| instruction[0].u.opcode == LLInt::getOpcode(llint_op_put_by_id_transition_normal_out_of_line));
Structure* newStructure = instruction[6].u.structure.get();
StructureChain* chain = instruction[7].u.structureChain.get();
......
......@@ -47,8 +47,8 @@ ExceptionHandler genericThrow(JSGlobalData* globalData, ExecState* callFrame, JS
void* catchRoutine;
Instruction* catchPCForInterpreter = 0;
if (handler) {
catchRoutine = handler->nativeCode.executableAddress();
catchPCForInterpreter = &callFrame->codeBlock()->instructions()[handler->target];
catchRoutine = ExecutableBase::catchRoutineFor(handler, catchPCForInterpreter);
} else
catchRoutine = FunctionPtr(LLInt::getCodePtr(ctiOpThrowNotCaught)).value();
......
......@@ -91,24 +91,4 @@
#define OFFLINE_ASM_VALUE_PROFILER 0
#endif
// These are for building an interpreter from generated assembly code:
#define OFFLINE_ASM_BEGIN asm (
#define OFFLINE_ASM_END );
#if CPU(ARM_THUMB2)
#define OFFLINE_ASM_GLOBAL_LABEL(label) \
".globl " SYMBOL_STRING(label) "\n" \
HIDE_SYMBOL(label) "\n" \
".thumb\n" \
".thumb_func " THUMB_FUNC_PARAM(label) "\n" \
SYMBOL_STRING(label) ":\n"
#else
#define OFFLINE_ASM_GLOBAL_LABEL(label) \
".globl " SYMBOL_STRING(label) "\n" \
HIDE_SYMBOL(label) "\n" \
SYMBOL_STRING(label) ":\n"
#endif
#define OFFLINE_ASM_LOCAL_LABEL(label) LOCAL_LABEL_STRING(label) ":\n"
#endif // LLIntOfflineAsmConfig_h
......@@ -1351,7 +1351,7 @@ inline SlowPathReturnType setUpCall(ExecState* execCallee, Instruction* pc, Code
MacroAssemblerCodePtr codePtr;
CodeBlock* codeBlock = 0;
if (executable->isHostFunction())
codePtr = executable->generatedJITCodeFor(kind).addressForCall();
codePtr = executable->hostCodeEntryFor(kind);
else {
FunctionExecutable* functionExecutable = static_cast<FunctionExecutable*>(executable);
JSObject* error = functionExecutable->compileFor(execCallee, callee->scope(), kind);
......@@ -1360,9 +1360,9 @@ inline SlowPathReturnType setUpCall(ExecState* execCallee, Instruction* pc, Code
codeBlock = &functionExecutable->generatedBytecodeFor(kind);
ASSERT(codeBlock);
if (execCallee->argumentCountIncludingThis() < static_cast<size_t>(codeBlock->numParameters()))
codePtr = functionExecutable->generatedJITCodeWithArityCheckFor(kind);
codePtr = functionExecutable->jsCodeWithArityCheckEntryFor(kind);
else
codePtr = functionExecutable->generatedJITCodeFor(kind).addressForCall();
codePtr = functionExecutable->jsCodeEntryFor(kind);
}
if (callLinkInfo) {
......@@ -1375,7 +1375,7 @@ inline SlowPathReturnType setUpCall(ExecState* execCallee, Instruction* pc, Code
if (codeBlock)
codeBlock->linkIncomingCall(callLinkInfo);
}
LLINT_CALL_RETURN(execCallee, pc, codePtr.executableAddress());
}
......
......@@ -44,33 +44,50 @@ namespace LLInt {
// warnings, or worse, a change in the ABI used to return these types.
struct SlowPathReturnType {
void* a;
void* b;
ExecState* b;
};
inline SlowPathReturnType encodeResult(void* a, void* b)
inline SlowPathReturnType encodeResult(void* a, ExecState* b)
{
SlowPathReturnType result;
result.a = a;
result.b = b;
return result;
}
#else
inline void decodeResult(SlowPathReturnType result, void*& a, ExecState*& b)
{
a = result.a;
b = result.b;
}
#else // USE(JSVALUE32_64)
typedef int64_t SlowPathReturnType;
inline SlowPathReturnType encodeResult(void* a, void* b)
typedef union {
struct {
void* a;
ExecState* b;
} pair;
int64_t i;
} SlowPathReturnTypeEncoding;
inline SlowPathReturnType encodeResult(void* a, ExecState* b)
{
union {
struct {
void* a;
void* b;
} pair;
int64_t i;
} u;
SlowPathReturnTypeEncoding u;
u.pair.a = a;
u.pair.b = b;
return u.i;
}
#endif
inline void decodeResult(SlowPathReturnType result, void*& a, ExecState*& b)
{
SlowPathReturnTypeEncoding u;
u.i = result;
a = u.pair.a;
b = u.pair.b;
}
#endif // USE(JSVALUE32_64)
extern "C" SlowPathReturnType llint_trace_operand(ExecState*, Instruction*, int fromWhere, int operand);
extern "C" SlowPathReturnType llint_trace_value(ExecState*, Instruction*, int fromWhere, int operand);
......
......@@ -149,6 +149,11 @@ macro traceExecution()
end
end
macro callTargetFunction(callLinkInfo)
call LLIntCallLinkInfo::machineCodeTarget[callLinkInfo]
dispatchAfterCall()
end
macro slowPathForCall(advance, slowPath)
callCallSlowPath(
advance,
......
......@@ -31,6 +31,33 @@
#include "LLIntOfflineAsmConfig.h"
#include <wtf/InlineASM.h>
//============================================================================
// Define the opcode dispatch mechanism when using an ASM loop:
//
// These are for building an interpreter from generated assembly code:
#define OFFLINE_ASM_BEGIN asm (
#define OFFLINE_ASM_END );
#define OFFLINE_ASM_OPCODE_LABEL(__opcode) OFFLINE_ASM_GLOBAL_LABEL(llint_##__opcode)
#define OFFLINE_ASM_GLUE_LABEL(__opcode) OFFLINE_ASM_GLOBAL_LABEL(__opcode)
#if CPU(ARM_THUMB2)
#define OFFLINE_ASM_GLOBAL_LABEL(label) \
".globl " SYMBOL_STRING(label) "\n" \
HIDE_SYMBOL(label) "\n" \
".thumb\n" \
".thumb_func " THUMB_FUNC_PARAM(label) "\n" \
SYMBOL_STRING(label) ":\n"
#else
#define OFFLINE_ASM_GLOBAL_LABEL(label) \
".globl " SYMBOL_STRING(label) "\n" \
HIDE_SYMBOL(label) "\n" \
SYMBOL_STRING(label) ":\n"
#endif
#define OFFLINE_ASM_LOCAL_LABEL(label) LOCAL_LABEL_STRING(label) ":\n"
// This is a file generated by offlineasm, which contains all of the assembly code
// for the interpreter, as compiled from LowLevelInterpreter.asm.
#include "LLIntAssembly.h"
......
......@@ -108,13 +108,14 @@ macro cCall2(function, arg1, arg2)
if ARMv7
move arg1, t0
move arg2, t1
call function
elsif X86
poke arg1, 0
poke arg2, 1
call function
else
error
end
call function
end
# This barely works. arg3 and arg4 should probably be immediates.
......@@ -124,15 +125,16 @@ macro cCall4(function, arg1, arg2, arg3, arg4)
move arg2, t1
move arg3, t2
move arg4, t3
call function
elsif X86
poke arg1, 0
poke arg2, 1
poke arg3, 2
poke arg4, 3
call function
else
error
end
call function
end
macro callSlowPath(slowPath)
......@@ -1622,8 +1624,7 @@ macro doCall(slowPath)
storei CellTag, Callee + TagOffset[t3]
storei CellTag, ScopeChain + TagOffset[t3]
move t3, cfr
call LLIntCallLinkInfo::machineCodeTarget[t1]
dispatchAfterCall()
callTargetFunction(t1)
.opCallSlow:
slowPathForCall(6, slowPath)
......
......@@ -51,18 +51,26 @@ macro dispatchAfterCall()
end
macro cCall2(function, arg1, arg2)
move arg1, t5
move arg2, t4
call function
if X86_64
move arg1, t5
move arg2, t4
call function
else
error
end
end
# This barely works. arg3 and arg4 should probably be immediates.
macro cCall4(function, arg1, arg2, arg3, arg4)
move arg1, t5
move arg2, t4
move arg3, t1
move arg4, t2
call function
if X86_64
move arg1, t5
move arg2, t4
move arg3, t1
move arg4, t2
call function
else
error
end
end
macro prepareStateForCCall()
......@@ -1460,8 +1468,7 @@ macro doCall(slowPath)
storep cfr, CallerFrame[t3]
storei t2, ArgumentCount + PayloadOffset[t3]
move t3, cfr
call LLIntCallLinkInfo::machineCodeTarget[t1]
dispatchAfterCall()
callTargetFunction(t1)
.opCallSlow:
slowPathForCall(6, slowPath)
......@@ -1632,21 +1639,26 @@ _llint_throw_during_call_trampoline:
macro nativeCallTrampoline(executableOffsetToFunction)
storep 0, CodeBlock[cfr]
loadp JITStackFrame::globalData + 8[sp], t0
storep cfr, JSGlobalData::topCallFrame[t0]
loadp CallerFrame[cfr], t0
loadp ScopeChain[t0], t1
storep t1, ScopeChain[cfr]
peek 0, t1
storep t1, ReturnPC[cfr]
move cfr, t5 # t5 = rdi
subp 16 - 8, sp
loadp Callee[cfr], t4 # t4 = rsi
loadp JSFunction::m_executable[t4], t1
move t0, cfr # Restore cfr to avoid loading from stack
call executableOffsetToFunction[t1]
addp 16 - 8, sp
loadp JITStackFrame::globalData + 8[sp], t3
if X86_64
loadp JITStackFrame::globalData + 8[sp], t0
storep cfr, JSGlobalData::topCallFrame[t0]
loadp CallerFrame[cfr], t0
loadp ScopeChain[t0], t1
storep t1, ScopeChain[cfr]
peek 0, t1
storep t1, ReturnPC[cfr]
move cfr, t5 # t5 = rdi
subp 16 - 8, sp
loadp Callee[cfr], t4 # t4 = rsi
loadp JSFunction::m_executable[t4], t1
move t0, cfr # Restore cfr to avoid loading from stack
call executableOffsetToFunction[t1]
addp 16 - 8, sp
loadp JITStackFrame::globalData + 8[sp], t3
else
error
end
btpnz JSGlobalData::exception[t3], .exception
ret
.exception:
......
......@@ -151,7 +151,11 @@ class Assembler
@numGlobalLabels += 1
putsNewlineSpacerIfAppropriate(:global)
@internalComment = $enableLabelCountComments ? "Global Label #{@numGlobalLabels}" : nil
@outp.puts(formatDump("OFFLINE_ASM_GLOBAL_LABEL(#{labelName})", lastComment))
if /\Allint_op_/.match(labelName)
@outp.puts(formatDump("OFFLINE_ASM_OPCODE_LABEL(op_#{$~.post_match})", lastComment))
else
@outp.puts(formatDump("OFFLINE_ASM_GLUE_LABEL(#{labelName})", lastComment))
end
@newlineSpacerState = :none # After a global label, we can use another spacer.
end
......
......@@ -21,7 +21,7 @@
# ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
# THE POSSIBILITY OF SUCH DAMAGE.
$preferredCommentStartColumn = 70
$preferredCommentStartColumn = 60
# Turns on dumping of the count of labels.
......
......@@ -28,6 +28,7 @@
#include "CallData.h"
#include "CodeSpecializationKind.h"
#include "HandlerInfo.h"
#include "JSFunction.h"
#include "Interpreter.h"
#include "Nodes.h"
......@@ -202,6 +203,27 @@ namespace JSC {
}
#endif
MacroAssemblerCodePtr hostCodeEntryFor(CodeSpecializationKind kind)
{
return generatedJITCodeFor(kind).addressForCall();
}
MacroAssemblerCodePtr jsCodeEntryFor(CodeSpecializationKind kind)
{
return generatedJITCodeFor(kind).addressForCall();
}
MacroAssemblerCodePtr jsCodeWithArityCheckEntryFor(CodeSpecializationKind kind)
{
return generatedJITCodeWithArityCheckFor(kind);
}
static void* catchRoutineFor(HandlerInfo* handler, Instruction* catchPCForInterpreter)
{
UNUSED_PARAM(catchPCForInterpreter);
return handler->nativeCode.executableAddress();
}
protected:
ExecutableBase* m_prev;
ExecutableBase* m_next;
......
......@@ -323,7 +323,7 @@ namespace JSC {
return payload();
}
#else // USE(JSVALUE32_64)
#else // !USE(JSVALUE32_64) i.e. USE(JSVALUE64)
// JSValue member functions.
inline EncodedJSValue JSValue::encode(JSValue value)
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment