Changeset 163027 in webkit for trunk/Source/JavaScriptCore/llint/LowLevelInterpreter.cpp
- Timestamp:
- Jan 29, 2014, 11:18:54 AM (11 years ago)
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/Source/JavaScriptCore/llint/LowLevelInterpreter.cpp
r161866 r163027 1 1 /* 2 * Copyright (C) 2012 Apple Inc. All rights reserved.2 * Copyright (C) 2012, 2014 Apple Inc. All rights reserved. 3 3 * 4 4 * Redistribution and use in source and binary forms, with or without … … 91 91 #define OFFLINE_ASM_END 92 92 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 93 99 // To keep compilers happy in case of unused labels, force usage of the label: 94 100 #define USE_LABEL(label) \ … … 98 104 } while (false) 99 105 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); 101 107 102 108 #if ENABLE(COMPUTED_GOTO_OPCODES) … … 213 219 #endif // !USE(JSVALUE64) 214 220 221 intptr_t* ip; 215 222 int8_t* i8p; 216 223 void* vp; 224 CallFrame* callFrame; 217 225 ExecState* execState; 218 226 void* instruction; 227 VM* vm; 228 ProtoCallFrame* protoCallFrame; 219 229 NativeFunction nativeFunc; 220 230 #if USE(JSVALUE64) … … 227 237 }; 228 238 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 229 245 #if USE(JSVALUE64) 230 246 inline void clearHighWord() { i32padding = 0; } … … 238 254 // 239 255 240 JSValue CLoop::execute( CallFrame* callFrame, Opcode entryOpcode, bool isInitializationPass)256 JSValue CLoop::execute(OpcodeID entryOpcodeID, void* executableAddress, VM* vm, ProtoCallFrame* protoCallFrame, bool isInitializationPass) 241 257 { 242 258 #define CAST reinterpret_cast … … 272 288 return JSValue(); 273 289 } 274 275 ASSERT(callFrame->vm().topCallFrame == callFrame);276 290 277 291 // Define the pseudo registers used by the LLINT C Loop backend: … … 309 323 // 3. 64 bit result values will be in t0. 310 324 311 CLoopRegister t0, t1, t2, t3 ;325 CLoopRegister t0, t1, t2, t3, t5, sp, cfr, lr, pc; 312 326 #if USE(JSVALUE64) 313 CLoopRegister rBasePC, tagTypeNumber, tagMask; 314 #endif 315 CLoopRegister rRetVPC; 327 CLoopRegister pcBase, tagTypeNumber, tagMask; 328 #endif 316 329 CLoopDoubleRegister d0, d1; 317 330 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) 337 345 // For the ASM llint, JITStubs takes care of this initialization. We do 338 346 // it explicitly here for the C loop: … … 341 349 #endif // USE(JSVALUE64) 342 350 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 349 351 // Interpreter variables for value passing between opcodes and/or helpers: 350 352 NativeFunction nativeFunc = 0; 351 353 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) 374 385 375 386 #if ENABLE(COMPUTED_GOTO_OPCODES) … … 413 424 #include "LLIntAssembly.h" 414 425 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 415 437 // 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). 417 439 // We simulate it here with a pseduo-opcode handler. 418 440 OFFLINE_ASM_GLUE_LABEL(getHostCallReturnValue) 419 441 { 420 // The ASM part pops the frame:421 callFrame = callFrame->callerFrame();422 423 442 // The part in getHostCallReturnValueWithExecState(): 424 443 JSValue result = vm->hostCallReturnValue; … … 429 448 t0.encodedJSValue = JSValue::encode(result); 430 449 #endif 431 goto doReturnHelper; 432 } 433 434 OFFLINE_ASM_GLUE_LABEL(returnFromJavaScript) 435 { 436 return vm->exception(); 450 opcode = lr.opcode; 451 DISPATCH_OPCODE(); 437 452 } 438 453 … … 443 458 444 459 } // 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 #else455 return JSValue::decode(t0.encodedJSValue);456 #endif457 }458 459 // The normal ASM llint call implementation returns to the caller as460 // recorded in rRetVPC, and the caller would fetch the return address461 // from ArgumentCount.tag() (see the dispatchAfterCall() macro used in462 // 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 assembly473 // LLInt, we can't simply return to the caller. In our case, we grab474 // the caller's VPC and resume execution there. However, the caller's475 // VPC returned by callFrame->currentVPC() is in the form of the real476 // address of the target bytecode, but the 64-bit llint expects the477 // VPC to be a bytecode offset. Hence, we need to map it back to a478 // bytecode offset before we dispatch via the usual dispatch mechanism479 // 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 494 460 495 461 #if ENABLE(COMPUTED_GOTO_OPCODES) … … 524 490 // These are for building an interpreter from generated assembly code: 525 491 #if CPU(X86_64) && COMPILER(CLANG) 526 #define OFFLINE_ASM_BEGIN asm ( \492 #define OFFLINE_ASM_BEGIN asm ( \ 527 493 ".cfi_startproc\n" 528 494 529 #define OFFLINE_ASM_END \530 ".cfi_endproc\n" \531 );495 #define OFFLINE_ASM_END \ 496 ".cfi_endproc\n" \ 497 ); 532 498 #else 533 499 #define OFFLINE_ASM_BEGIN asm ( … … 552 518 HIDE_SYMBOL(label) "\n" \ 553 519 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" 557 523 #else 558 524 #define OFFLINE_ASM_GLOBAL_LABEL(label) \
Note:
See TracChangeset
for help on using the changeset viewer.