Ignore:
Timestamp:
Jan 29, 2014, 11:18:54 AM (11 years ago)
Author:
[email protected]
Message:

Merge the jsCStack branch
https://bugs.webkit.org/show_bug.cgi?id=127763

Reviewed by Mark Hahnenberg.

Source/JavaScriptCore:

Changes from http://svn.webkit.org/repository/webkit/branches/jsCStack
up to changeset 162958.

Source/WebCore:

Changes from http://svn.webkit.org/repository/webkit/branches/jsCStack
up to changeset 162958.

Source/WTF:

Changes from http://svn.webkit.org/repository/webkit/branches/jsCStack
up to changeset 162958.

File:
1 edited

Legend:

Unmodified
Added
Removed
  • trunk/Source/JavaScriptCore/llint/LowLevelInterpreter.cpp

    r161866 r163027  
    11/*
    2  * Copyright (C) 2012 Apple Inc. All rights reserved.
     2 * Copyright (C) 2012, 2014 Apple Inc. All rights reserved.
    33 *
    44 * Redistribution and use in source and binary forms, with or without
     
    9191#define OFFLINE_ASM_END
    9292
     93#if ENABLE(OPCODE_TRACING)
     94#define TRACE_OPCODE(opcode) dataLogF("   op %s\n", #opcode)
     95#else
     96#define TRACE_OPCODE(opcode)
     97#endif
     98
    9399// To keep compilers happy in case of unused labels, force usage of the label:
    94100#define USE_LABEL(label) \
     
    98104    } while (false)
    99105
    100 #define OFFLINE_ASM_OPCODE_LABEL(opcode) DEFINE_OPCODE(opcode) USE_LABEL(opcode);
     106#define OFFLINE_ASM_OPCODE_LABEL(opcode) DEFINE_OPCODE(opcode) USE_LABEL(opcode); TRACE_OPCODE(opcode);
    101107
    102108#if ENABLE(COMPUTED_GOTO_OPCODES)
     
    213219#endif // !USE(JSVALUE64)
    214220
     221        intptr_t* ip;
    215222        int8_t* i8p;
    216223        void* vp;
     224        CallFrame* callFrame;
    217225        ExecState* execState;
    218226        void* instruction;
     227        VM* vm;
     228        ProtoCallFrame* protoCallFrame;
    219229        NativeFunction nativeFunc;
    220230#if USE(JSVALUE64)
     
    227237    };
    228238
     239    operator ExecState*() { return execState; }
     240    operator Instruction*() { return reinterpret_cast<Instruction*>(instruction); }
     241    operator VM*() { return vm; }
     242    operator ProtoCallFrame*() { return protoCallFrame; }
     243    operator Register*() { return reinterpret_cast<Register*>(vp); }
     244
    229245#if USE(JSVALUE64)
    230246    inline void clearHighWord() { i32padding = 0; }
     
    238254//
    239255
    240 JSValue CLoop::execute(CallFrame* callFrame, Opcode entryOpcode, bool isInitializationPass)
     256JSValue CLoop::execute(OpcodeID entryOpcodeID, void* executableAddress, VM* vm, ProtoCallFrame* protoCallFrame, bool isInitializationPass)
    241257{
    242258    #define CAST reinterpret_cast
     
    272288        return JSValue();
    273289    }
    274 
    275     ASSERT(callFrame->vm().topCallFrame == callFrame);
    276290
    277291    // Define the pseudo registers used by the LLINT C Loop backend:
     
    309323    // 3. 64 bit result values will be in t0.
    310324
    311     CLoopRegister t0, t1, t2, t3;
     325    CLoopRegister t0, t1, t2, t3, t5, sp, cfr, lr, pc;
    312326#if USE(JSVALUE64)
    313     CLoopRegister rBasePC, tagTypeNumber, tagMask;
    314 #endif
    315     CLoopRegister rRetVPC;
     327    CLoopRegister pcBase, tagTypeNumber, tagMask;
     328#endif
    316329    CLoopDoubleRegister d0, d1;
    317330
    318     // Keep the compiler happy. We don't really need this, but the compiler
    319     // will complain. This makes the warning go away.
    320     t0.i = 0;
    321     t1.i = 0;
    322 
    323     VM* vm = &callFrame->vm();
    324 
    325     CodeBlock* codeBlock = callFrame->codeBlock();
    326     Instruction* vPC;
    327 
    328     // rPC is an alias for vPC. Set up the alias:
    329     CLoopRegister& rPC = *CAST<CLoopRegister*>(&vPC);
    330 
    331 #if USE(JSVALUE32_64)
    332     vPC = codeBlock->instructions().begin();
    333 #else // USE(JSVALUE64)
    334     vPC = 0;
    335     rBasePC.vp = codeBlock->instructions().begin();
    336 
     331    lr.opcode = getOpcode(llint_return_to_host);
     332    sp.vp = vm->interpreter->stack().topOfStack() + 1;
     333    cfr.callFrame = vm->topCallFrame;
     334#ifndef NDEBUG
     335    void* startSP = sp.vp;
     336    CallFrame* startCFR = cfr.callFrame;
     337#endif
     338
     339    // Initialize the incoming args for doCallToJavaScript:
     340    t0.vp = executableAddress;
     341    t1.vm = vm;
     342    t2.protoCallFrame = protoCallFrame;
     343
     344#if USE(JSVALUE64)
    337345    // For the ASM llint, JITStubs takes care of this initialization. We do
    338346    // it explicitly here for the C loop:
     
    341349#endif // USE(JSVALUE64)
    342350
    343     // cfr is an alias for callFrame. Set up this alias:
    344     CLoopRegister& cfr = *CAST<CLoopRegister*>(&callFrame);
    345 
    346     // Simulate a native return PC which should never be used:
    347     rRetVPC.i = 0xbbadbeef;
    348 
    349351    // Interpreter variables for value passing between opcodes and/or helpers:
    350352    NativeFunction nativeFunc = 0;
    351353    JSValue functionReturnValue;
    352     Opcode opcode;
    353 
    354     opcode = entryOpcode;
    355 
    356     #if ENABLE(OPCODE_STATS)
    357         #define RECORD_OPCODE_STATS(__opcode) \
    358             OpcodeStats::recordInstruction(__opcode)
    359     #else
    360         #define RECORD_OPCODE_STATS(__opcode)
    361     #endif
    362 
    363     #if USE(JSVALUE32_64)
    364         #define FETCH_OPCODE() vPC->u.opcode
    365     #else // USE(JSVALUE64)
    366         #define FETCH_OPCODE() *bitwise_cast<Opcode*>(rBasePC.i8p + rPC.i * 8)
    367     #endif // USE(JSVALUE64)
    368 
    369     #define NEXT_INSTRUCTION() \
    370         do {                         \
    371             opcode = FETCH_OPCODE(); \
    372             DISPATCH_OPCODE();       \
    373         } while (false)
     354    Opcode opcode = getOpcode(entryOpcodeID);
     355
     356#define PUSH(cloopReg) \
     357    do { \
     358        sp.ip--; \
     359        *sp.ip = cloopReg.i; \
     360    } while (false)
     361
     362#define POP(cloopReg) \
     363    do { \
     364        cloopReg.i = *sp.ip; \
     365        sp.ip++; \
     366    } while (false)
     367
     368#if ENABLE(OPCODE_STATS)
     369#define RECORD_OPCODE_STATS(__opcode) OpcodeStats::recordInstruction(__opcode)
     370#else
     371#define RECORD_OPCODE_STATS(__opcode)
     372#endif
     373
     374#if USE(JSVALUE32_64)
     375#define FETCH_OPCODE() pc.opcode
     376#else // USE(JSVALUE64)
     377#define FETCH_OPCODE() *bitwise_cast<Opcode*>(pcBase.i8p + pc.i * 8)
     378#endif // USE(JSVALUE64)
     379
     380#define NEXT_INSTRUCTION() \
     381    do {                         \
     382        opcode = FETCH_OPCODE(); \
     383        DISPATCH_OPCODE();       \
     384    } while (false)
    374385
    375386#if ENABLE(COMPUTED_GOTO_OPCODES)
     
    413424        #include "LLIntAssembly.h"
    414425
     426        OFFLINE_ASM_GLUE_LABEL(llint_return_to_host)
     427        {
     428            ASSERT(startSP == sp.vp);
     429            ASSERT(startCFR == cfr.callFrame);
     430#if USE(JSVALUE32_64)
     431            return JSValue(t1.i, t0.i); // returning JSValue(tag, payload);
     432#else
     433            return JSValue::decode(t0.encodedJSValue);
     434#endif
     435        }
     436
    415437        // In the ASM llint, getHostCallReturnValue() is a piece of glue
    416         // function provided by the JIT (see dfg/DFGOperations.cpp).
     438        // function provided by the JIT (see jit/JITOperations.cpp).
    417439        // We simulate it here with a pseduo-opcode handler.
    418440        OFFLINE_ASM_GLUE_LABEL(getHostCallReturnValue)
    419441        {
    420             // The ASM part pops the frame:
    421             callFrame = callFrame->callerFrame();
    422 
    423442            // The part in getHostCallReturnValueWithExecState():
    424443            JSValue result = vm->hostCallReturnValue;
     
    429448            t0.encodedJSValue = JSValue::encode(result);
    430449#endif
    431             goto doReturnHelper;
    432         }
    433 
    434         OFFLINE_ASM_GLUE_LABEL(returnFromJavaScript)
    435         {
    436             return vm->exception();
     450            opcode = lr.opcode;
     451            DISPATCH_OPCODE();
    437452        }
    438453
     
    443458
    444459    } // END bytecode handler cases.
    445 
    446     //========================================================================
    447     // Bytecode helpers:
    448 
    449     doReturnHelper: {
    450         ASSERT(!!callFrame);
    451         if (callFrame->isVMEntrySentinel()) {
    452 #if USE(JSVALUE32_64)
    453             return JSValue(t1.i, t0.i); // returning JSValue(tag, payload);
    454 #else
    455             return JSValue::decode(t0.encodedJSValue);
    456 #endif
    457         }
    458 
    459         // The normal ASM llint call implementation returns to the caller as
    460         // recorded in rRetVPC, and the caller would fetch the return address
    461         // from ArgumentCount.tag() (see the dispatchAfterCall() macro used in
    462         // the callTargetFunction() macro in the llint asm files).
    463         //
    464         // For the C loop, we don't have the JIT stub to do this work for us. So,
    465         // we jump to llint_generic_return_point.
    466 
    467         vPC = callFrame->currentVPC();
    468 
    469 #if USE(JSVALUE64)
    470         // Based on LowLevelInterpreter64.asm's dispatchAfterCall():
    471 
    472         // When returning from a native trampoline call, unlike the assembly
    473         // LLInt, we can't simply return to the caller. In our case, we grab
    474         // the caller's VPC and resume execution there. However, the caller's
    475         // VPC returned by callFrame->currentVPC() is in the form of the real
    476         // address of the target bytecode, but the 64-bit llint expects the
    477         // VPC to be a bytecode offset. Hence, we need to map it back to a
    478         // bytecode offset before we dispatch via the usual dispatch mechanism
    479         // i.e. NEXT_INSTRUCTION():
    480 
    481         codeBlock = callFrame->codeBlock();
    482         ASSERT(codeBlock);
    483         rPC.vp = callFrame->currentVPC();
    484         rPC.i = rPC.i8p - reinterpret_cast<int8_t*>(codeBlock->instructions().begin());
    485         rPC.i >>= 3;
    486 
    487         rBasePC.vp = codeBlock->instructions().begin();
    488 #endif // USE(JSVALUE64)
    489 
    490         goto llint_generic_return_point;
    491 
    492     } // END doReturnHelper.
    493 
    494460
    495461#if ENABLE(COMPUTED_GOTO_OPCODES)
     
    524490// These are for building an interpreter from generated assembly code:
    525491#if CPU(X86_64) && COMPILER(CLANG)
    526 #define OFFLINE_ASM_BEGIN   asm ( \
     492#define OFFLINE_ASM_BEGIN   asm (                \
    527493    ".cfi_startproc\n"
    528494
    529 #define OFFLINE_ASM_END     \
    530     ".cfi_endproc\n" \
    531 );
     495#define OFFLINE_ASM_END                          \
     496    ".cfi_endproc\n"                             \
     497                            );
    532498#else
    533499#define OFFLINE_ASM_BEGIN   asm (
     
    552518    HIDE_SYMBOL(label) "\n"                     \
    553519    SYMBOL_STRING(label) ":\n"                  \
    554     ".cfi_def_cfa rbp, 0\n"                     \
    555     ".cfi_offset 16, 8\n"                       \
    556     ".cfi_offset 6, 0\n"
     520    ".cfi_def_cfa_offset 16\n"                  \
     521    ".cfi_offset %rbp, -16\n"                   \
     522    ".cfi_def_cfa_register rbp\n"
    557523#else
    558524#define OFFLINE_ASM_GLOBAL_LABEL(label)         \
Note: See TracChangeset for help on using the changeset viewer.