| OLD | NEW |
| 1 // Copyright 2013 the V8 project authors. All rights reserved. | 1 // Copyright 2013 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 |
| (...skipping 398 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 409 | 409 |
| 410 | 410 |
| 411 void LCodeGen::CallCodeGeneric(Handle<Code> code, | 411 void LCodeGen::CallCodeGeneric(Handle<Code> code, |
| 412 RelocInfo::Mode mode, | 412 RelocInfo::Mode mode, |
| 413 LInstruction* instr, | 413 LInstruction* instr, |
| 414 SafepointMode safepoint_mode) { | 414 SafepointMode safepoint_mode) { |
| 415 EnsureSpaceForLazyDeopt(Deoptimizer::patch_size()); | 415 EnsureSpaceForLazyDeopt(Deoptimizer::patch_size()); |
| 416 ASSERT(instr != NULL); | 416 ASSERT(instr != NULL); |
| 417 | 417 |
| 418 Assembler::BlockConstPoolScope scope(masm_); | 418 Assembler::BlockConstPoolScope scope(masm_); |
| 419 LPointerMap* pointers = instr->pointer_map(); | |
| 420 RecordPosition(pointers->position()); | |
| 421 __ Call(code, mode); | 419 __ Call(code, mode); |
| 422 RecordSafepointWithLazyDeopt(instr, safepoint_mode); | 420 RecordSafepointWithLazyDeopt(instr, safepoint_mode); |
| 423 | 421 |
| 424 if ((code->kind() == Code::BINARY_OP_IC) || | 422 if ((code->kind() == Code::BINARY_OP_IC) || |
| 425 (code->kind() == Code::COMPARE_IC)) { | 423 (code->kind() == Code::COMPARE_IC)) { |
| 426 // Signal that we don't inline smi code before these stubs in the | 424 // Signal that we don't inline smi code before these stubs in the |
| 427 // optimizing code generator. | 425 // optimizing code generator. |
| 428 InlineSmiCheckInfo::EmitNotInlined(masm()); | 426 InlineSmiCheckInfo::EmitNotInlined(masm()); |
| 429 } | 427 } |
| 430 } | 428 } |
| (...skipping 70 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 501 | 499 |
| 502 ASSERT(ToRegister(instr->result()).is(x0)); | 500 ASSERT(ToRegister(instr->result()).is(x0)); |
| 503 } | 501 } |
| 504 | 502 |
| 505 | 503 |
| 506 void LCodeGen::CallRuntime(const Runtime::Function* function, | 504 void LCodeGen::CallRuntime(const Runtime::Function* function, |
| 507 int num_arguments, | 505 int num_arguments, |
| 508 LInstruction* instr, | 506 LInstruction* instr, |
| 509 SaveFPRegsMode save_doubles) { | 507 SaveFPRegsMode save_doubles) { |
| 510 ASSERT(instr != NULL); | 508 ASSERT(instr != NULL); |
| 511 LPointerMap* pointers = instr->pointer_map(); | |
| 512 ASSERT(pointers != NULL); | |
| 513 RecordPosition(pointers->position()); | |
| 514 | 509 |
| 515 __ CallRuntime(function, num_arguments, save_doubles); | 510 __ CallRuntime(function, num_arguments, save_doubles); |
| 516 | 511 |
| 517 RecordSafepointWithLazyDeopt(instr, RECORD_SIMPLE_SAFEPOINT); | 512 RecordSafepointWithLazyDeopt(instr, RECORD_SIMPLE_SAFEPOINT); |
| 518 } | 513 } |
| 519 | 514 |
| 520 | 515 |
| 521 void LCodeGen::CallRuntimeFromDeferred(Runtime::FunctionId id, | 516 void LCodeGen::CallRuntimeFromDeferred(Runtime::FunctionId id, |
| 522 int argc, | 517 int argc, |
| 523 LInstruction* instr) { | 518 LInstruction* instr) { |
| 524 __ CallRuntimeSaveDoubles(id); | 519 __ CallRuntimeSaveDoubles(id); |
| 525 RecordSafepointWithRegisters( | 520 RecordSafepointWithRegisters( |
| 526 instr->pointer_map(), argc, Safepoint::kNoLazyDeopt); | 521 instr->pointer_map(), argc, Safepoint::kNoLazyDeopt); |
| 527 } | 522 } |
| 528 | 523 |
| 529 | 524 |
| 530 void LCodeGen::RecordPosition(int position) { | 525 void LCodeGen::RecordAndWritePosition(int position) { |
| 531 if (position == RelocInfo::kNoPosition) return; | 526 if (position == RelocInfo::kNoPosition) return; |
| 532 masm()->positions_recorder()->RecordPosition(position); | 527 masm()->positions_recorder()->RecordPosition(position); |
| 528 masm()->positions_recorder()->WriteRecordedPositions(); |
| 533 } | 529 } |
| 534 | 530 |
| 535 | 531 |
| 536 void LCodeGen::RecordAndUpdatePosition(int position) { | |
| 537 if (position >= 0 && position != old_position_) { | |
| 538 masm()->positions_recorder()->RecordPosition(position); | |
| 539 old_position_ = position; | |
| 540 } | |
| 541 } | |
| 542 | |
| 543 | |
| 544 void LCodeGen::RecordSafepointWithLazyDeopt(LInstruction* instr, | 532 void LCodeGen::RecordSafepointWithLazyDeopt(LInstruction* instr, |
| 545 SafepointMode safepoint_mode) { | 533 SafepointMode safepoint_mode) { |
| 546 if (safepoint_mode == RECORD_SIMPLE_SAFEPOINT) { | 534 if (safepoint_mode == RECORD_SIMPLE_SAFEPOINT) { |
| 547 RecordSafepoint(instr->pointer_map(), Safepoint::kLazyDeopt); | 535 RecordSafepoint(instr->pointer_map(), Safepoint::kLazyDeopt); |
| 548 } else { | 536 } else { |
| 549 ASSERT(safepoint_mode == RECORD_SAFEPOINT_WITH_REGISTERS_AND_NO_ARGUMENTS); | 537 ASSERT(safepoint_mode == RECORD_SAFEPOINT_WITH_REGISTERS_AND_NO_ARGUMENTS); |
| 550 RecordSafepointWithRegisters( | 538 RecordSafepointWithRegisters( |
| 551 instr->pointer_map(), 0, Safepoint::kLazyDeopt); | 539 instr->pointer_map(), 0, Safepoint::kLazyDeopt); |
| 552 } | 540 } |
| 553 } | 541 } |
| (...skipping 24 matching lines...) Expand all Loading... |
| 578 } | 566 } |
| 579 } | 567 } |
| 580 | 568 |
| 581 void LCodeGen::RecordSafepoint(LPointerMap* pointers, | 569 void LCodeGen::RecordSafepoint(LPointerMap* pointers, |
| 582 Safepoint::DeoptMode deopt_mode) { | 570 Safepoint::DeoptMode deopt_mode) { |
| 583 RecordSafepoint(pointers, Safepoint::kSimple, 0, deopt_mode); | 571 RecordSafepoint(pointers, Safepoint::kSimple, 0, deopt_mode); |
| 584 } | 572 } |
| 585 | 573 |
| 586 | 574 |
| 587 void LCodeGen::RecordSafepoint(Safepoint::DeoptMode deopt_mode) { | 575 void LCodeGen::RecordSafepoint(Safepoint::DeoptMode deopt_mode) { |
| 588 LPointerMap empty_pointers(RelocInfo::kNoPosition, zone()); | 576 LPointerMap empty_pointers(zone()); |
| 589 RecordSafepoint(&empty_pointers, deopt_mode); | 577 RecordSafepoint(&empty_pointers, deopt_mode); |
| 590 } | 578 } |
| 591 | 579 |
| 592 | 580 |
| 593 void LCodeGen::RecordSafepointWithRegisters(LPointerMap* pointers, | 581 void LCodeGen::RecordSafepointWithRegisters(LPointerMap* pointers, |
| 594 int arguments, | 582 int arguments, |
| 595 Safepoint::DeoptMode deopt_mode) { | 583 Safepoint::DeoptMode deopt_mode) { |
| 596 RecordSafepoint(pointers, Safepoint::kWithRegisters, arguments, deopt_mode); | 584 RecordSafepoint(pointers, Safepoint::kWithRegisters, arguments, deopt_mode); |
| 597 } | 585 } |
| 598 | 586 |
| (...skipping 42 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 641 int receiver_offset = scope()->num_parameters() * kPointerSize; | 629 int receiver_offset = scope()->num_parameters() * kPointerSize; |
| 642 __ LoadRoot(x10, Heap::kUndefinedValueRootIndex); | 630 __ LoadRoot(x10, Heap::kUndefinedValueRootIndex); |
| 643 __ Poke(x10, receiver_offset); | 631 __ Poke(x10, receiver_offset); |
| 644 __ Bind(&ok); | 632 __ Bind(&ok); |
| 645 } | 633 } |
| 646 } | 634 } |
| 647 | 635 |
| 648 ASSERT(__ StackPointer().Is(jssp)); | 636 ASSERT(__ StackPointer().Is(jssp)); |
| 649 info()->set_prologue_offset(masm_->pc_offset()); | 637 info()->set_prologue_offset(masm_->pc_offset()); |
| 650 if (NeedsEagerFrame()) { | 638 if (NeedsEagerFrame()) { |
| 651 if (info()->IsStub()) { | 639 __ Prologue(info()->IsStub() ? BUILD_STUB_FRAME : BUILD_FUNCTION_FRAME); |
| 652 // TODO(jbramley): Does x1 contain a JSFunction here, or does it already | |
| 653 // have the special STUB smi? | |
| 654 __ Mov(x10, Operand(Smi::FromInt(StackFrame::STUB))); | |
| 655 // Compiled stubs don't age, and so they don't need the predictable code | |
| 656 // ageing sequence. | |
| 657 __ Push(lr, fp, cp, x10); | |
| 658 __ Add(fp, jssp, 2 * kPointerSize); | |
| 659 } else { | |
| 660 // This call emits the following sequence in a way that can be patched for | |
| 661 // code ageing support: | |
| 662 // Push(lr, fp, cp, x1); | |
| 663 // Add(fp, jssp, 2 * kPointerSize); | |
| 664 __ EmitFrameSetupForCodeAgePatching(); | |
| 665 } | |
| 666 frame_is_built_ = true; | 640 frame_is_built_ = true; |
| 667 info_->AddNoFrameRange(0, masm_->pc_offset()); | 641 info_->AddNoFrameRange(0, masm_->pc_offset()); |
| 668 } | 642 } |
| 669 | 643 |
| 670 // Reserve space for the stack slots needed by the code. | 644 // Reserve space for the stack slots needed by the code. |
| 671 int slots = GetStackSlotCount(); | 645 int slots = GetStackSlotCount(); |
| 672 if (slots > 0) { | 646 if (slots > 0) { |
| 673 __ Claim(slots, kPointerSize); | 647 __ Claim(slots, kPointerSize); |
| 674 } | 648 } |
| 675 | 649 |
| (...skipping 73 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 749 __ Claim(slots); | 723 __ Claim(slots); |
| 750 } | 724 } |
| 751 | 725 |
| 752 | 726 |
| 753 bool LCodeGen::GenerateDeferredCode() { | 727 bool LCodeGen::GenerateDeferredCode() { |
| 754 ASSERT(is_generating()); | 728 ASSERT(is_generating()); |
| 755 if (deferred_.length() > 0) { | 729 if (deferred_.length() > 0) { |
| 756 for (int i = 0; !is_aborted() && (i < deferred_.length()); i++) { | 730 for (int i = 0; !is_aborted() && (i < deferred_.length()); i++) { |
| 757 LDeferredCode* code = deferred_[i]; | 731 LDeferredCode* code = deferred_[i]; |
| 758 | 732 |
| 759 int pos = instructions_->at(code->instruction_index())->position(); | 733 HValue* value = |
| 760 RecordAndUpdatePosition(pos); | 734 instructions_->at(code->instruction_index())->hydrogen_value(); |
| 735 RecordAndWritePosition(value->position()); |
| 761 | 736 |
| 762 Comment(";;; <@%d,#%d> " | 737 Comment(";;; <@%d,#%d> " |
| 763 "-------------------- Deferred %s --------------------", | 738 "-------------------- Deferred %s --------------------", |
| 764 code->instruction_index(), | 739 code->instruction_index(), |
| 765 code->instr()->hydrogen_value()->id(), | 740 code->instr()->hydrogen_value()->id(), |
| 766 code->instr()->Mnemonic()); | 741 code->instr()->Mnemonic()); |
| 767 | 742 |
| 768 __ Bind(code->entry()); | 743 __ Bind(code->entry()); |
| 769 | 744 |
| 770 if (NeedsDeferredFrame()) { | 745 if (NeedsDeferredFrame()) { |
| (...skipping 423 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1194 } | 1169 } |
| 1195 | 1170 |
| 1196 | 1171 |
| 1197 Condition LCodeGen::TokenToCondition(Token::Value op, bool is_unsigned) { | 1172 Condition LCodeGen::TokenToCondition(Token::Value op, bool is_unsigned) { |
| 1198 Condition cond = nv; | 1173 Condition cond = nv; |
| 1199 switch (op) { | 1174 switch (op) { |
| 1200 case Token::EQ: | 1175 case Token::EQ: |
| 1201 case Token::EQ_STRICT: | 1176 case Token::EQ_STRICT: |
| 1202 cond = eq; | 1177 cond = eq; |
| 1203 break; | 1178 break; |
| 1179 case Token::NE: |
| 1180 case Token::NE_STRICT: |
| 1181 cond = ne; |
| 1182 break; |
| 1204 case Token::LT: | 1183 case Token::LT: |
| 1205 cond = is_unsigned ? lo : lt; | 1184 cond = is_unsigned ? lo : lt; |
| 1206 break; | 1185 break; |
| 1207 case Token::GT: | 1186 case Token::GT: |
| 1208 cond = is_unsigned ? hi : gt; | 1187 cond = is_unsigned ? hi : gt; |
| 1209 break; | 1188 break; |
| 1210 case Token::LTE: | 1189 case Token::LTE: |
| 1211 cond = is_unsigned ? ls : le; | 1190 cond = is_unsigned ? ls : le; |
| 1212 break; | 1191 break; |
| 1213 case Token::GTE: | 1192 case Token::GTE: |
| (...skipping 281 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1495 __ Cbz(length, &invoke); | 1474 __ Cbz(length, &invoke); |
| 1496 __ Bind(&loop); | 1475 __ Bind(&loop); |
| 1497 __ Ldr(scratch, MemOperand(elements, length, LSL, kPointerSizeLog2)); | 1476 __ Ldr(scratch, MemOperand(elements, length, LSL, kPointerSizeLog2)); |
| 1498 __ Push(scratch); | 1477 __ Push(scratch); |
| 1499 __ Subs(length, length, 1); | 1478 __ Subs(length, length, 1); |
| 1500 __ B(ne, &loop); | 1479 __ B(ne, &loop); |
| 1501 | 1480 |
| 1502 __ Bind(&invoke); | 1481 __ Bind(&invoke); |
| 1503 ASSERT(instr->HasPointerMap()); | 1482 ASSERT(instr->HasPointerMap()); |
| 1504 LPointerMap* pointers = instr->pointer_map(); | 1483 LPointerMap* pointers = instr->pointer_map(); |
| 1505 RecordPosition(pointers->position()); | |
| 1506 SafepointGenerator safepoint_generator(this, pointers, Safepoint::kLazyDeopt); | 1484 SafepointGenerator safepoint_generator(this, pointers, Safepoint::kLazyDeopt); |
| 1507 // The number of arguments is stored in argc (receiver) which is x0, as | 1485 // The number of arguments is stored in argc (receiver) which is x0, as |
| 1508 // expected by InvokeFunction. | 1486 // expected by InvokeFunction. |
| 1509 ParameterCount actual(argc); | 1487 ParameterCount actual(argc); |
| 1510 __ InvokeFunction(function, actual, CALL_FUNCTION, | 1488 __ InvokeFunction(function, actual, CALL_FUNCTION, |
| 1511 safepoint_generator, CALL_AS_METHOD); | 1489 safepoint_generator, CALL_AS_METHOD); |
| 1512 __ Ldr(cp, MemOperand(fp, StandardFrameConstants::kContextOffset)); | 1490 __ Ldr(cp, MemOperand(fp, StandardFrameConstants::kContextOffset)); |
| 1513 } | 1491 } |
| 1514 | 1492 |
| 1515 | 1493 |
| (...skipping 306 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1822 formal_parameter_count == SharedFunctionInfo::kDontAdaptArgumentsSentinel; | 1800 formal_parameter_count == SharedFunctionInfo::kDontAdaptArgumentsSentinel; |
| 1823 bool can_invoke_directly = | 1801 bool can_invoke_directly = |
| 1824 dont_adapt_arguments || formal_parameter_count == arity; | 1802 dont_adapt_arguments || formal_parameter_count == arity; |
| 1825 | 1803 |
| 1826 // The function interface relies on the following register assignments. | 1804 // The function interface relies on the following register assignments. |
| 1827 ASSERT(function_reg.Is(x1) || function_reg.IsNone()); | 1805 ASSERT(function_reg.Is(x1) || function_reg.IsNone()); |
| 1828 Register arity_reg = x0; | 1806 Register arity_reg = x0; |
| 1829 Register call_kind_reg = x5; | 1807 Register call_kind_reg = x5; |
| 1830 | 1808 |
| 1831 LPointerMap* pointers = instr->pointer_map(); | 1809 LPointerMap* pointers = instr->pointer_map(); |
| 1832 RecordPosition(pointers->position()); | |
| 1833 | 1810 |
| 1834 // If necessary, load the function object. | 1811 // If necessary, load the function object. |
| 1835 if (function_reg.IsNone()) { | 1812 if (function_reg.IsNone()) { |
| 1836 function_reg = x1; | 1813 function_reg = x1; |
| 1837 __ LoadHeapObject(function_reg, function); | 1814 __ LoadObject(function_reg, function); |
| 1838 } | 1815 } |
| 1839 | 1816 |
| 1840 if (FLAG_debug_code) { | 1817 if (FLAG_debug_code) { |
| 1841 Label is_not_smi; | 1818 Label is_not_smi; |
| 1842 // Try to confirm that function_reg (x1) is a tagged pointer. | 1819 // Try to confirm that function_reg (x1) is a tagged pointer. |
| 1843 __ JumpIfNotSmi(function_reg, &is_not_smi); | 1820 __ JumpIfNotSmi(function_reg, &is_not_smi); |
| 1844 __ Abort(kExpectedFunctionObject); | 1821 __ Abort(kExpectedFunctionObject); |
| 1845 __ Bind(&is_not_smi); | 1822 __ Bind(&is_not_smi); |
| 1846 } | 1823 } |
| 1847 | 1824 |
| (...skipping 1094 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2942 | 2919 |
| 2943 __ Bind(&return_false); | 2920 __ Bind(&return_false); |
| 2944 __ LoadRoot(result, Heap::kFalseValueRootIndex); | 2921 __ LoadRoot(result, Heap::kFalseValueRootIndex); |
| 2945 | 2922 |
| 2946 // Here result is either true or false. | 2923 // Here result is either true or false. |
| 2947 __ Bind(deferred->exit()); | 2924 __ Bind(deferred->exit()); |
| 2948 __ Bind(&done); | 2925 __ Bind(&done); |
| 2949 } | 2926 } |
| 2950 | 2927 |
| 2951 | 2928 |
| 2952 void LCodeGen::DoInstanceSize(LInstanceSize* instr) { | |
| 2953 Register object = ToRegister(instr->object()); | |
| 2954 Register result = ToRegister(instr->result()); | |
| 2955 __ Ldr(result, FieldMemOperand(object, HeapObject::kMapOffset)); | |
| 2956 __ Ldrb(result, FieldMemOperand(result, Map::kInstanceSizeOffset)); | |
| 2957 } | |
| 2958 | |
| 2959 | |
| 2960 void LCodeGen::DoDeferredInstanceOfKnownGlobal(LInstanceOfKnownGlobal* instr) { | 2929 void LCodeGen::DoDeferredInstanceOfKnownGlobal(LInstanceOfKnownGlobal* instr) { |
| 2961 Register result = ToRegister(instr->result()); | 2930 Register result = ToRegister(instr->result()); |
| 2962 ASSERT(result.Is(x0)); // InstanceofStub returns its result in x0. | 2931 ASSERT(result.Is(x0)); // InstanceofStub returns its result in x0. |
| 2963 InstanceofStub::Flags flags = InstanceofStub::kNoFlags; | 2932 InstanceofStub::Flags flags = InstanceofStub::kNoFlags; |
| 2964 flags = static_cast<InstanceofStub::Flags>( | 2933 flags = static_cast<InstanceofStub::Flags>( |
| 2965 flags | InstanceofStub::kArgsInRegisters); | 2934 flags | InstanceofStub::kArgsInRegisters); |
| 2966 flags = static_cast<InstanceofStub::Flags>( | 2935 flags = static_cast<InstanceofStub::Flags>( |
| 2967 flags | InstanceofStub::kReturnTrueFalseObject); | 2936 flags | InstanceofStub::kReturnTrueFalseObject); |
| 2968 flags = static_cast<InstanceofStub::Flags>( | 2937 flags = static_cast<InstanceofStub::Flags>( |
| 2969 flags | InstanceofStub::kCallSiteInlineCheck); | 2938 flags | InstanceofStub::kCallSiteInlineCheck); |
| 2970 | 2939 |
| 2971 PushSafepointRegistersScope scope(this, Safepoint::kWithRegisters); | 2940 PushSafepointRegistersScope scope(this, Safepoint::kWithRegisters); |
| 2972 | 2941 |
| 2973 // Prepare InstanceofStub arguments. | 2942 // Prepare InstanceofStub arguments. |
| 2974 ASSERT(ToRegister(instr->value()).Is(InstanceofStub::left())); | 2943 ASSERT(ToRegister(instr->value()).Is(InstanceofStub::left())); |
| 2975 __ LoadHeapObject(InstanceofStub::right(), instr->function()); | 2944 __ LoadObject(InstanceofStub::right(), instr->function()); |
| 2976 | 2945 |
| 2977 InstanceofStub stub(flags); | 2946 InstanceofStub stub(flags); |
| 2978 CallCodeGeneric(stub.GetCode(isolate()), | 2947 CallCodeGeneric(stub.GetCode(isolate()), |
| 2979 RelocInfo::CODE_TARGET, | 2948 RelocInfo::CODE_TARGET, |
| 2980 instr, | 2949 instr, |
| 2981 RECORD_SAFEPOINT_WITH_REGISTERS_AND_NO_ARGUMENTS); | 2950 RECORD_SAFEPOINT_WITH_REGISTERS_AND_NO_ARGUMENTS); |
| 2982 LEnvironment* env = instr->GetDeferredLazyDeoptimizationEnvironment(); | 2951 LEnvironment* env = instr->GetDeferredLazyDeoptimizationEnvironment(); |
| 2983 safepoints_.RecordLazyDeoptimizationIndex(env->deoptimization_index()); | 2952 safepoints_.RecordLazyDeoptimizationIndex(env->deoptimization_index()); |
| 2984 | 2953 |
| 2985 // Put the result value into the result register slot. | 2954 // Put the result value into the result register slot. |
| (...skipping 25 matching lines...) Expand all Loading... |
| 3011 | 2980 |
| 3012 | 2981 |
| 3013 void LCodeGen::DoInvokeFunction(LInvokeFunction* instr) { | 2982 void LCodeGen::DoInvokeFunction(LInvokeFunction* instr) { |
| 3014 // The function is required to be in x1. | 2983 // The function is required to be in x1. |
| 3015 ASSERT(ToRegister(instr->function()).is(x1)); | 2984 ASSERT(ToRegister(instr->function()).is(x1)); |
| 3016 ASSERT(instr->HasPointerMap()); | 2985 ASSERT(instr->HasPointerMap()); |
| 3017 | 2986 |
| 3018 Handle<JSFunction> known_function = instr->hydrogen()->known_function(); | 2987 Handle<JSFunction> known_function = instr->hydrogen()->known_function(); |
| 3019 if (known_function.is_null()) { | 2988 if (known_function.is_null()) { |
| 3020 LPointerMap* pointers = instr->pointer_map(); | 2989 LPointerMap* pointers = instr->pointer_map(); |
| 3021 RecordPosition(pointers->position()); | |
| 3022 SafepointGenerator generator(this, pointers, Safepoint::kLazyDeopt); | 2990 SafepointGenerator generator(this, pointers, Safepoint::kLazyDeopt); |
| 3023 ParameterCount count(instr->arity()); | 2991 ParameterCount count(instr->arity()); |
| 3024 __ InvokeFunction(x1, count, CALL_FUNCTION, generator, CALL_AS_METHOD); | 2992 __ InvokeFunction(x1, count, CALL_FUNCTION, generator, CALL_AS_METHOD); |
| 3025 __ Ldr(cp, MemOperand(fp, StandardFrameConstants::kContextOffset)); | 2993 __ Ldr(cp, MemOperand(fp, StandardFrameConstants::kContextOffset)); |
| 3026 } else { | 2994 } else { |
| 3027 CallKnownFunction(known_function, | 2995 CallKnownFunction(known_function, |
| 3028 instr->hydrogen()->formal_parameter_count(), | 2996 instr->hydrogen()->formal_parameter_count(), |
| 3029 instr->arity(), | 2997 instr->arity(), |
| 3030 instr, | 2998 instr, |
| 3031 CALL_AS_METHOD, | 2999 CALL_AS_METHOD, |
| (...skipping 2117 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 5149 DoubleRegister dbl_scratch1 = double_scratch(); | 5117 DoubleRegister dbl_scratch1 = double_scratch(); |
| 5150 | 5118 |
| 5151 Label done; | 5119 Label done; |
| 5152 | 5120 |
| 5153 // Load heap object map. | 5121 // Load heap object map. |
| 5154 __ Ldr(scratch1, FieldMemOperand(input, HeapObject::kMapOffset)); | 5122 __ Ldr(scratch1, FieldMemOperand(input, HeapObject::kMapOffset)); |
| 5155 | 5123 |
| 5156 if (instr->truncating()) { | 5124 if (instr->truncating()) { |
| 5157 Register output = ToRegister(instr->result()); | 5125 Register output = ToRegister(instr->result()); |
| 5158 Register scratch2 = ToRegister(temp2); | 5126 Register scratch2 = ToRegister(temp2); |
| 5159 Label undefined; | 5127 Label check_bools, undefined; |
| 5160 | 5128 |
| 5161 // If it's not a heap number, jump to undefined check. | 5129 // If it's not a heap number, jump to undefined check. |
| 5162 __ JumpIfNotRoot(scratch1, Heap::kHeapNumberMapRootIndex, &undefined); | 5130 __ JumpIfNotRoot(scratch1, Heap::kHeapNumberMapRootIndex, &check_bools); |
| 5163 | 5131 |
| 5164 // A heap number: load value and convert to int32 using truncating function. | 5132 // A heap number: load value and convert to int32 using truncating function. |
| 5165 __ Ldr(dbl_scratch1, FieldMemOperand(input, HeapNumber::kValueOffset)); | 5133 __ Ldr(dbl_scratch1, FieldMemOperand(input, HeapNumber::kValueOffset)); |
| 5166 __ ECMA262ToInt32(output, dbl_scratch1, scratch1, scratch2); | 5134 __ ECMA262ToInt32(output, dbl_scratch1, scratch1, scratch2); |
| 5167 __ B(&done); | 5135 __ B(&done); |
| 5168 | 5136 |
| 5137 __ Bind(&check_bools); |
| 5138 |
| 5139 TODO_UNIMPLEMENTED("LTaggedToI: Truncate booleans to 0 or 1."); |
| 5140 |
| 5169 // Check for undefined. Undefined is converted to zero for truncating | 5141 // Check for undefined. Undefined is converted to zero for truncating |
| 5170 // conversions. | 5142 // conversions. |
| 5171 __ Bind(&undefined); | 5143 __ Bind(&undefined); |
| 5172 | 5144 |
| 5173 DeoptimizeIfNotRoot(input, Heap::kUndefinedValueRootIndex, | 5145 DeoptimizeIfNotRoot(input, Heap::kUndefinedValueRootIndex, |
| 5174 instr->environment()); | 5146 instr->environment()); |
| 5175 __ Mov(output, 0); | 5147 __ Mov(output, 0); |
| 5176 } else { | 5148 } else { |
| 5177 Register output = ToRegister32(instr->result()); | 5149 Register output = ToRegister32(instr->result()); |
| 5178 | 5150 |
| (...skipping 75 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 5254 | 5226 |
| 5255 void LCodeGen::DoRegExpLiteral(LRegExpLiteral* instr) { | 5227 void LCodeGen::DoRegExpLiteral(LRegExpLiteral* instr) { |
| 5256 Label materialized; | 5228 Label materialized; |
| 5257 // Registers will be used as follows: | 5229 // Registers will be used as follows: |
| 5258 // x7 = literals array. | 5230 // x7 = literals array. |
| 5259 // x1 = regexp literal. | 5231 // x1 = regexp literal. |
| 5260 // x0 = regexp literal clone. | 5232 // x0 = regexp literal clone. |
| 5261 // x10-x12 are used as temporaries. | 5233 // x10-x12 are used as temporaries. |
| 5262 int literal_offset = | 5234 int literal_offset = |
| 5263 FixedArray::OffsetOfElementAt(instr->hydrogen()->literal_index()); | 5235 FixedArray::OffsetOfElementAt(instr->hydrogen()->literal_index()); |
| 5264 __ LoadHeapObject(x7, instr->hydrogen()->literals()); | 5236 __ LoadObject(x7, instr->hydrogen()->literals()); |
| 5265 __ Ldr(x1, FieldMemOperand(x7, literal_offset)); | 5237 __ Ldr(x1, FieldMemOperand(x7, literal_offset)); |
| 5266 __ JumpIfNotRoot(x1, Heap::kUndefinedValueRootIndex, &materialized); | 5238 __ JumpIfNotRoot(x1, Heap::kUndefinedValueRootIndex, &materialized); |
| 5267 | 5239 |
| 5268 // Create regexp literal using runtime function | 5240 // Create regexp literal using runtime function |
| 5269 // Result will be in x0. | 5241 // Result will be in x0. |
| 5270 __ Mov(x12, Operand(Smi::FromInt(instr->hydrogen()->literal_index()))); | 5242 __ Mov(x12, Operand(Smi::FromInt(instr->hydrogen()->literal_index()))); |
| 5271 __ Mov(x11, Operand(instr->hydrogen()->pattern())); | 5243 __ Mov(x11, Operand(instr->hydrogen()->pattern())); |
| 5272 __ Mov(x10, Operand(instr->hydrogen()->flags())); | 5244 __ Mov(x10, Operand(instr->hydrogen()->flags())); |
| 5273 __ Push(x7, x12, x11, x10); | 5245 __ Push(x7, x12, x11, x10); |
| 5274 CallRuntime(Runtime::kMaterializeRegExpLiteral, 4, instr); | 5246 CallRuntime(Runtime::kMaterializeRegExpLiteral, 4, instr); |
| (...skipping 59 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 5334 instr->pointer_map(), 0, Safepoint::kNoLazyDeopt); | 5306 instr->pointer_map(), 0, Safepoint::kNoLazyDeopt); |
| 5335 } | 5307 } |
| 5336 __ Bind(¬_applicable); | 5308 __ Bind(¬_applicable); |
| 5337 } | 5309 } |
| 5338 | 5310 |
| 5339 | 5311 |
| 5340 void LCodeGen::DoTrapAllocationMemento(LTrapAllocationMemento* instr) { | 5312 void LCodeGen::DoTrapAllocationMemento(LTrapAllocationMemento* instr) { |
| 5341 Register object = ToRegister(instr->object()); | 5313 Register object = ToRegister(instr->object()); |
| 5342 Register temp1 = ToRegister(instr->temp1()); | 5314 Register temp1 = ToRegister(instr->temp1()); |
| 5343 Register temp2 = ToRegister(instr->temp2()); | 5315 Register temp2 = ToRegister(instr->temp2()); |
| 5344 __ TestJSArrayForAllocationMemento(object, temp1, temp2); | 5316 |
| 5345 DeoptimizeIf(eq, instr->environment()); | 5317 Label no_memento_found; |
| 5318 __ JumpIfJSArrayHasAllocationMemento(object, temp1, temp2, &no_memento_found); |
| 5319 Deoptimize(instr->environment()); |
| 5320 __ Bind(&no_memento_found); |
| 5346 } | 5321 } |
| 5347 | 5322 |
| 5348 | 5323 |
| 5349 void LCodeGen::DoTruncateDoubleToIntOrSmi(LTruncateDoubleToIntOrSmi* instr) { | 5324 void LCodeGen::DoTruncateDoubleToIntOrSmi(LTruncateDoubleToIntOrSmi* instr) { |
| 5350 DoubleRegister input = ToDoubleRegister(instr->value()); | 5325 DoubleRegister input = ToDoubleRegister(instr->value()); |
| 5351 Register result = ToRegister(instr->result()); | 5326 Register result = ToRegister(instr->result()); |
| 5352 __ ECMA262ToInt32(result, input, | 5327 __ ECMA262ToInt32(result, input, |
| 5353 ToRegister(instr->temp1()), | 5328 ToRegister(instr->temp1()), |
| 5354 ToRegister(instr->temp2()), | 5329 ToRegister(instr->temp2()), |
| 5355 instr->tag_result() | 5330 instr->tag_result() |
| (...skipping 95 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 5451 __ B(false_label); | 5426 __ B(false_label); |
| 5452 } | 5427 } |
| 5453 } | 5428 } |
| 5454 | 5429 |
| 5455 | 5430 |
| 5456 void LCodeGen::DoUint32ToDouble(LUint32ToDouble* instr) { | 5431 void LCodeGen::DoUint32ToDouble(LUint32ToDouble* instr) { |
| 5457 __ Ucvtf(ToDoubleRegister(instr->result()), ToRegister32(instr->value())); | 5432 __ Ucvtf(ToDoubleRegister(instr->result()), ToRegister32(instr->value())); |
| 5458 } | 5433 } |
| 5459 | 5434 |
| 5460 | 5435 |
| 5436 void LCodeGen::DoUint32ToSmi(LUint32ToSmi* instr) { |
| 5437 Register value = ToRegister(instr->value()); |
| 5438 Register result = ToRegister(instr->result()); |
| 5439 |
| 5440 if (!instr->hydrogen()->value()->HasRange() || |
| 5441 !instr->hydrogen()->value()->range()->IsInSmiRange()) { |
| 5442 DeoptimizeIfNegative(value.W(), instr->environment()); |
| 5443 } |
| 5444 __ SmiTag(result, value); |
| 5445 } |
| 5446 |
| 5447 |
| 5461 void LCodeGen::DoValueOf(LValueOf* instr) { | 5448 void LCodeGen::DoValueOf(LValueOf* instr) { |
| 5462 Register input = ToRegister(instr->value()); | 5449 Register input = ToRegister(instr->value()); |
| 5463 Register result = ToRegister(instr->result()); | 5450 Register result = ToRegister(instr->result()); |
| 5464 Register scratch = ToRegister(instr->temp()); | 5451 Register scratch = ToRegister(instr->temp()); |
| 5465 Label done; | 5452 Label done; |
| 5466 | 5453 |
| 5467 ASSERT(input.Is(result)); | 5454 ASSERT(input.Is(result)); |
| 5468 | 5455 |
| 5469 if (!instr->hydrogen()->value()->IsHeapObject()) { | 5456 if (!instr->hydrogen()->value()->IsHeapObject()) { |
| 5470 // If the object is a smi return it. | 5457 // If the object is a smi return it. |
| (...skipping 89 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 5560 __ Bind(&out_of_object); | 5547 __ Bind(&out_of_object); |
| 5561 __ Ldr(result, FieldMemOperand(object, JSObject::kPropertiesOffset)); | 5548 __ Ldr(result, FieldMemOperand(object, JSObject::kPropertiesOffset)); |
| 5562 // Index is equal to negated out of object property index plus 1. | 5549 // Index is equal to negated out of object property index plus 1. |
| 5563 __ Sub(result, result, Operand::UntagSmiAndScale(index, kPointerSizeLog2)); | 5550 __ Sub(result, result, Operand::UntagSmiAndScale(index, kPointerSizeLog2)); |
| 5564 __ Ldr(result, FieldMemOperand(result, | 5551 __ Ldr(result, FieldMemOperand(result, |
| 5565 FixedArray::kHeaderSize - kPointerSize)); | 5552 FixedArray::kHeaderSize - kPointerSize)); |
| 5566 __ Bind(&done); | 5553 __ Bind(&done); |
| 5567 } | 5554 } |
| 5568 | 5555 |
| 5569 } } // namespace v8::internal | 5556 } } // namespace v8::internal |
| OLD | NEW |