| OLD | NEW |
| 1 // Copyright 2006-2009 the V8 project authors. All rights reserved. | 1 // Copyright 2010 the V8 project authors. All rights reserved. |
| 2 // Redistribution and use in source and binary forms, with or without | 2 // Redistribution and use in source and binary forms, with or without |
| 3 // modification, are permitted provided that the following conditions are | 3 // modification, are permitted provided that the following conditions are |
| 4 // met: | 4 // met: |
| 5 // | 5 // |
| 6 // * Redistributions of source code must retain the above copyright | 6 // * Redistributions of source code must retain the above copyright |
| 7 // notice, this list of conditions and the following disclaimer. | 7 // notice, this list of conditions and the following disclaimer. |
| 8 // * Redistributions in binary form must reproduce the above | 8 // * Redistributions in binary form must reproduce the above |
| 9 // copyright notice, this list of conditions and the following | 9 // copyright notice, this list of conditions and the following |
| 10 // disclaimer in the documentation and/or other materials provided | 10 // disclaimer in the documentation and/or other materials provided |
| 11 // with the distribution. | 11 // with the distribution. |
| (...skipping 12 matching lines...) Expand all Loading... |
| 24 // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT | 24 // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT |
| 25 // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE | 25 // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE |
| 26 // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. | 26 // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
| 27 | 27 |
| 28 #include "v8.h" | 28 #include "v8.h" |
| 29 | 29 |
| 30 #if defined(V8_TARGET_ARCH_IA32) | 30 #if defined(V8_TARGET_ARCH_IA32) |
| 31 | 31 |
| 32 #include "code-stubs.h" | 32 #include "code-stubs.h" |
| 33 #include "codegen-inl.h" | 33 #include "codegen-inl.h" |
| 34 #include "deoptimizer.h" |
| 35 #include "full-codegen.h" |
| 34 | 36 |
| 35 namespace v8 { | 37 namespace v8 { |
| 36 namespace internal { | 38 namespace internal { |
| 37 | 39 |
| 38 | 40 |
| 39 #define __ ACCESS_MASM(masm) | 41 #define __ ACCESS_MASM(masm) |
| 40 | 42 |
| 41 | 43 |
| 42 void Builtins::Generate_Adaptor(MacroAssembler* masm, | 44 void Builtins::Generate_Adaptor(MacroAssembler* masm, |
| 43 CFunctionId id, | 45 CFunctionId id, |
| (...skipping 430 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 474 | 476 |
| 475 // Tear down temporary frame. | 477 // Tear down temporary frame. |
| 476 __ LeaveInternalFrame(); | 478 __ LeaveInternalFrame(); |
| 477 | 479 |
| 478 // Do a tail-call of the compiled function. | 480 // Do a tail-call of the compiled function. |
| 479 __ lea(ecx, FieldOperand(eax, Code::kHeaderSize)); | 481 __ lea(ecx, FieldOperand(eax, Code::kHeaderSize)); |
| 480 __ jmp(Operand(ecx)); | 482 __ jmp(Operand(ecx)); |
| 481 } | 483 } |
| 482 | 484 |
| 483 | 485 |
| 486 void Builtins::Generate_LazyRecompile(MacroAssembler* masm) { |
| 487 // Enter an internal frame. |
| 488 __ EnterInternalFrame(); |
| 489 |
| 490 // Push a copy of the function onto the stack. |
| 491 __ push(edi); |
| 492 |
| 493 __ push(edi); // Function is also the parameter to the runtime call. |
| 494 __ CallRuntime(Runtime::kLazyRecompile, 1); |
| 495 |
| 496 // Restore function and tear down temporary frame. |
| 497 __ pop(edi); |
| 498 __ LeaveInternalFrame(); |
| 499 |
| 500 // Do a tail-call of the compiled function. |
| 501 __ lea(ecx, FieldOperand(eax, Code::kHeaderSize)); |
| 502 __ jmp(Operand(ecx)); |
| 503 } |
| 504 |
| 505 |
| 506 static void Generate_NotifyDeoptimizedHelper(MacroAssembler* masm, |
| 507 Deoptimizer::BailoutType type) { |
| 508 // Enter an internal frame. |
| 509 __ EnterInternalFrame(); |
| 510 |
| 511 // Pass the function and deoptimization type to the runtime system. |
| 512 __ push(Immediate(Smi::FromInt(static_cast<int>(type)))); |
| 513 __ CallRuntime(Runtime::kNotifyDeoptimized, 1); |
| 514 |
| 515 // Tear down temporary frame. |
| 516 __ LeaveInternalFrame(); |
| 517 |
| 518 // Get the full codegen state from the stack and untag it. |
| 519 __ mov(ecx, Operand(esp, 1 * kPointerSize)); |
| 520 __ SmiUntag(ecx); |
| 521 |
| 522 // Switch on the state. |
| 523 NearLabel not_no_registers, not_tos_eax; |
| 524 __ cmp(ecx, FullCodeGenerator::NO_REGISTERS); |
| 525 __ j(not_equal, ¬_no_registers); |
| 526 __ ret(1 * kPointerSize); // Remove state. |
| 527 |
| 528 __ bind(¬_no_registers); |
| 529 __ mov(eax, Operand(esp, 2 * kPointerSize)); |
| 530 __ cmp(ecx, FullCodeGenerator::TOS_REG); |
| 531 __ j(not_equal, ¬_tos_eax); |
| 532 __ ret(2 * kPointerSize); // Remove state, eax. |
| 533 |
| 534 __ bind(¬_tos_eax); |
| 535 __ Abort("no cases left"); |
| 536 } |
| 537 |
| 538 |
| 539 void Builtins::Generate_NotifyDeoptimized(MacroAssembler* masm) { |
| 540 Generate_NotifyDeoptimizedHelper(masm, Deoptimizer::EAGER); |
| 541 } |
| 542 |
| 543 |
| 544 void Builtins::Generate_NotifyLazyDeoptimized(MacroAssembler* masm) { |
| 545 Generate_NotifyDeoptimizedHelper(masm, Deoptimizer::LAZY); |
| 546 } |
| 547 |
| 548 |
| 549 void Builtins::Generate_NotifyOSR(MacroAssembler* masm) { |
| 550 // TODO(kasperl): Do we need to save/restore the XMM registers too? |
| 551 |
| 552 // For now, we are relying on the fact that Runtime::NotifyOSR |
| 553 // doesn't do any garbage collection which allows us to save/restore |
| 554 // the registers without worrying about which of them contain |
| 555 // pointers. This seems a bit fragile. |
| 556 __ pushad(); |
| 557 __ EnterInternalFrame(); |
| 558 __ CallRuntime(Runtime::kNotifyOSR, 0); |
| 559 __ LeaveInternalFrame(); |
| 560 __ popad(); |
| 561 __ ret(0); |
| 562 } |
| 563 |
| 564 |
| 484 void Builtins::Generate_FunctionCall(MacroAssembler* masm) { | 565 void Builtins::Generate_FunctionCall(MacroAssembler* masm) { |
| 485 // 1. Make sure we have at least one argument. | 566 // 1. Make sure we have at least one argument. |
| 486 { Label done; | 567 { Label done; |
| 487 __ test(eax, Operand(eax)); | 568 __ test(eax, Operand(eax)); |
| 488 __ j(not_zero, &done, taken); | 569 __ j(not_zero, &done, taken); |
| 489 __ pop(ebx); | 570 __ pop(ebx); |
| 490 __ push(Immediate(FACTORY->undefined_value())); | 571 __ push(Immediate(FACTORY->undefined_value())); |
| 491 __ push(ebx); | 572 __ push(ebx); |
| 492 __ inc(eax); | 573 __ inc(eax); |
| 493 __ bind(&done); | 574 __ bind(&done); |
| (...skipping 922 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1416 __ ret(0); | 1497 __ ret(0); |
| 1417 | 1498 |
| 1418 // ------------------------------------------- | 1499 // ------------------------------------------- |
| 1419 // Dont adapt arguments. | 1500 // Dont adapt arguments. |
| 1420 // ------------------------------------------- | 1501 // ------------------------------------------- |
| 1421 __ bind(&dont_adapt_arguments); | 1502 __ bind(&dont_adapt_arguments); |
| 1422 __ jmp(Operand(edx)); | 1503 __ jmp(Operand(edx)); |
| 1423 } | 1504 } |
| 1424 | 1505 |
| 1425 | 1506 |
| 1507 void Builtins::Generate_OnStackReplacement(MacroAssembler* masm) { |
| 1508 // We shouldn't be performing on-stack replacement in the first |
| 1509 // place if the CPU features we need for the optimized Crankshaft |
| 1510 // code aren't supported. |
| 1511 CpuFeatures* cpu_features = Isolate::Current()->cpu_features(); |
| 1512 cpu_features->Probe(false); |
| 1513 if (!cpu_features->IsSupported(SSE2)) { |
| 1514 __ Abort("Unreachable code: Cannot optimize without SSE2 support."); |
| 1515 return; |
| 1516 } |
| 1517 |
| 1518 // Get the loop depth of the stack guard check. This is recorded in |
| 1519 // a test(eax, depth) instruction right after the call. |
| 1520 Label stack_check; |
| 1521 __ mov(ebx, Operand(esp, 0)); // return address |
| 1522 if (FLAG_debug_code) { |
| 1523 __ cmpb(Operand(ebx, 0), Assembler::kTestAlByte); |
| 1524 __ Assert(equal, "test eax instruction not found after loop stack check"); |
| 1525 } |
| 1526 __ movzx_b(ebx, Operand(ebx, 1)); // depth |
| 1527 |
| 1528 // Get the loop nesting level at which we allow OSR from the |
| 1529 // unoptimized code and check if we want to do OSR yet. If not we |
| 1530 // should perform a stack guard check so we can get interrupts while |
| 1531 // waiting for on-stack replacement. |
| 1532 __ mov(eax, Operand(ebp, JavaScriptFrameConstants::kFunctionOffset)); |
| 1533 __ mov(ecx, FieldOperand(eax, JSFunction::kSharedFunctionInfoOffset)); |
| 1534 __ mov(ecx, FieldOperand(ecx, SharedFunctionInfo::kCodeOffset)); |
| 1535 __ cmpb(ebx, FieldOperand(ecx, Code::kAllowOSRAtLoopNestingLevelOffset)); |
| 1536 __ j(greater, &stack_check); |
| 1537 |
| 1538 // Pass the function to optimize as the argument to the on-stack |
| 1539 // replacement runtime function. |
| 1540 __ EnterInternalFrame(); |
| 1541 __ push(eax); |
| 1542 __ CallRuntime(Runtime::kCompileForOnStackReplacement, 1); |
| 1543 __ LeaveInternalFrame(); |
| 1544 |
| 1545 // If the result was -1 it means that we couldn't optimize the |
| 1546 // function. Just return and continue in the unoptimized version. |
| 1547 NearLabel skip; |
| 1548 __ cmp(Operand(eax), Immediate(Smi::FromInt(-1))); |
| 1549 __ j(not_equal, &skip); |
| 1550 __ ret(0); |
| 1551 |
| 1552 // If we decide not to perform on-stack replacement we perform a |
| 1553 // stack guard check to enable interrupts. |
| 1554 __ bind(&stack_check); |
| 1555 NearLabel ok; |
| 1556 ExternalReference stack_limit = |
| 1557 ExternalReference::address_of_stack_limit(); |
| 1558 __ cmp(esp, Operand::StaticVariable(stack_limit)); |
| 1559 __ j(above_equal, &ok, taken); |
| 1560 StackCheckStub stub; |
| 1561 __ TailCallStub(&stub); |
| 1562 __ Abort("Unreachable code: returned from tail call."); |
| 1563 __ bind(&ok); |
| 1564 __ ret(0); |
| 1565 |
| 1566 __ bind(&skip); |
| 1567 // Untag the AST id and push it on the stack. |
| 1568 __ SmiUntag(eax); |
| 1569 __ push(eax); |
| 1570 |
| 1571 // Generate the code for doing the frame-to-frame translation using |
| 1572 // the deoptimizer infrastructure. |
| 1573 Deoptimizer::EntryGenerator generator(masm, Deoptimizer::OSR); |
| 1574 generator.Generate(); |
| 1575 } |
| 1576 |
| 1577 |
| 1426 #undef __ | 1578 #undef __ |
| 1427 | 1579 |
| 1428 } } // namespace v8::internal | 1580 } } // namespace v8::internal |
| 1429 | 1581 |
| 1430 #endif // V8_TARGET_ARCH_IA32 | 1582 #endif // V8_TARGET_ARCH_IA32 |
| OLD | NEW |