| OLD | NEW |
| 1 // Copyright 2012 the V8 project authors. All rights reserved. | 1 // Copyright 2012 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 80 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 91 info()->CommitDependencies(code); | 91 info()->CommitDependencies(code); |
| 92 } | 92 } |
| 93 | 93 |
| 94 | 94 |
| 95 void LChunkBuilder::Abort(BailoutReason reason) { | 95 void LChunkBuilder::Abort(BailoutReason reason) { |
| 96 info()->set_bailout_reason(reason); | 96 info()->set_bailout_reason(reason); |
| 97 status_ = ABORTED; | 97 status_ = ABORTED; |
| 98 } | 98 } |
| 99 | 99 |
| 100 | 100 |
| 101 void LCodeGen::Comment(const char* format, ...) { | |
| 102 if (!FLAG_code_comments) return; | |
| 103 char buffer[4 * KB]; | |
| 104 StringBuilder builder(buffer, ARRAY_SIZE(buffer)); | |
| 105 va_list arguments; | |
| 106 va_start(arguments, format); | |
| 107 builder.AddFormattedList(format, arguments); | |
| 108 va_end(arguments); | |
| 109 | |
| 110 // Copy the string before recording it in the assembler to avoid | |
| 111 // issues when the stack allocated buffer goes out of scope. | |
| 112 size_t length = builder.position(); | |
| 113 Vector<char> copy = Vector<char>::New(length + 1); | |
| 114 OS::MemCopy(copy.start(), builder.Finalize(), copy.length()); | |
| 115 masm()->RecordComment(copy.start()); | |
| 116 } | |
| 117 | |
| 118 | |
| 119 bool LCodeGen::GeneratePrologue() { | 101 bool LCodeGen::GeneratePrologue() { |
| 120 ASSERT(is_generating()); | 102 ASSERT(is_generating()); |
| 121 | 103 |
| 122 if (info()->IsOptimizing()) { | 104 if (info()->IsOptimizing()) { |
| 123 ProfileEntryHookStub::MaybeCallEntryHook(masm_); | 105 ProfileEntryHookStub::MaybeCallEntryHook(masm_); |
| 124 | 106 |
| 125 #ifdef DEBUG | 107 #ifdef DEBUG |
| 126 if (strlen(FLAG_stop_at) > 0 && | 108 if (strlen(FLAG_stop_at) > 0 && |
| 127 info_->function()->name()->IsUtf8EqualTo(CStrVector(FLAG_stop_at))) { | 109 info_->function()->name()->IsUtf8EqualTo(CStrVector(FLAG_stop_at))) { |
| 128 __ stop("stop_at"); | 110 __ stop("stop_at"); |
| (...skipping 106 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 235 // Update the write barrier. This clobbers a3 and a0. | 217 // Update the write barrier. This clobbers a3 and a0. |
| 236 __ RecordWriteContextSlot( | 218 __ RecordWriteContextSlot( |
| 237 cp, target.offset(), a0, a3, GetRAState(), kSaveFPRegs); | 219 cp, target.offset(), a0, a3, GetRAState(), kSaveFPRegs); |
| 238 } | 220 } |
| 239 } | 221 } |
| 240 Comment(";;; End allocate local context"); | 222 Comment(";;; End allocate local context"); |
| 241 } | 223 } |
| 242 | 224 |
| 243 // Trace the call. | 225 // Trace the call. |
| 244 if (FLAG_trace && info()->IsOptimizing()) { | 226 if (FLAG_trace && info()->IsOptimizing()) { |
| 227 // We have not executed any compiled code yet, so cp still holds the |
| 228 // incoming context. |
| 245 __ CallRuntime(Runtime::kTraceEnter, 0); | 229 __ CallRuntime(Runtime::kTraceEnter, 0); |
| 246 } | 230 } |
| 247 return !is_aborted(); | 231 return !is_aborted(); |
| 248 } | 232 } |
| 249 | 233 |
| 250 | 234 |
| 251 void LCodeGen::GenerateOsrPrologue() { | 235 void LCodeGen::GenerateOsrPrologue() { |
| 252 // Generate the OSR entry prologue at the first unknown OSR value, or if there | 236 // Generate the OSR entry prologue at the first unknown OSR value, or if there |
| 253 // are none, at the OSR entrypoint instruction. | 237 // are none, at the OSR entrypoint instruction. |
| 254 if (osr_pc_offset_ >= 0) return; | 238 if (osr_pc_offset_ >= 0) return; |
| 255 | 239 |
| 256 osr_pc_offset_ = masm()->pc_offset(); | 240 osr_pc_offset_ = masm()->pc_offset(); |
| 257 | 241 |
| 258 // Adjust the frame size, subsuming the unoptimized frame into the | 242 // Adjust the frame size, subsuming the unoptimized frame into the |
| 259 // optimized frame. | 243 // optimized frame. |
| 260 int slots = GetStackSlotCount() - graph()->osr()->UnoptimizedFrameSlots(); | 244 int slots = GetStackSlotCount() - graph()->osr()->UnoptimizedFrameSlots(); |
| 261 ASSERT(slots >= 0); | 245 ASSERT(slots >= 0); |
| 262 __ Subu(sp, sp, Operand(slots * kPointerSize)); | 246 __ Subu(sp, sp, Operand(slots * kPointerSize)); |
| 263 } | 247 } |
| 264 | 248 |
| 265 | 249 |
| 266 bool LCodeGen::GenerateBody() { | |
| 267 ASSERT(is_generating()); | |
| 268 bool emit_instructions = true; | |
| 269 for (current_instruction_ = 0; | |
| 270 !is_aborted() && current_instruction_ < instructions_->length(); | |
| 271 current_instruction_++) { | |
| 272 LInstruction* instr = instructions_->at(current_instruction_); | |
| 273 | |
| 274 // Don't emit code for basic blocks with a replacement. | |
| 275 if (instr->IsLabel()) { | |
| 276 emit_instructions = !LLabel::cast(instr)->HasReplacement(); | |
| 277 } | |
| 278 if (!emit_instructions) continue; | |
| 279 | |
| 280 if (FLAG_code_comments && instr->HasInterestingComment(this)) { | |
| 281 Comment(";;; <@%d,#%d> %s", | |
| 282 current_instruction_, | |
| 283 instr->hydrogen_value()->id(), | |
| 284 instr->Mnemonic()); | |
| 285 } | |
| 286 | |
| 287 RecordAndUpdatePosition(instr->position()); | |
| 288 | |
| 289 instr->CompileToNative(this); | |
| 290 } | |
| 291 EnsureSpaceForLazyDeopt(); | |
| 292 last_lazy_deopt_pc_ = masm()->pc_offset(); | |
| 293 return !is_aborted(); | |
| 294 } | |
| 295 | |
| 296 | |
| 297 bool LCodeGen::GenerateDeferredCode() { | 250 bool LCodeGen::GenerateDeferredCode() { |
| 298 ASSERT(is_generating()); | 251 ASSERT(is_generating()); |
| 299 if (deferred_.length() > 0) { | 252 if (deferred_.length() > 0) { |
| 300 for (int i = 0; !is_aborted() && i < deferred_.length(); i++) { | 253 for (int i = 0; !is_aborted() && i < deferred_.length(); i++) { |
| 301 LDeferredCode* code = deferred_[i]; | 254 LDeferredCode* code = deferred_[i]; |
| 302 | 255 |
| 303 int pos = instructions_->at(code->instruction_index())->position(); | 256 int pos = instructions_->at(code->instruction_index())->position(); |
| 304 RecordAndUpdatePosition(pos); | 257 RecordAndUpdatePosition(pos); |
| 305 | 258 |
| 306 Comment(";;; <@%d,#%d> " | 259 Comment(";;; <@%d,#%d> " |
| (...skipping 387 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 694 RelocInfo::Mode mode, | 647 RelocInfo::Mode mode, |
| 695 LInstruction* instr) { | 648 LInstruction* instr) { |
| 696 CallCodeGeneric(code, mode, instr, RECORD_SIMPLE_SAFEPOINT); | 649 CallCodeGeneric(code, mode, instr, RECORD_SIMPLE_SAFEPOINT); |
| 697 } | 650 } |
| 698 | 651 |
| 699 | 652 |
| 700 void LCodeGen::CallCodeGeneric(Handle<Code> code, | 653 void LCodeGen::CallCodeGeneric(Handle<Code> code, |
| 701 RelocInfo::Mode mode, | 654 RelocInfo::Mode mode, |
| 702 LInstruction* instr, | 655 LInstruction* instr, |
| 703 SafepointMode safepoint_mode) { | 656 SafepointMode safepoint_mode) { |
| 704 EnsureSpaceForLazyDeopt(); | 657 EnsureSpaceForLazyDeopt(Deoptimizer::patch_size()); |
| 705 ASSERT(instr != NULL); | 658 ASSERT(instr != NULL); |
| 706 LPointerMap* pointers = instr->pointer_map(); | 659 LPointerMap* pointers = instr->pointer_map(); |
| 707 RecordPosition(pointers->position()); | 660 RecordPosition(pointers->position()); |
| 708 __ Call(code, mode); | 661 __ Call(code, mode); |
| 709 RecordSafepointWithLazyDeopt(instr, safepoint_mode); | 662 RecordSafepointWithLazyDeopt(instr, safepoint_mode); |
| 710 } | 663 } |
| 711 | 664 |
| 712 | 665 |
| 713 void LCodeGen::CallRuntime(const Runtime::Function* function, | 666 void LCodeGen::CallRuntime(const Runtime::Function* function, |
| 714 int num_arguments, | 667 int num_arguments, |
| 715 LInstruction* instr) { | 668 LInstruction* instr, |
| 669 SaveFPRegsMode save_doubles) { |
| 716 ASSERT(instr != NULL); | 670 ASSERT(instr != NULL); |
| 717 LPointerMap* pointers = instr->pointer_map(); | 671 LPointerMap* pointers = instr->pointer_map(); |
| 718 ASSERT(pointers != NULL); | 672 ASSERT(pointers != NULL); |
| 719 RecordPosition(pointers->position()); | 673 RecordPosition(pointers->position()); |
| 720 | 674 |
| 721 __ CallRuntime(function, num_arguments); | 675 __ CallRuntime(function, num_arguments, save_doubles); |
| 676 |
| 722 RecordSafepointWithLazyDeopt(instr, RECORD_SIMPLE_SAFEPOINT); | 677 RecordSafepointWithLazyDeopt(instr, RECORD_SIMPLE_SAFEPOINT); |
| 723 } | 678 } |
| 724 | 679 |
| 725 | 680 |
| 681 void LCodeGen::LoadContextFromDeferred(LOperand* context) { |
| 682 if (context->IsRegister()) { |
| 683 __ Move(cp, ToRegister(context)); |
| 684 } else if (context->IsStackSlot()) { |
| 685 __ lw(cp, ToMemOperand(context)); |
| 686 } else if (context->IsConstantOperand()) { |
| 687 HConstant* constant = |
| 688 chunk_->LookupConstant(LConstantOperand::cast(context)); |
| 689 __ LoadObject(cp, Handle<Object>::cast(constant->handle(isolate()))); |
| 690 } else { |
| 691 UNREACHABLE(); |
| 692 } |
| 693 } |
| 694 |
| 695 |
| 726 void LCodeGen::CallRuntimeFromDeferred(Runtime::FunctionId id, | 696 void LCodeGen::CallRuntimeFromDeferred(Runtime::FunctionId id, |
| 727 int argc, | 697 int argc, |
| 728 LInstruction* instr) { | 698 LInstruction* instr, |
| 699 LOperand* context) { |
| 700 LoadContextFromDeferred(context); |
| 729 __ CallRuntimeSaveDoubles(id); | 701 __ CallRuntimeSaveDoubles(id); |
| 730 RecordSafepointWithRegisters( | 702 RecordSafepointWithRegisters( |
| 731 instr->pointer_map(), argc, Safepoint::kNoLazyDeopt); | 703 instr->pointer_map(), argc, Safepoint::kNoLazyDeopt); |
| 732 } | 704 } |
| 733 | 705 |
| 734 | 706 |
| 735 void LCodeGen::RegisterEnvironmentForDeoptimization(LEnvironment* environment, | 707 void LCodeGen::RegisterEnvironmentForDeoptimization(LEnvironment* environment, |
| 736 Safepoint::DeoptMode mode) { | 708 Safepoint::DeoptMode mode) { |
| 737 if (!environment->HasBeenRegistered()) { | 709 if (!environment->HasBeenRegistered()) { |
| 738 // Physical stack frame layout: | 710 // Physical stack frame layout: |
| (...skipping 89 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 828 const Operand& src2) { | 800 const Operand& src2) { |
| 829 Deoptimizer::BailoutType bailout_type = info()->IsStub() | 801 Deoptimizer::BailoutType bailout_type = info()->IsStub() |
| 830 ? Deoptimizer::LAZY | 802 ? Deoptimizer::LAZY |
| 831 : Deoptimizer::EAGER; | 803 : Deoptimizer::EAGER; |
| 832 DeoptimizeIf(condition, environment, bailout_type, src1, src2); | 804 DeoptimizeIf(condition, environment, bailout_type, src1, src2); |
| 833 } | 805 } |
| 834 | 806 |
| 835 | 807 |
| 836 void LCodeGen::RegisterDependentCodeForEmbeddedMaps(Handle<Code> code) { | 808 void LCodeGen::RegisterDependentCodeForEmbeddedMaps(Handle<Code> code) { |
| 837 ZoneList<Handle<Map> > maps(1, zone()); | 809 ZoneList<Handle<Map> > maps(1, zone()); |
| 810 ZoneList<Handle<JSObject> > objects(1, zone()); |
| 838 int mode_mask = RelocInfo::ModeMask(RelocInfo::EMBEDDED_OBJECT); | 811 int mode_mask = RelocInfo::ModeMask(RelocInfo::EMBEDDED_OBJECT); |
| 839 for (RelocIterator it(*code, mode_mask); !it.done(); it.next()) { | 812 for (RelocIterator it(*code, mode_mask); !it.done(); it.next()) { |
| 840 RelocInfo::Mode mode = it.rinfo()->rmode(); | 813 if (Code::IsWeakEmbeddedObject(code->kind(), it.rinfo()->target_object())) { |
| 841 if (mode == RelocInfo::EMBEDDED_OBJECT && | 814 if (it.rinfo()->target_object()->IsMap()) { |
| 842 it.rinfo()->target_object()->IsMap()) { | 815 Handle<Map> map(Map::cast(it.rinfo()->target_object())); |
| 843 Handle<Map> map(Map::cast(it.rinfo()->target_object())); | |
| 844 if (map->CanTransition()) { | |
| 845 maps.Add(map, zone()); | 816 maps.Add(map, zone()); |
| 817 } else if (it.rinfo()->target_object()->IsJSObject()) { |
| 818 Handle<JSObject> object(JSObject::cast(it.rinfo()->target_object())); |
| 819 objects.Add(object, zone()); |
| 846 } | 820 } |
| 847 } | 821 } |
| 848 } | 822 } |
| 849 #ifdef VERIFY_HEAP | 823 #ifdef VERIFY_HEAP |
| 850 // This disables verification of weak embedded maps after full GC. | 824 // This disables verification of weak embedded objects after full GC. |
| 851 // AddDependentCode can cause a GC, which would observe the state where | 825 // AddDependentCode can cause a GC, which would observe the state where |
| 852 // this code is not yet in the depended code lists of the embedded maps. | 826 // this code is not yet in the depended code lists of the embedded maps. |
| 853 NoWeakEmbeddedMapsVerificationScope disable_verification_of_embedded_maps; | 827 NoWeakObjectVerificationScope disable_verification_of_embedded_objects; |
| 854 #endif | 828 #endif |
| 855 for (int i = 0; i < maps.length(); i++) { | 829 for (int i = 0; i < maps.length(); i++) { |
| 856 maps.at(i)->AddDependentCode(DependentCode::kWeaklyEmbeddedGroup, code); | 830 maps.at(i)->AddDependentCode(DependentCode::kWeaklyEmbeddedGroup, code); |
| 857 } | 831 } |
| 832 for (int i = 0; i < objects.length(); i++) { |
| 833 AddWeakObjectToCodeDependency(isolate()->heap(), objects.at(i), code); |
| 834 } |
| 858 } | 835 } |
| 859 | 836 |
| 860 | 837 |
| 861 void LCodeGen::PopulateDeoptimizationData(Handle<Code> code) { | 838 void LCodeGen::PopulateDeoptimizationData(Handle<Code> code) { |
| 862 int length = deoptimizations_.length(); | 839 int length = deoptimizations_.length(); |
| 863 if (length == 0) return; | 840 if (length == 0) return; |
| 864 Handle<DeoptimizationInputData> data = | 841 Handle<DeoptimizationInputData> data = |
| 865 factory()->NewDeoptimizationInputData(length, TENURED); | 842 factory()->NewDeoptimizationInputData(length, TENURED); |
| 866 | 843 |
| 867 Handle<ByteArray> translations = | 844 Handle<ByteArray> translations = |
| (...skipping 75 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 943 Safepoint safepoint = safepoints_.DefineSafepoint(masm(), | 920 Safepoint safepoint = safepoints_.DefineSafepoint(masm(), |
| 944 kind, arguments, deopt_mode); | 921 kind, arguments, deopt_mode); |
| 945 for (int i = 0; i < operands->length(); i++) { | 922 for (int i = 0; i < operands->length(); i++) { |
| 946 LOperand* pointer = operands->at(i); | 923 LOperand* pointer = operands->at(i); |
| 947 if (pointer->IsStackSlot()) { | 924 if (pointer->IsStackSlot()) { |
| 948 safepoint.DefinePointerSlot(pointer->index(), zone()); | 925 safepoint.DefinePointerSlot(pointer->index(), zone()); |
| 949 } else if (pointer->IsRegister() && (kind & Safepoint::kWithRegisters)) { | 926 } else if (pointer->IsRegister() && (kind & Safepoint::kWithRegisters)) { |
| 950 safepoint.DefinePointerRegister(ToRegister(pointer), zone()); | 927 safepoint.DefinePointerRegister(ToRegister(pointer), zone()); |
| 951 } | 928 } |
| 952 } | 929 } |
| 953 if (kind & Safepoint::kWithRegisters) { | |
| 954 // Register cp always contains a pointer to the context. | |
| 955 safepoint.DefinePointerRegister(cp, zone()); | |
| 956 } | |
| 957 } | 930 } |
| 958 | 931 |
| 959 | 932 |
| 960 void LCodeGen::RecordSafepoint(LPointerMap* pointers, | 933 void LCodeGen::RecordSafepoint(LPointerMap* pointers, |
| 961 Safepoint::DeoptMode deopt_mode) { | 934 Safepoint::DeoptMode deopt_mode) { |
| 962 RecordSafepoint(pointers, Safepoint::kSimple, 0, deopt_mode); | 935 RecordSafepoint(pointers, Safepoint::kSimple, 0, deopt_mode); |
| 963 } | 936 } |
| 964 | 937 |
| 965 | 938 |
| 966 void LCodeGen::RecordSafepoint(Safepoint::DeoptMode deopt_mode) { | 939 void LCodeGen::RecordSafepoint(Safepoint::DeoptMode deopt_mode) { |
| (...skipping 72 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1039 DoGap(instr); | 1012 DoGap(instr); |
| 1040 } | 1013 } |
| 1041 | 1014 |
| 1042 | 1015 |
| 1043 void LCodeGen::DoParameter(LParameter* instr) { | 1016 void LCodeGen::DoParameter(LParameter* instr) { |
| 1044 // Nothing to do. | 1017 // Nothing to do. |
| 1045 } | 1018 } |
| 1046 | 1019 |
| 1047 | 1020 |
| 1048 void LCodeGen::DoCallStub(LCallStub* instr) { | 1021 void LCodeGen::DoCallStub(LCallStub* instr) { |
| 1022 ASSERT(ToRegister(instr->context()).is(cp)); |
| 1049 ASSERT(ToRegister(instr->result()).is(v0)); | 1023 ASSERT(ToRegister(instr->result()).is(v0)); |
| 1050 switch (instr->hydrogen()->major_key()) { | 1024 switch (instr->hydrogen()->major_key()) { |
| 1051 case CodeStub::RegExpConstructResult: { | 1025 case CodeStub::RegExpConstructResult: { |
| 1052 RegExpConstructResultStub stub; | 1026 RegExpConstructResultStub stub; |
| 1053 CallCode(stub.GetCode(isolate()), RelocInfo::CODE_TARGET, instr); | 1027 CallCode(stub.GetCode(isolate()), RelocInfo::CODE_TARGET, instr); |
| 1054 break; | 1028 break; |
| 1055 } | 1029 } |
| 1056 case CodeStub::RegExpExec: { | 1030 case CodeStub::RegExpExec: { |
| 1057 RegExpExecStub stub; | 1031 RegExpExecStub stub; |
| 1058 CallCode(stub.GetCode(isolate()), RelocInfo::CODE_TARGET, instr); | 1032 CallCode(stub.GetCode(isolate()), RelocInfo::CODE_TARGET, instr); |
| (...skipping 337 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1396 } | 1370 } |
| 1397 | 1371 |
| 1398 | 1372 |
| 1399 void LCodeGen::DoMulI(LMulI* instr) { | 1373 void LCodeGen::DoMulI(LMulI* instr) { |
| 1400 Register scratch = scratch0(); | 1374 Register scratch = scratch0(); |
| 1401 Register result = ToRegister(instr->result()); | 1375 Register result = ToRegister(instr->result()); |
| 1402 // Note that result may alias left. | 1376 // Note that result may alias left. |
| 1403 Register left = ToRegister(instr->left()); | 1377 Register left = ToRegister(instr->left()); |
| 1404 LOperand* right_op = instr->right(); | 1378 LOperand* right_op = instr->right(); |
| 1405 | 1379 |
| 1406 bool can_overflow = instr->hydrogen()->CheckFlag(HValue::kCanOverflow); | |
| 1407 bool bailout_on_minus_zero = | 1380 bool bailout_on_minus_zero = |
| 1408 instr->hydrogen()->CheckFlag(HValue::kBailoutOnMinusZero); | 1381 instr->hydrogen()->CheckFlag(HValue::kBailoutOnMinusZero); |
| 1382 bool overflow = instr->hydrogen()->CheckFlag(HValue::kCanOverflow); |
| 1409 | 1383 |
| 1410 if (right_op->IsConstantOperand() && !can_overflow) { | 1384 if (right_op->IsConstantOperand()) { |
| 1411 int32_t constant = ToInteger32(LConstantOperand::cast(right_op)); | 1385 int32_t constant = ToInteger32(LConstantOperand::cast(right_op)); |
| 1412 | 1386 |
| 1413 if (bailout_on_minus_zero && (constant < 0)) { | 1387 if (bailout_on_minus_zero && (constant < 0)) { |
| 1414 // The case of a null constant will be handled separately. | 1388 // The case of a null constant will be handled separately. |
| 1415 // If constant is negative and left is null, the result should be -0. | 1389 // If constant is negative and left is null, the result should be -0. |
| 1416 DeoptimizeIf(eq, instr->environment(), left, Operand(zero_reg)); | 1390 DeoptimizeIf(eq, instr->environment(), left, Operand(zero_reg)); |
| 1417 } | 1391 } |
| 1418 | 1392 |
| 1419 switch (constant) { | 1393 switch (constant) { |
| 1420 case -1: | 1394 case -1: |
| 1421 __ Subu(result, zero_reg, left); | 1395 if (overflow) { |
| 1396 __ SubuAndCheckForOverflow(result, zero_reg, left, scratch); |
| 1397 DeoptimizeIf(lt, instr->environment(), scratch, Operand(zero_reg)); |
| 1398 } else { |
| 1399 __ Subu(result, zero_reg, left); |
| 1400 } |
| 1422 break; | 1401 break; |
| 1423 case 0: | 1402 case 0: |
| 1424 if (bailout_on_minus_zero) { | 1403 if (bailout_on_minus_zero) { |
| 1425 // If left is strictly negative and the constant is null, the | 1404 // If left is strictly negative and the constant is null, the |
| 1426 // result is -0. Deoptimize if required, otherwise return 0. | 1405 // result is -0. Deoptimize if required, otherwise return 0. |
| 1427 DeoptimizeIf(lt, instr->environment(), left, Operand(zero_reg)); | 1406 DeoptimizeIf(lt, instr->environment(), left, Operand(zero_reg)); |
| 1428 } | 1407 } |
| 1429 __ mov(result, zero_reg); | 1408 __ mov(result, zero_reg); |
| 1430 break; | 1409 break; |
| 1431 case 1: | 1410 case 1: |
| 1432 // Nothing to do. | 1411 // Nothing to do. |
| 1433 __ Move(result, left); | 1412 __ Move(result, left); |
| 1434 break; | 1413 break; |
| 1435 default: | 1414 default: |
| 1436 // Multiplying by powers of two and powers of two plus or minus | 1415 // Multiplying by powers of two and powers of two plus or minus |
| 1437 // one can be done faster with shifted operands. | 1416 // one can be done faster with shifted operands. |
| 1438 // For other constants we emit standard code. | 1417 // For other constants we emit standard code. |
| 1439 int32_t mask = constant >> 31; | 1418 int32_t mask = constant >> 31; |
| 1440 uint32_t constant_abs = (constant + mask) ^ mask; | 1419 uint32_t constant_abs = (constant + mask) ^ mask; |
| 1441 | 1420 |
| 1442 if (IsPowerOf2(constant_abs) || | 1421 if (IsPowerOf2(constant_abs)) { |
| 1443 IsPowerOf2(constant_abs - 1) || | 1422 int32_t shift = WhichPowerOf2(constant_abs); |
| 1444 IsPowerOf2(constant_abs + 1)) { | 1423 __ sll(result, left, shift); |
| 1445 if (IsPowerOf2(constant_abs)) { | 1424 // Correct the sign of the result if the constant is negative. |
| 1446 int32_t shift = WhichPowerOf2(constant_abs); | 1425 if (constant < 0) __ Subu(result, zero_reg, result); |
| 1447 __ sll(result, left, shift); | 1426 } else if (IsPowerOf2(constant_abs - 1)) { |
| 1448 } else if (IsPowerOf2(constant_abs - 1)) { | 1427 int32_t shift = WhichPowerOf2(constant_abs - 1); |
| 1449 int32_t shift = WhichPowerOf2(constant_abs - 1); | 1428 __ sll(scratch, left, shift); |
| 1450 __ sll(scratch, left, shift); | 1429 __ Addu(result, scratch, left); |
| 1451 __ Addu(result, scratch, left); | 1430 // Correct the sign of the result if the constant is negative. |
| 1452 } else if (IsPowerOf2(constant_abs + 1)) { | 1431 if (constant < 0) __ Subu(result, zero_reg, result); |
| 1453 int32_t shift = WhichPowerOf2(constant_abs + 1); | 1432 } else if (IsPowerOf2(constant_abs + 1)) { |
| 1454 __ sll(scratch, left, shift); | 1433 int32_t shift = WhichPowerOf2(constant_abs + 1); |
| 1455 __ Subu(result, scratch, left); | 1434 __ sll(scratch, left, shift); |
| 1456 } | 1435 __ Subu(result, scratch, left); |
| 1457 | 1436 // Correct the sign of the result if the constant is negative. |
| 1458 // Correct the sign of the result is the constant is negative. | 1437 if (constant < 0) __ Subu(result, zero_reg, result); |
| 1459 if (constant < 0) { | |
| 1460 __ Subu(result, zero_reg, result); | |
| 1461 } | |
| 1462 | |
| 1463 } else { | 1438 } else { |
| 1464 // Generate standard code. | 1439 // Generate standard code. |
| 1465 __ li(at, constant); | 1440 __ li(at, constant); |
| 1466 __ Mul(result, left, at); | 1441 __ Mul(result, left, at); |
| 1467 } | 1442 } |
| 1468 } | 1443 } |
| 1469 | 1444 |
| 1470 } else { | 1445 } else { |
| 1471 Register right = EmitLoadRegister(right_op, scratch); | 1446 ASSERT(right_op->IsRegister()); |
| 1472 if (bailout_on_minus_zero) { | 1447 Register right = ToRegister(right_op); |
| 1473 __ Or(ToRegister(instr->temp()), left, right); | |
| 1474 } | |
| 1475 | 1448 |
| 1476 if (can_overflow) { | 1449 if (overflow) { |
| 1477 // hi:lo = left * right. | 1450 // hi:lo = left * right. |
| 1478 if (instr->hydrogen()->representation().IsSmi()) { | 1451 if (instr->hydrogen()->representation().IsSmi()) { |
| 1479 __ SmiUntag(result, left); | 1452 __ SmiUntag(result, left); |
| 1480 __ mult(result, right); | 1453 __ mult(result, right); |
| 1481 __ mfhi(scratch); | 1454 __ mfhi(scratch); |
| 1482 __ mflo(result); | 1455 __ mflo(result); |
| 1483 } else { | 1456 } else { |
| 1484 __ mult(left, right); | 1457 __ mult(left, right); |
| 1485 __ mfhi(scratch); | 1458 __ mfhi(scratch); |
| 1486 __ mflo(result); | 1459 __ mflo(result); |
| 1487 } | 1460 } |
| 1488 __ sra(at, result, 31); | 1461 __ sra(at, result, 31); |
| 1489 DeoptimizeIf(ne, instr->environment(), scratch, Operand(at)); | 1462 DeoptimizeIf(ne, instr->environment(), scratch, Operand(at)); |
| 1490 } else { | 1463 } else { |
| 1491 if (instr->hydrogen()->representation().IsSmi()) { | 1464 if (instr->hydrogen()->representation().IsSmi()) { |
| 1492 __ SmiUntag(result, left); | 1465 __ SmiUntag(result, left); |
| 1493 __ Mul(result, result, right); | 1466 __ Mul(result, result, right); |
| 1494 } else { | 1467 } else { |
| 1495 __ Mul(result, left, right); | 1468 __ Mul(result, left, right); |
| 1496 } | 1469 } |
| 1497 } | 1470 } |
| 1498 | 1471 |
| 1499 if (bailout_on_minus_zero) { | 1472 if (bailout_on_minus_zero) { |
| 1500 // Bail out if the result is supposed to be negative zero. | |
| 1501 Label done; | 1473 Label done; |
| 1502 __ Branch(&done, ne, result, Operand(zero_reg)); | 1474 __ Xor(at, left, right); |
| 1503 DeoptimizeIf(lt, | 1475 __ Branch(&done, ge, at, Operand(zero_reg)); |
| 1476 // Bail out if the result is minus zero. |
| 1477 DeoptimizeIf(eq, |
| 1504 instr->environment(), | 1478 instr->environment(), |
| 1505 ToRegister(instr->temp()), | 1479 result, |
| 1506 Operand(zero_reg)); | 1480 Operand(zero_reg)); |
| 1507 __ bind(&done); | 1481 __ bind(&done); |
| 1508 } | 1482 } |
| 1509 } | 1483 } |
| 1510 } | 1484 } |
| 1511 | 1485 |
| 1512 | 1486 |
| 1513 void LCodeGen::DoBitI(LBitI* instr) { | 1487 void LCodeGen::DoBitI(LBitI* instr) { |
| 1514 LOperand* left_op = instr->left(); | 1488 LOperand* left_op = instr->left(); |
| 1515 LOperand* right_op = instr->right(); | 1489 LOperand* right_op = instr->right(); |
| (...skipping 305 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1821 __ Addu(scratch, string, scratch); | 1795 __ Addu(scratch, string, scratch); |
| 1822 __ sh(value, FieldMemOperand(scratch, SeqString::kHeaderSize)); | 1796 __ sh(value, FieldMemOperand(scratch, SeqString::kHeaderSize)); |
| 1823 } | 1797 } |
| 1824 } | 1798 } |
| 1825 } | 1799 } |
| 1826 | 1800 |
| 1827 | 1801 |
| 1828 void LCodeGen::DoThrow(LThrow* instr) { | 1802 void LCodeGen::DoThrow(LThrow* instr) { |
| 1829 Register input_reg = EmitLoadRegister(instr->value(), at); | 1803 Register input_reg = EmitLoadRegister(instr->value(), at); |
| 1830 __ push(input_reg); | 1804 __ push(input_reg); |
| 1805 ASSERT(ToRegister(instr->context()).is(cp)); |
| 1831 CallRuntime(Runtime::kThrow, 1, instr); | 1806 CallRuntime(Runtime::kThrow, 1, instr); |
| 1832 | 1807 |
| 1833 if (FLAG_debug_code) { | 1808 if (FLAG_debug_code) { |
| 1834 __ stop("Unreachable code."); | 1809 __ stop("Unreachable code."); |
| 1835 } | 1810 } |
| 1836 } | 1811 } |
| 1837 | 1812 |
| 1838 | 1813 |
| 1839 void LCodeGen::DoAddI(LAddI* instr) { | 1814 void LCodeGen::DoAddI(LAddI* instr) { |
| 1840 LOperand* left = instr->left(); | 1815 LOperand* left = instr->left(); |
| (...skipping 131 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1972 break; | 1947 break; |
| 1973 } | 1948 } |
| 1974 default: | 1949 default: |
| 1975 UNREACHABLE(); | 1950 UNREACHABLE(); |
| 1976 break; | 1951 break; |
| 1977 } | 1952 } |
| 1978 } | 1953 } |
| 1979 | 1954 |
| 1980 | 1955 |
| 1981 void LCodeGen::DoArithmeticT(LArithmeticT* instr) { | 1956 void LCodeGen::DoArithmeticT(LArithmeticT* instr) { |
| 1957 ASSERT(ToRegister(instr->context()).is(cp)); |
| 1982 ASSERT(ToRegister(instr->left()).is(a1)); | 1958 ASSERT(ToRegister(instr->left()).is(a1)); |
| 1983 ASSERT(ToRegister(instr->right()).is(a0)); | 1959 ASSERT(ToRegister(instr->right()).is(a0)); |
| 1984 ASSERT(ToRegister(instr->result()).is(v0)); | 1960 ASSERT(ToRegister(instr->result()).is(v0)); |
| 1985 | 1961 |
| 1986 BinaryOpStub stub(instr->op(), NO_OVERWRITE); | 1962 BinaryOpStub stub(instr->op(), NO_OVERWRITE); |
| 1987 CallCode(stub.GetCode(isolate()), RelocInfo::CODE_TARGET, instr); | 1963 CallCode(stub.GetCode(isolate()), RelocInfo::CODE_TARGET, instr); |
| 1988 // Other arch use a nop here, to signal that there is no inlined | 1964 // Other arch use a nop here, to signal that there is no inlined |
| 1989 // patchable code. Mips does not need the nop, since our marker | 1965 // patchable code. Mips does not need the nop, since our marker |
| 1990 // instruction (andi zero_reg) will never be used in normal code. | 1966 // instruction (andi zero_reg) will never be used in normal code. |
| 1991 } | 1967 } |
| 1992 | 1968 |
| 1993 | 1969 |
| 1994 int LCodeGen::GetNextEmittedBlock() const { | |
| 1995 for (int i = current_block_ + 1; i < graph()->blocks()->length(); ++i) { | |
| 1996 if (!chunk_->GetLabel(i)->HasReplacement()) return i; | |
| 1997 } | |
| 1998 return -1; | |
| 1999 } | |
| 2000 | |
| 2001 template<class InstrType> | 1970 template<class InstrType> |
| 2002 void LCodeGen::EmitBranch(InstrType instr, | 1971 void LCodeGen::EmitBranch(InstrType instr, |
| 2003 Condition condition, | 1972 Condition condition, |
| 2004 Register src1, | 1973 Register src1, |
| 2005 const Operand& src2) { | 1974 const Operand& src2) { |
| 2006 int left_block = instr->TrueDestination(chunk_); | 1975 int left_block = instr->TrueDestination(chunk_); |
| 2007 int right_block = instr->FalseDestination(chunk_); | 1976 int right_block = instr->FalseDestination(chunk_); |
| 2008 | 1977 |
| 2009 int next_block = GetNextEmittedBlock(); | 1978 int next_block = GetNextEmittedBlock(); |
| 2010 if (right_block == left_block || condition == al) { | 1979 if (right_block == left_block || condition == al) { |
| (...skipping 407 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2418 case Token::GTE: | 2387 case Token::GTE: |
| 2419 return ge; | 2388 return ge; |
| 2420 default: | 2389 default: |
| 2421 UNREACHABLE(); | 2390 UNREACHABLE(); |
| 2422 return kNoCondition; | 2391 return kNoCondition; |
| 2423 } | 2392 } |
| 2424 } | 2393 } |
| 2425 | 2394 |
| 2426 | 2395 |
| 2427 void LCodeGen::DoStringCompareAndBranch(LStringCompareAndBranch* instr) { | 2396 void LCodeGen::DoStringCompareAndBranch(LStringCompareAndBranch* instr) { |
| 2397 ASSERT(ToRegister(instr->context()).is(cp)); |
| 2428 Token::Value op = instr->op(); | 2398 Token::Value op = instr->op(); |
| 2429 | 2399 |
| 2430 Handle<Code> ic = CompareIC::GetUninitialized(isolate(), op); | 2400 Handle<Code> ic = CompareIC::GetUninitialized(isolate(), op); |
| 2431 CallCode(ic, RelocInfo::CODE_TARGET, instr); | 2401 CallCode(ic, RelocInfo::CODE_TARGET, instr); |
| 2432 | 2402 |
| 2433 Condition condition = ComputeCompareCondition(op); | 2403 Condition condition = ComputeCompareCondition(op); |
| 2434 | 2404 |
| 2435 EmitBranch(instr, condition, v0, Operand(zero_reg)); | 2405 EmitBranch(instr, condition, v0, Operand(zero_reg)); |
| 2436 } | 2406 } |
| 2437 | 2407 |
| (...skipping 139 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2577 void LCodeGen::DoCmpMapAndBranch(LCmpMapAndBranch* instr) { | 2547 void LCodeGen::DoCmpMapAndBranch(LCmpMapAndBranch* instr) { |
| 2578 Register reg = ToRegister(instr->value()); | 2548 Register reg = ToRegister(instr->value()); |
| 2579 Register temp = ToRegister(instr->temp()); | 2549 Register temp = ToRegister(instr->temp()); |
| 2580 | 2550 |
| 2581 __ lw(temp, FieldMemOperand(reg, HeapObject::kMapOffset)); | 2551 __ lw(temp, FieldMemOperand(reg, HeapObject::kMapOffset)); |
| 2582 EmitBranch(instr, eq, temp, Operand(instr->map())); | 2552 EmitBranch(instr, eq, temp, Operand(instr->map())); |
| 2583 } | 2553 } |
| 2584 | 2554 |
| 2585 | 2555 |
| 2586 void LCodeGen::DoInstanceOf(LInstanceOf* instr) { | 2556 void LCodeGen::DoInstanceOf(LInstanceOf* instr) { |
| 2557 ASSERT(ToRegister(instr->context()).is(cp)); |
| 2587 Label true_label, done; | 2558 Label true_label, done; |
| 2588 ASSERT(ToRegister(instr->left()).is(a0)); // Object is in a0. | 2559 ASSERT(ToRegister(instr->left()).is(a0)); // Object is in a0. |
| 2589 ASSERT(ToRegister(instr->right()).is(a1)); // Function is in a1. | 2560 ASSERT(ToRegister(instr->right()).is(a1)); // Function is in a1. |
| 2590 Register result = ToRegister(instr->result()); | 2561 Register result = ToRegister(instr->result()); |
| 2591 ASSERT(result.is(v0)); | 2562 ASSERT(result.is(v0)); |
| 2592 | 2563 |
| 2593 InstanceofStub stub(InstanceofStub::kArgsInRegisters); | 2564 InstanceofStub stub(InstanceofStub::kArgsInRegisters); |
| 2594 CallCode(stub.GetCode(isolate()), RelocInfo::CODE_TARGET, instr); | 2565 CallCode(stub.GetCode(isolate()), RelocInfo::CODE_TARGET, instr); |
| 2595 | 2566 |
| 2596 __ Branch(&true_label, eq, result, Operand(zero_reg)); | 2567 __ Branch(&true_label, eq, result, Operand(zero_reg)); |
| (...skipping 90 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2687 InstanceofStub::Flags flags = InstanceofStub::kNoFlags; | 2658 InstanceofStub::Flags flags = InstanceofStub::kNoFlags; |
| 2688 flags = static_cast<InstanceofStub::Flags>( | 2659 flags = static_cast<InstanceofStub::Flags>( |
| 2689 flags | InstanceofStub::kArgsInRegisters); | 2660 flags | InstanceofStub::kArgsInRegisters); |
| 2690 flags = static_cast<InstanceofStub::Flags>( | 2661 flags = static_cast<InstanceofStub::Flags>( |
| 2691 flags | InstanceofStub::kCallSiteInlineCheck); | 2662 flags | InstanceofStub::kCallSiteInlineCheck); |
| 2692 flags = static_cast<InstanceofStub::Flags>( | 2663 flags = static_cast<InstanceofStub::Flags>( |
| 2693 flags | InstanceofStub::kReturnTrueFalseObject); | 2664 flags | InstanceofStub::kReturnTrueFalseObject); |
| 2694 InstanceofStub stub(flags); | 2665 InstanceofStub stub(flags); |
| 2695 | 2666 |
| 2696 PushSafepointRegistersScope scope(this, Safepoint::kWithRegisters); | 2667 PushSafepointRegistersScope scope(this, Safepoint::kWithRegisters); |
| 2668 LoadContextFromDeferred(instr->context()); |
| 2697 | 2669 |
| 2698 // Get the temp register reserved by the instruction. This needs to be t0 as | 2670 // Get the temp register reserved by the instruction. This needs to be t0 as |
| 2699 // its slot of the pushing of safepoint registers is used to communicate the | 2671 // its slot of the pushing of safepoint registers is used to communicate the |
| 2700 // offset to the location of the map check. | 2672 // offset to the location of the map check. |
| 2701 Register temp = ToRegister(instr->temp()); | 2673 Register temp = ToRegister(instr->temp()); |
| 2702 ASSERT(temp.is(t0)); | 2674 ASSERT(temp.is(t0)); |
| 2703 __ LoadHeapObject(InstanceofStub::right(), instr->function()); | 2675 __ LoadHeapObject(InstanceofStub::right(), instr->function()); |
| 2704 static const int kAdditionalDelta = 7; | 2676 static const int kAdditionalDelta = 7; |
| 2705 int delta = masm_->InstructionsGeneratedSince(map_check) + kAdditionalDelta; | 2677 int delta = masm_->InstructionsGeneratedSince(map_check) + kAdditionalDelta; |
| 2706 Label before_push_delta; | 2678 Label before_push_delta; |
| (...skipping 17 matching lines...) Expand all Loading... |
| 2724 | 2696 |
| 2725 void LCodeGen::DoInstanceSize(LInstanceSize* instr) { | 2697 void LCodeGen::DoInstanceSize(LInstanceSize* instr) { |
| 2726 Register object = ToRegister(instr->object()); | 2698 Register object = ToRegister(instr->object()); |
| 2727 Register result = ToRegister(instr->result()); | 2699 Register result = ToRegister(instr->result()); |
| 2728 __ lw(result, FieldMemOperand(object, HeapObject::kMapOffset)); | 2700 __ lw(result, FieldMemOperand(object, HeapObject::kMapOffset)); |
| 2729 __ lbu(result, FieldMemOperand(result, Map::kInstanceSizeOffset)); | 2701 __ lbu(result, FieldMemOperand(result, Map::kInstanceSizeOffset)); |
| 2730 } | 2702 } |
| 2731 | 2703 |
| 2732 | 2704 |
| 2733 void LCodeGen::DoCmpT(LCmpT* instr) { | 2705 void LCodeGen::DoCmpT(LCmpT* instr) { |
| 2706 ASSERT(ToRegister(instr->context()).is(cp)); |
| 2734 Token::Value op = instr->op(); | 2707 Token::Value op = instr->op(); |
| 2735 | 2708 |
| 2736 Handle<Code> ic = CompareIC::GetUninitialized(isolate(), op); | 2709 Handle<Code> ic = CompareIC::GetUninitialized(isolate(), op); |
| 2737 CallCode(ic, RelocInfo::CODE_TARGET, instr); | 2710 CallCode(ic, RelocInfo::CODE_TARGET, instr); |
| 2738 // On MIPS there is no need for a "no inlined smi code" marker (nop). | 2711 // On MIPS there is no need for a "no inlined smi code" marker (nop). |
| 2739 | 2712 |
| 2740 Condition condition = ComputeCompareCondition(op); | 2713 Condition condition = ComputeCompareCondition(op); |
| 2741 // A minor optimization that relies on LoadRoot always emitting one | 2714 // A minor optimization that relies on LoadRoot always emitting one |
| 2742 // instruction. | 2715 // instruction. |
| 2743 Assembler::BlockTrampolinePoolScope block_trampoline_pool(masm()); | 2716 Assembler::BlockTrampolinePoolScope block_trampoline_pool(masm()); |
| 2744 Label done, check; | 2717 Label done, check; |
| 2745 __ Branch(USE_DELAY_SLOT, &done, condition, v0, Operand(zero_reg)); | 2718 __ Branch(USE_DELAY_SLOT, &done, condition, v0, Operand(zero_reg)); |
| 2746 __ bind(&check); | 2719 __ bind(&check); |
| 2747 __ LoadRoot(ToRegister(instr->result()), Heap::kTrueValueRootIndex); | 2720 __ LoadRoot(ToRegister(instr->result()), Heap::kTrueValueRootIndex); |
| 2748 ASSERT_EQ(1, masm()->InstructionsGeneratedSince(&check)); | 2721 ASSERT_EQ(1, masm()->InstructionsGeneratedSince(&check)); |
| 2749 __ LoadRoot(ToRegister(instr->result()), Heap::kFalseValueRootIndex); | 2722 __ LoadRoot(ToRegister(instr->result()), Heap::kFalseValueRootIndex); |
| 2750 __ bind(&done); | 2723 __ bind(&done); |
| 2751 } | 2724 } |
| 2752 | 2725 |
| 2753 | 2726 |
| 2754 void LCodeGen::DoReturn(LReturn* instr) { | 2727 void LCodeGen::DoReturn(LReturn* instr) { |
| 2755 if (FLAG_trace && info()->IsOptimizing()) { | 2728 if (FLAG_trace && info()->IsOptimizing()) { |
| 2756 // Push the return value on the stack as the parameter. | 2729 // Push the return value on the stack as the parameter. |
| 2757 // Runtime::TraceExit returns its parameter in v0. | 2730 // Runtime::TraceExit returns its parameter in v0. We're leaving the code |
| 2731 // managed by the register allocator and tearing down the frame, it's |
| 2732 // safe to write to the context register. |
| 2758 __ push(v0); | 2733 __ push(v0); |
| 2734 __ lw(cp, MemOperand(fp, StandardFrameConstants::kContextOffset)); |
| 2759 __ CallRuntime(Runtime::kTraceExit, 1); | 2735 __ CallRuntime(Runtime::kTraceExit, 1); |
| 2760 } | 2736 } |
| 2761 if (info()->saves_caller_doubles()) { | 2737 if (info()->saves_caller_doubles()) { |
| 2762 ASSERT(NeedsEagerFrame()); | 2738 ASSERT(NeedsEagerFrame()); |
| 2763 BitVector* doubles = chunk()->allocated_double_registers(); | 2739 BitVector* doubles = chunk()->allocated_double_registers(); |
| 2764 BitVector::Iterator save_iterator(doubles); | 2740 BitVector::Iterator save_iterator(doubles); |
| 2765 int count = 0; | 2741 int count = 0; |
| 2766 while (!save_iterator.Done()) { | 2742 while (!save_iterator.Done()) { |
| 2767 __ ldc1(DoubleRegister::FromAllocationIndex(save_iterator.Current()), | 2743 __ ldc1(DoubleRegister::FromAllocationIndex(save_iterator.Current()), |
| 2768 MemOperand(sp, count * kDoubleSize)); | 2744 MemOperand(sp, count * kDoubleSize)); |
| (...skipping 34 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2803 __ li(at, Operand(Handle<Object>(instr->hydrogen()->cell().handle()))); | 2779 __ li(at, Operand(Handle<Object>(instr->hydrogen()->cell().handle()))); |
| 2804 __ lw(result, FieldMemOperand(at, Cell::kValueOffset)); | 2780 __ lw(result, FieldMemOperand(at, Cell::kValueOffset)); |
| 2805 if (instr->hydrogen()->RequiresHoleCheck()) { | 2781 if (instr->hydrogen()->RequiresHoleCheck()) { |
| 2806 __ LoadRoot(at, Heap::kTheHoleValueRootIndex); | 2782 __ LoadRoot(at, Heap::kTheHoleValueRootIndex); |
| 2807 DeoptimizeIf(eq, instr->environment(), result, Operand(at)); | 2783 DeoptimizeIf(eq, instr->environment(), result, Operand(at)); |
| 2808 } | 2784 } |
| 2809 } | 2785 } |
| 2810 | 2786 |
| 2811 | 2787 |
| 2812 void LCodeGen::DoLoadGlobalGeneric(LLoadGlobalGeneric* instr) { | 2788 void LCodeGen::DoLoadGlobalGeneric(LLoadGlobalGeneric* instr) { |
| 2789 ASSERT(ToRegister(instr->context()).is(cp)); |
| 2813 ASSERT(ToRegister(instr->global_object()).is(a0)); | 2790 ASSERT(ToRegister(instr->global_object()).is(a0)); |
| 2814 ASSERT(ToRegister(instr->result()).is(v0)); | 2791 ASSERT(ToRegister(instr->result()).is(v0)); |
| 2815 | 2792 |
| 2816 __ li(a2, Operand(instr->name())); | 2793 __ li(a2, Operand(instr->name())); |
| 2817 RelocInfo::Mode mode = instr->for_typeof() ? RelocInfo::CODE_TARGET | 2794 RelocInfo::Mode mode = instr->for_typeof() ? RelocInfo::CODE_TARGET |
| 2818 : RelocInfo::CODE_TARGET_CONTEXT; | 2795 : RelocInfo::CODE_TARGET_CONTEXT; |
| 2819 Handle<Code> ic = isolate()->builtins()->LoadIC_Initialize(); | 2796 Handle<Code> ic = isolate()->builtins()->LoadIC_Initialize(); |
| 2820 CallCode(ic, mode, instr); | 2797 CallCode(ic, mode, instr); |
| 2821 } | 2798 } |
| 2822 | 2799 |
| (...skipping 17 matching lines...) Expand all Loading... |
| 2840 DeoptimizeIf(eq, instr->environment(), payload, Operand(at)); | 2817 DeoptimizeIf(eq, instr->environment(), payload, Operand(at)); |
| 2841 } | 2818 } |
| 2842 | 2819 |
| 2843 // Store the value. | 2820 // Store the value. |
| 2844 __ sw(value, FieldMemOperand(cell, Cell::kValueOffset)); | 2821 __ sw(value, FieldMemOperand(cell, Cell::kValueOffset)); |
| 2845 // Cells are always rescanned, so no write barrier here. | 2822 // Cells are always rescanned, so no write barrier here. |
| 2846 } | 2823 } |
| 2847 | 2824 |
| 2848 | 2825 |
| 2849 void LCodeGen::DoStoreGlobalGeneric(LStoreGlobalGeneric* instr) { | 2826 void LCodeGen::DoStoreGlobalGeneric(LStoreGlobalGeneric* instr) { |
| 2827 ASSERT(ToRegister(instr->context()).is(cp)); |
| 2850 ASSERT(ToRegister(instr->global_object()).is(a1)); | 2828 ASSERT(ToRegister(instr->global_object()).is(a1)); |
| 2851 ASSERT(ToRegister(instr->value()).is(a0)); | 2829 ASSERT(ToRegister(instr->value()).is(a0)); |
| 2852 | 2830 |
| 2853 __ li(a2, Operand(instr->name())); | 2831 __ li(a2, Operand(instr->name())); |
| 2854 Handle<Code> ic = (instr->strict_mode_flag() == kStrictMode) | 2832 Handle<Code> ic = (instr->strict_mode_flag() == kStrictMode) |
| 2855 ? isolate()->builtins()->StoreIC_Initialize_Strict() | 2833 ? isolate()->builtins()->StoreIC_Initialize_Strict() |
| 2856 : isolate()->builtins()->StoreIC_Initialize(); | 2834 : isolate()->builtins()->StoreIC_Initialize(); |
| 2857 CallCode(ic, RelocInfo::CODE_TARGET_CONTEXT, instr); | 2835 CallCode(ic, RelocInfo::CODE_TARGET_CONTEXT, instr); |
| 2858 } | 2836 } |
| 2859 | 2837 |
| (...skipping 56 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2916 } | 2894 } |
| 2917 | 2895 |
| 2918 | 2896 |
| 2919 void LCodeGen::DoLoadNamedField(LLoadNamedField* instr) { | 2897 void LCodeGen::DoLoadNamedField(LLoadNamedField* instr) { |
| 2920 HObjectAccess access = instr->hydrogen()->access(); | 2898 HObjectAccess access = instr->hydrogen()->access(); |
| 2921 int offset = access.offset(); | 2899 int offset = access.offset(); |
| 2922 Register object = ToRegister(instr->object()); | 2900 Register object = ToRegister(instr->object()); |
| 2923 | 2901 |
| 2924 if (access.IsExternalMemory()) { | 2902 if (access.IsExternalMemory()) { |
| 2925 Register result = ToRegister(instr->result()); | 2903 Register result = ToRegister(instr->result()); |
| 2926 __ lw(result, MemOperand(object, offset)); | 2904 MemOperand operand = MemOperand(object, offset); |
| 2905 if (access.representation().IsByte()) { |
| 2906 __ lb(result, operand); |
| 2907 } else { |
| 2908 __ lw(result, operand); |
| 2909 } |
| 2927 return; | 2910 return; |
| 2928 } | 2911 } |
| 2929 | 2912 |
| 2930 if (instr->hydrogen()->representation().IsDouble()) { | 2913 if (instr->hydrogen()->representation().IsDouble()) { |
| 2931 DoubleRegister result = ToDoubleRegister(instr->result()); | 2914 DoubleRegister result = ToDoubleRegister(instr->result()); |
| 2932 __ ldc1(result, FieldMemOperand(object, offset)); | 2915 __ ldc1(result, FieldMemOperand(object, offset)); |
| 2933 return; | 2916 return; |
| 2934 } | 2917 } |
| 2935 | 2918 |
| 2936 Register result = ToRegister(instr->result()); | 2919 Register result = ToRegister(instr->result()); |
| 2937 if (access.IsInobject()) { | 2920 if (!access.IsInobject()) { |
| 2938 __ lw(result, FieldMemOperand(object, offset)); | 2921 __ lw(result, FieldMemOperand(object, JSObject::kPropertiesOffset)); |
| 2922 object = result; |
| 2923 } |
| 2924 MemOperand operand = FieldMemOperand(object, offset); |
| 2925 if (access.representation().IsByte()) { |
| 2926 __ lb(result, operand); |
| 2939 } else { | 2927 } else { |
| 2940 __ lw(result, FieldMemOperand(object, JSObject::kPropertiesOffset)); | 2928 __ lw(result, operand); |
| 2941 __ lw(result, FieldMemOperand(result, offset)); | |
| 2942 } | 2929 } |
| 2943 } | 2930 } |
| 2944 | 2931 |
| 2945 | 2932 |
| 2946 void LCodeGen::DoLoadNamedGeneric(LLoadNamedGeneric* instr) { | 2933 void LCodeGen::DoLoadNamedGeneric(LLoadNamedGeneric* instr) { |
| 2934 ASSERT(ToRegister(instr->context()).is(cp)); |
| 2947 ASSERT(ToRegister(instr->object()).is(a0)); | 2935 ASSERT(ToRegister(instr->object()).is(a0)); |
| 2948 ASSERT(ToRegister(instr->result()).is(v0)); | 2936 ASSERT(ToRegister(instr->result()).is(v0)); |
| 2949 | 2937 |
| 2950 // Name is always in a2. | 2938 // Name is always in a2. |
| 2951 __ li(a2, Operand(instr->name())); | 2939 __ li(a2, Operand(instr->name())); |
| 2952 Handle<Code> ic = isolate()->builtins()->LoadIC_Initialize(); | 2940 Handle<Code> ic = isolate()->builtins()->LoadIC_Initialize(); |
| 2953 CallCode(ic, RelocInfo::CODE_TARGET, instr); | 2941 CallCode(ic, RelocInfo::CODE_TARGET, instr); |
| 2954 } | 2942 } |
| 2955 | 2943 |
| 2956 | 2944 |
| (...skipping 160 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 3117 | 3105 |
| 3118 | 3106 |
| 3119 void LCodeGen::DoLoadKeyedFixedDoubleArray(LLoadKeyed* instr) { | 3107 void LCodeGen::DoLoadKeyedFixedDoubleArray(LLoadKeyed* instr) { |
| 3120 Register elements = ToRegister(instr->elements()); | 3108 Register elements = ToRegister(instr->elements()); |
| 3121 bool key_is_constant = instr->key()->IsConstantOperand(); | 3109 bool key_is_constant = instr->key()->IsConstantOperand(); |
| 3122 Register key = no_reg; | 3110 Register key = no_reg; |
| 3123 DoubleRegister result = ToDoubleRegister(instr->result()); | 3111 DoubleRegister result = ToDoubleRegister(instr->result()); |
| 3124 Register scratch = scratch0(); | 3112 Register scratch = scratch0(); |
| 3125 | 3113 |
| 3126 int element_size_shift = ElementsKindToShiftSize(FAST_DOUBLE_ELEMENTS); | 3114 int element_size_shift = ElementsKindToShiftSize(FAST_DOUBLE_ELEMENTS); |
| 3127 int shift_size = (instr->hydrogen()->key()->representation().IsSmi()) | 3115 |
| 3128 ? (element_size_shift - kSmiTagSize) : element_size_shift; | 3116 int base_offset = |
| 3129 int constant_key = 0; | 3117 FixedDoubleArray::kHeaderSize - kHeapObjectTag + |
| 3118 (instr->additional_index() << element_size_shift); |
| 3130 if (key_is_constant) { | 3119 if (key_is_constant) { |
| 3131 constant_key = ToInteger32(LConstantOperand::cast(instr->key())); | 3120 int constant_key = ToInteger32(LConstantOperand::cast(instr->key())); |
| 3132 if (constant_key & 0xF0000000) { | 3121 if (constant_key & 0xF0000000) { |
| 3133 Abort(kArrayIndexConstantValueTooBig); | 3122 Abort(kArrayIndexConstantValueTooBig); |
| 3134 } | 3123 } |
| 3135 } else { | 3124 base_offset += constant_key << element_size_shift; |
| 3125 } |
| 3126 __ Addu(scratch, elements, Operand(base_offset)); |
| 3127 |
| 3128 if (!key_is_constant) { |
| 3136 key = ToRegister(instr->key()); | 3129 key = ToRegister(instr->key()); |
| 3130 int shift_size = (instr->hydrogen()->key()->representation().IsSmi()) |
| 3131 ? (element_size_shift - kSmiTagSize) : element_size_shift; |
| 3132 __ sll(at, key, shift_size); |
| 3133 __ Addu(scratch, scratch, at); |
| 3137 } | 3134 } |
| 3138 | 3135 |
| 3139 int base_offset = (FixedDoubleArray::kHeaderSize - kHeapObjectTag) + | 3136 __ ldc1(result, MemOperand(scratch)); |
| 3140 ((constant_key + instr->additional_index()) << element_size_shift); | 3137 |
| 3141 if (!key_is_constant) { | |
| 3142 __ sll(scratch, key, shift_size); | |
| 3143 __ Addu(elements, elements, scratch); | |
| 3144 } | |
| 3145 __ Addu(elements, elements, Operand(base_offset)); | |
| 3146 __ ldc1(result, MemOperand(elements)); | |
| 3147 if (instr->hydrogen()->RequiresHoleCheck()) { | 3138 if (instr->hydrogen()->RequiresHoleCheck()) { |
| 3148 __ lw(scratch, MemOperand(elements, sizeof(kHoleNanLower32))); | 3139 __ lw(scratch, MemOperand(scratch, sizeof(kHoleNanLower32))); |
| 3149 DeoptimizeIf(eq, instr->environment(), scratch, Operand(kHoleNanUpper32)); | 3140 DeoptimizeIf(eq, instr->environment(), scratch, Operand(kHoleNanUpper32)); |
| 3150 } | 3141 } |
| 3151 } | 3142 } |
| 3152 | 3143 |
| 3153 | 3144 |
| 3154 void LCodeGen::DoLoadKeyedFixedArray(LLoadKeyed* instr) { | 3145 void LCodeGen::DoLoadKeyedFixedArray(LLoadKeyed* instr) { |
| 3155 Register elements = ToRegister(instr->elements()); | 3146 Register elements = ToRegister(instr->elements()); |
| 3156 Register result = ToRegister(instr->result()); | 3147 Register result = ToRegister(instr->result()); |
| 3157 Register scratch = scratch0(); | 3148 Register scratch = scratch0(); |
| 3158 Register store_base = scratch; | 3149 Register store_base = scratch; |
| 3159 int offset = 0; | 3150 int offset = 0; |
| 3160 | 3151 |
| 3161 if (instr->key()->IsConstantOperand()) { | 3152 if (instr->key()->IsConstantOperand()) { |
| 3162 LConstantOperand* const_operand = LConstantOperand::cast(instr->key()); | 3153 LConstantOperand* const_operand = LConstantOperand::cast(instr->key()); |
| 3163 offset = FixedArray::OffsetOfElementAt(ToInteger32(const_operand) + | 3154 offset = FixedArray::OffsetOfElementAt(ToInteger32(const_operand) + |
| 3164 instr->additional_index()); | 3155 instr->additional_index()); |
| 3165 store_base = elements; | 3156 store_base = elements; |
| 3166 } else { | 3157 } else { |
| 3167 Register key = EmitLoadRegister(instr->key(), scratch0()); | 3158 Register key = ToRegister(instr->key()); |
| 3168 // Even though the HLoadKeyed instruction forces the input | 3159 // Even though the HLoadKeyed instruction forces the input |
| 3169 // representation for the key to be an integer, the input gets replaced | 3160 // representation for the key to be an integer, the input gets replaced |
| 3170 // during bound check elimination with the index argument to the bounds | 3161 // during bound check elimination with the index argument to the bounds |
| 3171 // check, which can be tagged, so that case must be handled here, too. | 3162 // check, which can be tagged, so that case must be handled here, too. |
| 3172 if (instr->hydrogen()->key()->representation().IsSmi()) { | 3163 if (instr->hydrogen()->key()->representation().IsSmi()) { |
| 3173 __ sll(scratch, key, kPointerSizeLog2 - kSmiTagSize); | 3164 __ sll(scratch, key, kPointerSizeLog2 - kSmiTagSize); |
| 3174 __ addu(scratch, elements, scratch); | 3165 __ addu(scratch, elements, scratch); |
| 3175 } else { | 3166 } else { |
| 3176 __ sll(scratch, key, kPointerSizeLog2); | 3167 __ sll(scratch, key, kPointerSizeLog2); |
| 3177 __ addu(scratch, elements, scratch); | 3168 __ addu(scratch, elements, scratch); |
| (...skipping 64 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 3242 } else { | 3233 } else { |
| 3243 ASSERT_EQ(-1, shift_size); | 3234 ASSERT_EQ(-1, shift_size); |
| 3244 __ srl(scratch0(), scratch0(), 1); | 3235 __ srl(scratch0(), scratch0(), 1); |
| 3245 __ Addu(scratch0(), base, scratch0()); | 3236 __ Addu(scratch0(), base, scratch0()); |
| 3246 return MemOperand(scratch0()); | 3237 return MemOperand(scratch0()); |
| 3247 } | 3238 } |
| 3248 } | 3239 } |
| 3249 | 3240 |
| 3250 | 3241 |
| 3251 void LCodeGen::DoLoadKeyedGeneric(LLoadKeyedGeneric* instr) { | 3242 void LCodeGen::DoLoadKeyedGeneric(LLoadKeyedGeneric* instr) { |
| 3243 ASSERT(ToRegister(instr->context()).is(cp)); |
| 3252 ASSERT(ToRegister(instr->object()).is(a1)); | 3244 ASSERT(ToRegister(instr->object()).is(a1)); |
| 3253 ASSERT(ToRegister(instr->key()).is(a0)); | 3245 ASSERT(ToRegister(instr->key()).is(a0)); |
| 3254 | 3246 |
| 3255 Handle<Code> ic = isolate()->builtins()->KeyedLoadIC_Initialize(); | 3247 Handle<Code> ic = isolate()->builtins()->KeyedLoadIC_Initialize(); |
| 3256 CallCode(ic, RelocInfo::CODE_TARGET, instr); | 3248 CallCode(ic, RelocInfo::CODE_TARGET, instr); |
| 3257 } | 3249 } |
| 3258 | 3250 |
| 3259 | 3251 |
| 3260 void LCodeGen::DoArgumentsElements(LArgumentsElements* instr) { | 3252 void LCodeGen::DoArgumentsElements(LArgumentsElements* instr) { |
| 3261 Register scratch = scratch0(); | 3253 Register scratch = scratch0(); |
| (...skipping 125 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 3387 ASSERT(instr->HasPointerMap()); | 3379 ASSERT(instr->HasPointerMap()); |
| 3388 LPointerMap* pointers = instr->pointer_map(); | 3380 LPointerMap* pointers = instr->pointer_map(); |
| 3389 RecordPosition(pointers->position()); | 3381 RecordPosition(pointers->position()); |
| 3390 SafepointGenerator safepoint_generator( | 3382 SafepointGenerator safepoint_generator( |
| 3391 this, pointers, Safepoint::kLazyDeopt); | 3383 this, pointers, Safepoint::kLazyDeopt); |
| 3392 // The number of arguments is stored in receiver which is a0, as expected | 3384 // The number of arguments is stored in receiver which is a0, as expected |
| 3393 // by InvokeFunction. | 3385 // by InvokeFunction. |
| 3394 ParameterCount actual(receiver); | 3386 ParameterCount actual(receiver); |
| 3395 __ InvokeFunction(function, actual, CALL_FUNCTION, | 3387 __ InvokeFunction(function, actual, CALL_FUNCTION, |
| 3396 safepoint_generator, CALL_AS_METHOD); | 3388 safepoint_generator, CALL_AS_METHOD); |
| 3397 __ lw(cp, MemOperand(fp, StandardFrameConstants::kContextOffset)); | |
| 3398 } | 3389 } |
| 3399 | 3390 |
| 3400 | 3391 |
| 3401 void LCodeGen::DoPushArgument(LPushArgument* instr) { | 3392 void LCodeGen::DoPushArgument(LPushArgument* instr) { |
| 3402 LOperand* argument = instr->value(); | 3393 LOperand* argument = instr->value(); |
| 3403 if (argument->IsDoubleRegister() || argument->IsDoubleStackSlot()) { | 3394 if (argument->IsDoubleRegister() || argument->IsDoubleStackSlot()) { |
| 3404 Abort(kDoPushArgumentNotImplementedForDoubleType); | 3395 Abort(kDoPushArgumentNotImplementedForDoubleType); |
| 3405 } else { | 3396 } else { |
| 3406 Register argument_reg = EmitLoadRegister(argument, at); | 3397 Register argument_reg = EmitLoadRegister(argument, at); |
| 3407 __ push(argument_reg); | 3398 __ push(argument_reg); |
| 3408 } | 3399 } |
| 3409 } | 3400 } |
| 3410 | 3401 |
| 3411 | 3402 |
| 3412 void LCodeGen::DoDrop(LDrop* instr) { | 3403 void LCodeGen::DoDrop(LDrop* instr) { |
| 3413 __ Drop(instr->count()); | 3404 __ Drop(instr->count()); |
| 3414 } | 3405 } |
| 3415 | 3406 |
| 3416 | 3407 |
| 3417 void LCodeGen::DoThisFunction(LThisFunction* instr) { | 3408 void LCodeGen::DoThisFunction(LThisFunction* instr) { |
| 3418 Register result = ToRegister(instr->result()); | 3409 Register result = ToRegister(instr->result()); |
| 3419 __ lw(result, MemOperand(fp, JavaScriptFrameConstants::kFunctionOffset)); | 3410 __ lw(result, MemOperand(fp, JavaScriptFrameConstants::kFunctionOffset)); |
| 3420 } | 3411 } |
| 3421 | 3412 |
| 3422 | 3413 |
| 3423 void LCodeGen::DoContext(LContext* instr) { | 3414 void LCodeGen::DoContext(LContext* instr) { |
| 3424 // If there is a non-return use, the context must be moved to a register. | 3415 // If there is a non-return use, the context must be moved to a register. |
| 3425 Register result = ToRegister(instr->result()); | 3416 Register result = ToRegister(instr->result()); |
| 3426 for (HUseIterator it(instr->hydrogen()->uses()); !it.Done(); it.Advance()) { | 3417 if (info()->IsOptimizing()) { |
| 3427 if (!it.value()->IsReturn()) { | 3418 __ lw(result, MemOperand(fp, StandardFrameConstants::kContextOffset)); |
| 3428 __ mov(result, cp); | 3419 } else { |
| 3429 return; | 3420 // If there is no frame, the context must be in cp. |
| 3430 } | 3421 ASSERT(result.is(cp)); |
| 3431 } | 3422 } |
| 3432 } | 3423 } |
| 3433 | 3424 |
| 3434 | 3425 |
| 3435 void LCodeGen::DoOuterContext(LOuterContext* instr) { | 3426 void LCodeGen::DoOuterContext(LOuterContext* instr) { |
| 3436 Register context = ToRegister(instr->context()); | 3427 Register context = ToRegister(instr->context()); |
| 3437 Register result = ToRegister(instr->result()); | 3428 Register result = ToRegister(instr->result()); |
| 3438 __ lw(result, | 3429 __ lw(result, |
| 3439 MemOperand(context, Context::SlotOffset(Context::PREVIOUS_INDEX))); | 3430 MemOperand(context, Context::SlotOffset(Context::PREVIOUS_INDEX))); |
| 3440 } | 3431 } |
| 3441 | 3432 |
| 3442 | 3433 |
| 3443 void LCodeGen::DoDeclareGlobals(LDeclareGlobals* instr) { | 3434 void LCodeGen::DoDeclareGlobals(LDeclareGlobals* instr) { |
| 3435 ASSERT(ToRegister(instr->context()).is(cp)); |
| 3444 __ LoadHeapObject(scratch0(), instr->hydrogen()->pairs()); | 3436 __ LoadHeapObject(scratch0(), instr->hydrogen()->pairs()); |
| 3445 __ li(scratch1(), Operand(Smi::FromInt(instr->hydrogen()->flags()))); | 3437 __ li(scratch1(), Operand(Smi::FromInt(instr->hydrogen()->flags()))); |
| 3446 // The context is the first argument. | 3438 // The context is the first argument. |
| 3447 __ Push(cp, scratch0(), scratch1()); | 3439 __ Push(cp, scratch0(), scratch1()); |
| 3448 CallRuntime(Runtime::kDeclareGlobals, 3, instr); | 3440 CallRuntime(Runtime::kDeclareGlobals, 3, instr); |
| 3449 } | 3441 } |
| 3450 | 3442 |
| 3451 | 3443 |
| 3452 void LCodeGen::DoGlobalObject(LGlobalObject* instr) { | 3444 void LCodeGen::DoGlobalObject(LGlobalObject* instr) { |
| 3445 Register context = ToRegister(instr->context()); |
| 3453 Register result = ToRegister(instr->result()); | 3446 Register result = ToRegister(instr->result()); |
| 3454 __ lw(result, ContextOperand(cp, Context::GLOBAL_OBJECT_INDEX)); | 3447 __ lw(result, ContextOperand(context, Context::GLOBAL_OBJECT_INDEX)); |
| 3455 } | 3448 } |
| 3456 | 3449 |
| 3457 | 3450 |
| 3458 void LCodeGen::DoGlobalReceiver(LGlobalReceiver* instr) { | 3451 void LCodeGen::DoGlobalReceiver(LGlobalReceiver* instr) { |
| 3459 Register global = ToRegister(instr->global_object()); | 3452 Register global = ToRegister(instr->global_object()); |
| 3460 Register result = ToRegister(instr->result()); | 3453 Register result = ToRegister(instr->result()); |
| 3461 __ lw(result, FieldMemOperand(global, GlobalObject::kGlobalReceiverOffset)); | 3454 __ lw(result, FieldMemOperand(global, GlobalObject::kGlobalReceiverOffset)); |
| 3462 } | 3455 } |
| 3463 | 3456 |
| 3464 | 3457 |
| (...skipping 32 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 3497 | 3490 |
| 3498 // Set up deoptimization. | 3491 // Set up deoptimization. |
| 3499 RecordSafepointWithLazyDeopt(instr, RECORD_SIMPLE_SAFEPOINT); | 3492 RecordSafepointWithLazyDeopt(instr, RECORD_SIMPLE_SAFEPOINT); |
| 3500 } else { | 3493 } else { |
| 3501 SafepointGenerator generator(this, pointers, Safepoint::kLazyDeopt); | 3494 SafepointGenerator generator(this, pointers, Safepoint::kLazyDeopt); |
| 3502 ParameterCount count(arity); | 3495 ParameterCount count(arity); |
| 3503 ParameterCount expected(formal_parameter_count); | 3496 ParameterCount expected(formal_parameter_count); |
| 3504 __ InvokeFunction( | 3497 __ InvokeFunction( |
| 3505 function, expected, count, CALL_FUNCTION, generator, call_kind); | 3498 function, expected, count, CALL_FUNCTION, generator, call_kind); |
| 3506 } | 3499 } |
| 3507 | |
| 3508 // Restore context. | |
| 3509 __ lw(cp, MemOperand(fp, StandardFrameConstants::kContextOffset)); | |
| 3510 } | 3500 } |
| 3511 | 3501 |
| 3512 | 3502 |
| 3513 void LCodeGen::DoCallConstantFunction(LCallConstantFunction* instr) { | 3503 void LCodeGen::DoCallConstantFunction(LCallConstantFunction* instr) { |
| 3514 ASSERT(ToRegister(instr->result()).is(v0)); | 3504 ASSERT(ToRegister(instr->result()).is(v0)); |
| 3515 __ mov(a0, v0); | 3505 __ mov(a0, v0); |
| 3516 CallKnownFunction(instr->hydrogen()->function(), | 3506 CallKnownFunction(instr->hydrogen()->function(), |
| 3517 instr->hydrogen()->formal_parameter_count(), | 3507 instr->hydrogen()->formal_parameter_count(), |
| 3518 instr->arity(), | 3508 instr->arity(), |
| 3519 instr, | 3509 instr, |
| 3520 CALL_AS_METHOD, | 3510 CALL_AS_METHOD, |
| 3521 A1_UNINITIALIZED); | 3511 A1_UNINITIALIZED); |
| 3522 } | 3512 } |
| 3523 | 3513 |
| 3524 | 3514 |
| 3525 void LCodeGen::DoDeferredMathAbsTaggedHeapNumber(LMathAbs* instr) { | 3515 void LCodeGen::DoDeferredMathAbsTaggedHeapNumber(LMathAbs* instr) { |
| 3516 ASSERT(instr->context() != NULL); |
| 3517 ASSERT(ToRegister(instr->context()).is(cp)); |
| 3526 Register input = ToRegister(instr->value()); | 3518 Register input = ToRegister(instr->value()); |
| 3527 Register result = ToRegister(instr->result()); | 3519 Register result = ToRegister(instr->result()); |
| 3528 Register scratch = scratch0(); | 3520 Register scratch = scratch0(); |
| 3529 | 3521 |
| 3530 // Deoptimize if not a heap number. | 3522 // Deoptimize if not a heap number. |
| 3531 __ lw(scratch, FieldMemOperand(input, HeapObject::kMapOffset)); | 3523 __ lw(scratch, FieldMemOperand(input, HeapObject::kMapOffset)); |
| 3532 __ LoadRoot(at, Heap::kHeapNumberMapRootIndex); | 3524 __ LoadRoot(at, Heap::kHeapNumberMapRootIndex); |
| 3533 DeoptimizeIf(ne, instr->environment(), scratch, Operand(at)); | 3525 DeoptimizeIf(ne, instr->environment(), scratch, Operand(at)); |
| 3534 | 3526 |
| 3535 Label done; | 3527 Label done; |
| (...skipping 21 matching lines...) Expand all Loading... |
| 3557 // exponent: floating point exponent value. | 3549 // exponent: floating point exponent value. |
| 3558 | 3550 |
| 3559 Label allocated, slow; | 3551 Label allocated, slow; |
| 3560 __ LoadRoot(tmp4, Heap::kHeapNumberMapRootIndex); | 3552 __ LoadRoot(tmp4, Heap::kHeapNumberMapRootIndex); |
| 3561 __ AllocateHeapNumber(tmp1, tmp2, tmp3, tmp4, &slow); | 3553 __ AllocateHeapNumber(tmp1, tmp2, tmp3, tmp4, &slow); |
| 3562 __ Branch(&allocated); | 3554 __ Branch(&allocated); |
| 3563 | 3555 |
| 3564 // Slow case: Call the runtime system to do the number allocation. | 3556 // Slow case: Call the runtime system to do the number allocation. |
| 3565 __ bind(&slow); | 3557 __ bind(&slow); |
| 3566 | 3558 |
| 3567 CallRuntimeFromDeferred(Runtime::kAllocateHeapNumber, 0, instr); | 3559 CallRuntimeFromDeferred(Runtime::kAllocateHeapNumber, 0, instr, |
| 3560 instr->context()); |
| 3568 // Set the pointer to the new heap number in tmp. | 3561 // Set the pointer to the new heap number in tmp. |
| 3569 if (!tmp1.is(v0)) | 3562 if (!tmp1.is(v0)) |
| 3570 __ mov(tmp1, v0); | 3563 __ mov(tmp1, v0); |
| 3571 // Restore input_reg after call to runtime. | 3564 // Restore input_reg after call to runtime. |
| 3572 __ LoadFromSafepointRegisterSlot(input, input); | 3565 __ LoadFromSafepointRegisterSlot(input, input); |
| 3573 __ lw(exponent, FieldMemOperand(input, HeapNumber::kExponentOffset)); | 3566 __ lw(exponent, FieldMemOperand(input, HeapNumber::kExponentOffset)); |
| 3574 | 3567 |
| 3575 __ bind(&allocated); | 3568 __ bind(&allocated); |
| 3576 // exponent: floating point exponent value. | 3569 // exponent: floating point exponent value. |
| 3577 // tmp1: allocated heap number. | 3570 // tmp1: allocated heap number. |
| (...skipping 297 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 3875 Register temp2 = ToRegister(instr->temp2()); | 3868 Register temp2 = ToRegister(instr->temp2()); |
| 3876 | 3869 |
| 3877 MathExpGenerator::EmitMathExp( | 3870 MathExpGenerator::EmitMathExp( |
| 3878 masm(), input, result, double_scratch1, double_scratch2, | 3871 masm(), input, result, double_scratch1, double_scratch2, |
| 3879 temp1, temp2, scratch0()); | 3872 temp1, temp2, scratch0()); |
| 3880 } | 3873 } |
| 3881 | 3874 |
| 3882 | 3875 |
| 3883 void LCodeGen::DoMathLog(LMathLog* instr) { | 3876 void LCodeGen::DoMathLog(LMathLog* instr) { |
| 3884 ASSERT(ToDoubleRegister(instr->result()).is(f4)); | 3877 ASSERT(ToDoubleRegister(instr->result()).is(f4)); |
| 3878 // Set the context register to a GC-safe fake value. Clobbering it is |
| 3879 // OK because this instruction is marked as a call. |
| 3880 __ mov(cp, zero_reg); |
| 3885 TranscendentalCacheStub stub(TranscendentalCache::LOG, | 3881 TranscendentalCacheStub stub(TranscendentalCache::LOG, |
| 3886 TranscendentalCacheStub::UNTAGGED); | 3882 TranscendentalCacheStub::UNTAGGED); |
| 3887 CallCode(stub.GetCode(isolate()), RelocInfo::CODE_TARGET, instr); | 3883 CallCode(stub.GetCode(isolate()), RelocInfo::CODE_TARGET, instr); |
| 3888 } | 3884 } |
| 3889 | 3885 |
| 3890 | 3886 |
| 3891 void LCodeGen::DoMathTan(LMathTan* instr) { | 3887 void LCodeGen::DoMathTan(LMathTan* instr) { |
| 3892 ASSERT(ToDoubleRegister(instr->result()).is(f4)); | 3888 ASSERT(ToDoubleRegister(instr->result()).is(f4)); |
| 3889 // Set the context register to a GC-safe fake value. Clobbering it is |
| 3890 // OK because this instruction is marked as a call. |
| 3891 __ mov(cp, zero_reg); |
| 3893 TranscendentalCacheStub stub(TranscendentalCache::TAN, | 3892 TranscendentalCacheStub stub(TranscendentalCache::TAN, |
| 3894 TranscendentalCacheStub::UNTAGGED); | 3893 TranscendentalCacheStub::UNTAGGED); |
| 3895 CallCode(stub.GetCode(isolate()), RelocInfo::CODE_TARGET, instr); | 3894 CallCode(stub.GetCode(isolate()), RelocInfo::CODE_TARGET, instr); |
| 3896 } | 3895 } |
| 3897 | 3896 |
| 3898 | 3897 |
| 3899 void LCodeGen::DoMathCos(LMathCos* instr) { | 3898 void LCodeGen::DoMathCos(LMathCos* instr) { |
| 3900 ASSERT(ToDoubleRegister(instr->result()).is(f4)); | 3899 ASSERT(ToDoubleRegister(instr->result()).is(f4)); |
| 3900 // Set the context register to a GC-safe fake value. Clobbering it is |
| 3901 // OK because this instruction is marked as a call. |
| 3902 __ mov(cp, zero_reg); |
| 3901 TranscendentalCacheStub stub(TranscendentalCache::COS, | 3903 TranscendentalCacheStub stub(TranscendentalCache::COS, |
| 3902 TranscendentalCacheStub::UNTAGGED); | 3904 TranscendentalCacheStub::UNTAGGED); |
| 3903 CallCode(stub.GetCode(isolate()), RelocInfo::CODE_TARGET, instr); | 3905 CallCode(stub.GetCode(isolate()), RelocInfo::CODE_TARGET, instr); |
| 3904 } | 3906 } |
| 3905 | 3907 |
| 3906 | 3908 |
| 3907 void LCodeGen::DoMathSin(LMathSin* instr) { | 3909 void LCodeGen::DoMathSin(LMathSin* instr) { |
| 3908 ASSERT(ToDoubleRegister(instr->result()).is(f4)); | 3910 ASSERT(ToDoubleRegister(instr->result()).is(f4)); |
| 3911 // Set the context register to a GC-safe fake value. Clobbering it is |
| 3912 // OK because this instruction is marked as a call. |
| 3913 __ mov(cp, zero_reg); |
| 3909 TranscendentalCacheStub stub(TranscendentalCache::SIN, | 3914 TranscendentalCacheStub stub(TranscendentalCache::SIN, |
| 3910 TranscendentalCacheStub::UNTAGGED); | 3915 TranscendentalCacheStub::UNTAGGED); |
| 3911 CallCode(stub.GetCode(isolate()), RelocInfo::CODE_TARGET, instr); | 3916 CallCode(stub.GetCode(isolate()), RelocInfo::CODE_TARGET, instr); |
| 3912 } | 3917 } |
| 3913 | 3918 |
| 3914 | 3919 |
| 3915 void LCodeGen::DoInvokeFunction(LInvokeFunction* instr) { | 3920 void LCodeGen::DoInvokeFunction(LInvokeFunction* instr) { |
| 3921 ASSERT(ToRegister(instr->context()).is(cp)); |
| 3916 ASSERT(ToRegister(instr->function()).is(a1)); | 3922 ASSERT(ToRegister(instr->function()).is(a1)); |
| 3917 ASSERT(instr->HasPointerMap()); | 3923 ASSERT(instr->HasPointerMap()); |
| 3918 | 3924 |
| 3919 Handle<JSFunction> known_function = instr->hydrogen()->known_function(); | 3925 Handle<JSFunction> known_function = instr->hydrogen()->known_function(); |
| 3920 if (known_function.is_null()) { | 3926 if (known_function.is_null()) { |
| 3921 LPointerMap* pointers = instr->pointer_map(); | 3927 LPointerMap* pointers = instr->pointer_map(); |
| 3922 RecordPosition(pointers->position()); | 3928 RecordPosition(pointers->position()); |
| 3923 SafepointGenerator generator(this, pointers, Safepoint::kLazyDeopt); | 3929 SafepointGenerator generator(this, pointers, Safepoint::kLazyDeopt); |
| 3924 ParameterCount count(instr->arity()); | 3930 ParameterCount count(instr->arity()); |
| 3925 __ InvokeFunction(a1, count, CALL_FUNCTION, generator, CALL_AS_METHOD); | 3931 __ InvokeFunction(a1, count, CALL_FUNCTION, generator, CALL_AS_METHOD); |
| 3926 __ lw(cp, MemOperand(fp, StandardFrameConstants::kContextOffset)); | |
| 3927 } else { | 3932 } else { |
| 3928 CallKnownFunction(known_function, | 3933 CallKnownFunction(known_function, |
| 3929 instr->hydrogen()->formal_parameter_count(), | 3934 instr->hydrogen()->formal_parameter_count(), |
| 3930 instr->arity(), | 3935 instr->arity(), |
| 3931 instr, | 3936 instr, |
| 3932 CALL_AS_METHOD, | 3937 CALL_AS_METHOD, |
| 3933 A1_CONTAINS_TARGET); | 3938 A1_CONTAINS_TARGET); |
| 3934 } | 3939 } |
| 3935 } | 3940 } |
| 3936 | 3941 |
| 3937 | 3942 |
| 3938 void LCodeGen::DoCallKeyed(LCallKeyed* instr) { | 3943 void LCodeGen::DoCallKeyed(LCallKeyed* instr) { |
| 3944 ASSERT(ToRegister(instr->context()).is(cp)); |
| 3939 ASSERT(ToRegister(instr->result()).is(v0)); | 3945 ASSERT(ToRegister(instr->result()).is(v0)); |
| 3940 | 3946 |
| 3941 int arity = instr->arity(); | 3947 int arity = instr->arity(); |
| 3942 Handle<Code> ic = | 3948 Handle<Code> ic = |
| 3943 isolate()->stub_cache()->ComputeKeyedCallInitialize(arity); | 3949 isolate()->stub_cache()->ComputeKeyedCallInitialize(arity); |
| 3944 CallCode(ic, RelocInfo::CODE_TARGET, instr); | 3950 CallCode(ic, RelocInfo::CODE_TARGET, instr); |
| 3945 __ lw(cp, MemOperand(fp, StandardFrameConstants::kContextOffset)); | |
| 3946 } | 3951 } |
| 3947 | 3952 |
| 3948 | 3953 |
| 3949 void LCodeGen::DoCallNamed(LCallNamed* instr) { | 3954 void LCodeGen::DoCallNamed(LCallNamed* instr) { |
| 3955 ASSERT(ToRegister(instr->context()).is(cp)); |
| 3950 ASSERT(ToRegister(instr->result()).is(v0)); | 3956 ASSERT(ToRegister(instr->result()).is(v0)); |
| 3951 | 3957 |
| 3952 int arity = instr->arity(); | 3958 int arity = instr->arity(); |
| 3953 RelocInfo::Mode mode = RelocInfo::CODE_TARGET; | 3959 RelocInfo::Mode mode = RelocInfo::CODE_TARGET; |
| 3954 Handle<Code> ic = | 3960 Handle<Code> ic = |
| 3955 isolate()->stub_cache()->ComputeCallInitialize(arity, mode); | 3961 isolate()->stub_cache()->ComputeCallInitialize(arity, mode); |
| 3956 __ li(a2, Operand(instr->name())); | 3962 __ li(a2, Operand(instr->name())); |
| 3957 CallCode(ic, mode, instr); | 3963 CallCode(ic, mode, instr); |
| 3958 // Restore context register. | |
| 3959 __ lw(cp, MemOperand(fp, StandardFrameConstants::kContextOffset)); | |
| 3960 } | 3964 } |
| 3961 | 3965 |
| 3962 | 3966 |
| 3963 void LCodeGen::DoCallFunction(LCallFunction* instr) { | 3967 void LCodeGen::DoCallFunction(LCallFunction* instr) { |
| 3968 ASSERT(ToRegister(instr->context()).is(cp)); |
| 3964 ASSERT(ToRegister(instr->function()).is(a1)); | 3969 ASSERT(ToRegister(instr->function()).is(a1)); |
| 3965 ASSERT(ToRegister(instr->result()).is(v0)); | 3970 ASSERT(ToRegister(instr->result()).is(v0)); |
| 3966 | 3971 |
| 3967 int arity = instr->arity(); | 3972 int arity = instr->arity(); |
| 3968 CallFunctionStub stub(arity, NO_CALL_FUNCTION_FLAGS); | 3973 CallFunctionStub stub(arity, NO_CALL_FUNCTION_FLAGS); |
| 3969 CallCode(stub.GetCode(isolate()), RelocInfo::CODE_TARGET, instr); | 3974 CallCode(stub.GetCode(isolate()), RelocInfo::CODE_TARGET, instr); |
| 3970 __ lw(cp, MemOperand(fp, StandardFrameConstants::kContextOffset)); | |
| 3971 } | 3975 } |
| 3972 | 3976 |
| 3973 | 3977 |
| 3974 void LCodeGen::DoCallGlobal(LCallGlobal* instr) { | 3978 void LCodeGen::DoCallGlobal(LCallGlobal* instr) { |
| 3979 ASSERT(ToRegister(instr->context()).is(cp)); |
| 3975 ASSERT(ToRegister(instr->result()).is(v0)); | 3980 ASSERT(ToRegister(instr->result()).is(v0)); |
| 3976 | 3981 |
| 3977 int arity = instr->arity(); | 3982 int arity = instr->arity(); |
| 3978 RelocInfo::Mode mode = RelocInfo::CODE_TARGET_CONTEXT; | 3983 RelocInfo::Mode mode = RelocInfo::CODE_TARGET_CONTEXT; |
| 3979 Handle<Code> ic = | 3984 Handle<Code> ic = |
| 3980 isolate()->stub_cache()->ComputeCallInitialize(arity, mode); | 3985 isolate()->stub_cache()->ComputeCallInitialize(arity, mode); |
| 3981 __ li(a2, Operand(instr->name())); | 3986 __ li(a2, Operand(instr->name())); |
| 3982 CallCode(ic, mode, instr); | 3987 CallCode(ic, mode, instr); |
| 3983 __ lw(cp, MemOperand(fp, StandardFrameConstants::kContextOffset)); | |
| 3984 } | 3988 } |
| 3985 | 3989 |
| 3986 | 3990 |
| 3987 void LCodeGen::DoCallKnownGlobal(LCallKnownGlobal* instr) { | 3991 void LCodeGen::DoCallKnownGlobal(LCallKnownGlobal* instr) { |
| 3988 ASSERT(ToRegister(instr->result()).is(v0)); | 3992 ASSERT(ToRegister(instr->result()).is(v0)); |
| 3989 CallKnownFunction(instr->hydrogen()->target(), | 3993 CallKnownFunction(instr->hydrogen()->target(), |
| 3990 instr->hydrogen()->formal_parameter_count(), | 3994 instr->hydrogen()->formal_parameter_count(), |
| 3991 instr->arity(), | 3995 instr->arity(), |
| 3992 instr, | 3996 instr, |
| 3993 CALL_AS_FUNCTION, | 3997 CALL_AS_FUNCTION, |
| 3994 A1_UNINITIALIZED); | 3998 A1_UNINITIALIZED); |
| 3995 } | 3999 } |
| 3996 | 4000 |
| 3997 | 4001 |
| 3998 void LCodeGen::DoCallNew(LCallNew* instr) { | 4002 void LCodeGen::DoCallNew(LCallNew* instr) { |
| 4003 ASSERT(ToRegister(instr->context()).is(cp)); |
| 3999 ASSERT(ToRegister(instr->constructor()).is(a1)); | 4004 ASSERT(ToRegister(instr->constructor()).is(a1)); |
| 4000 ASSERT(ToRegister(instr->result()).is(v0)); | 4005 ASSERT(ToRegister(instr->result()).is(v0)); |
| 4001 | 4006 |
| 4002 __ li(a0, Operand(instr->arity())); | 4007 __ li(a0, Operand(instr->arity())); |
| 4003 // No cell in a2 for construct type feedback in optimized code | 4008 // No cell in a2 for construct type feedback in optimized code |
| 4004 Handle<Object> undefined_value(isolate()->factory()->undefined_value()); | 4009 Handle<Object> undefined_value(isolate()->factory()->undefined_value()); |
| 4005 __ li(a2, Operand(undefined_value)); | 4010 __ li(a2, Operand(undefined_value)); |
| 4006 CallConstructStub stub(NO_CALL_FUNCTION_FLAGS); | 4011 CallConstructStub stub(NO_CALL_FUNCTION_FLAGS); |
| 4007 CallCode(stub.GetCode(isolate()), RelocInfo::CONSTRUCT_CALL, instr); | 4012 CallCode(stub.GetCode(isolate()), RelocInfo::CONSTRUCT_CALL, instr); |
| 4008 } | 4013 } |
| 4009 | 4014 |
| 4010 | 4015 |
| 4011 void LCodeGen::DoCallNewArray(LCallNewArray* instr) { | 4016 void LCodeGen::DoCallNewArray(LCallNewArray* instr) { |
| 4017 ASSERT(ToRegister(instr->context()).is(cp)); |
| 4012 ASSERT(ToRegister(instr->constructor()).is(a1)); | 4018 ASSERT(ToRegister(instr->constructor()).is(a1)); |
| 4013 ASSERT(ToRegister(instr->result()).is(v0)); | 4019 ASSERT(ToRegister(instr->result()).is(v0)); |
| 4014 | 4020 |
| 4015 __ li(a0, Operand(instr->arity())); | 4021 __ li(a0, Operand(instr->arity())); |
| 4016 __ li(a2, Operand(instr->hydrogen()->property_cell())); | 4022 __ li(a2, Operand(instr->hydrogen()->property_cell())); |
| 4017 ElementsKind kind = instr->hydrogen()->elements_kind(); | 4023 ElementsKind kind = instr->hydrogen()->elements_kind(); |
| 4018 AllocationSiteOverrideMode override_mode = | 4024 AllocationSiteOverrideMode override_mode = |
| 4019 (AllocationSite::GetMode(kind) == TRACK_ALLOCATION_SITE) | 4025 (AllocationSite::GetMode(kind) == TRACK_ALLOCATION_SITE) |
| 4020 ? DISABLE_ALLOCATION_SITES | 4026 ? DISABLE_ALLOCATION_SITES |
| 4021 : DONT_OVERRIDE; | 4027 : DONT_OVERRIDE; |
| (...skipping 54 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 4076 void LCodeGen::DoStoreNamedField(LStoreNamedField* instr) { | 4082 void LCodeGen::DoStoreNamedField(LStoreNamedField* instr) { |
| 4077 Representation representation = instr->representation(); | 4083 Representation representation = instr->representation(); |
| 4078 | 4084 |
| 4079 Register object = ToRegister(instr->object()); | 4085 Register object = ToRegister(instr->object()); |
| 4080 Register scratch = scratch0(); | 4086 Register scratch = scratch0(); |
| 4081 HObjectAccess access = instr->hydrogen()->access(); | 4087 HObjectAccess access = instr->hydrogen()->access(); |
| 4082 int offset = access.offset(); | 4088 int offset = access.offset(); |
| 4083 | 4089 |
| 4084 if (access.IsExternalMemory()) { | 4090 if (access.IsExternalMemory()) { |
| 4085 Register value = ToRegister(instr->value()); | 4091 Register value = ToRegister(instr->value()); |
| 4086 __ sw(value, MemOperand(object, offset)); | 4092 MemOperand operand = MemOperand(object, offset); |
| 4093 if (representation.IsByte()) { |
| 4094 __ sb(value, operand); |
| 4095 } else { |
| 4096 __ sw(value, operand); |
| 4097 } |
| 4087 return; | 4098 return; |
| 4088 } | 4099 } |
| 4089 | 4100 |
| 4090 Handle<Map> transition = instr->transition(); | 4101 Handle<Map> transition = instr->transition(); |
| 4091 | 4102 |
| 4092 if (FLAG_track_heap_object_fields && representation.IsHeapObject()) { | 4103 if (FLAG_track_heap_object_fields && representation.IsHeapObject()) { |
| 4093 Register value = ToRegister(instr->value()); | 4104 Register value = ToRegister(instr->value()); |
| 4094 if (!instr->hydrogen()->value()->type().IsHeapObject()) { | 4105 if (!instr->hydrogen()->value()->type().IsHeapObject()) { |
| 4095 __ And(scratch, value, Operand(kSmiTagMask)); | 4106 __ And(scratch, value, Operand(kSmiTagMask)); |
| 4096 DeoptimizeIf(eq, instr->environment(), scratch, Operand(zero_reg)); | 4107 DeoptimizeIf(eq, instr->environment(), scratch, Operand(zero_reg)); |
| (...skipping 24 matching lines...) Expand all Loading... |
| 4121 } | 4132 } |
| 4122 } | 4133 } |
| 4123 | 4134 |
| 4124 // Do the store. | 4135 // Do the store. |
| 4125 Register value = ToRegister(instr->value()); | 4136 Register value = ToRegister(instr->value()); |
| 4126 ASSERT(!object.is(value)); | 4137 ASSERT(!object.is(value)); |
| 4127 SmiCheck check_needed = | 4138 SmiCheck check_needed = |
| 4128 instr->hydrogen()->value()->IsHeapObject() | 4139 instr->hydrogen()->value()->IsHeapObject() |
| 4129 ? OMIT_SMI_CHECK : INLINE_SMI_CHECK; | 4140 ? OMIT_SMI_CHECK : INLINE_SMI_CHECK; |
| 4130 if (access.IsInobject()) { | 4141 if (access.IsInobject()) { |
| 4131 __ sw(value, FieldMemOperand(object, offset)); | 4142 MemOperand operand = FieldMemOperand(object, offset); |
| 4143 if (representation.IsByte()) { |
| 4144 __ sb(value, operand); |
| 4145 } else { |
| 4146 __ sw(value, operand); |
| 4147 } |
| 4132 if (instr->hydrogen()->NeedsWriteBarrier()) { | 4148 if (instr->hydrogen()->NeedsWriteBarrier()) { |
| 4133 // Update the write barrier for the object for in-object properties. | 4149 // Update the write barrier for the object for in-object properties. |
| 4134 __ RecordWriteField(object, | 4150 __ RecordWriteField(object, |
| 4135 offset, | 4151 offset, |
| 4136 value, | 4152 value, |
| 4137 scratch, | 4153 scratch, |
| 4138 GetRAState(), | 4154 GetRAState(), |
| 4139 kSaveFPRegs, | 4155 kSaveFPRegs, |
| 4140 EMIT_REMEMBERED_SET, | 4156 EMIT_REMEMBERED_SET, |
| 4141 check_needed); | 4157 check_needed); |
| 4142 } | 4158 } |
| 4143 } else { | 4159 } else { |
| 4144 __ lw(scratch, FieldMemOperand(object, JSObject::kPropertiesOffset)); | 4160 __ lw(scratch, FieldMemOperand(object, JSObject::kPropertiesOffset)); |
| 4145 __ sw(value, FieldMemOperand(scratch, offset)); | 4161 MemOperand operand = FieldMemOperand(scratch, offset); |
| 4162 if (representation.IsByte()) { |
| 4163 __ sb(value, operand); |
| 4164 } else { |
| 4165 __ sw(value, operand); |
| 4166 } |
| 4146 if (instr->hydrogen()->NeedsWriteBarrier()) { | 4167 if (instr->hydrogen()->NeedsWriteBarrier()) { |
| 4147 // Update the write barrier for the properties array. | 4168 // Update the write barrier for the properties array. |
| 4148 // object is used as a scratch register. | 4169 // object is used as a scratch register. |
| 4149 __ RecordWriteField(scratch, | 4170 __ RecordWriteField(scratch, |
| 4150 offset, | 4171 offset, |
| 4151 value, | 4172 value, |
| 4152 object, | 4173 object, |
| 4153 GetRAState(), | 4174 GetRAState(), |
| 4154 kSaveFPRegs, | 4175 kSaveFPRegs, |
| 4155 EMIT_REMEMBERED_SET, | 4176 EMIT_REMEMBERED_SET, |
| 4156 check_needed); | 4177 check_needed); |
| 4157 } | 4178 } |
| 4158 } | 4179 } |
| 4159 } | 4180 } |
| 4160 | 4181 |
| 4161 | 4182 |
| 4162 void LCodeGen::DoStoreNamedGeneric(LStoreNamedGeneric* instr) { | 4183 void LCodeGen::DoStoreNamedGeneric(LStoreNamedGeneric* instr) { |
| 4184 ASSERT(ToRegister(instr->context()).is(cp)); |
| 4163 ASSERT(ToRegister(instr->object()).is(a1)); | 4185 ASSERT(ToRegister(instr->object()).is(a1)); |
| 4164 ASSERT(ToRegister(instr->value()).is(a0)); | 4186 ASSERT(ToRegister(instr->value()).is(a0)); |
| 4165 | 4187 |
| 4166 // Name is always in a2. | 4188 // Name is always in a2. |
| 4167 __ li(a2, Operand(instr->name())); | 4189 __ li(a2, Operand(instr->name())); |
| 4168 Handle<Code> ic = (instr->strict_mode_flag() == kStrictMode) | 4190 Handle<Code> ic = (instr->strict_mode_flag() == kStrictMode) |
| 4169 ? isolate()->builtins()->StoreIC_Initialize_Strict() | 4191 ? isolate()->builtins()->StoreIC_Initialize_Strict() |
| 4170 : isolate()->builtins()->StoreIC_Initialize(); | 4192 : isolate()->builtins()->StoreIC_Initialize(); |
| 4171 CallCode(ic, RelocInfo::CODE_TARGET, instr); | 4193 CallCode(ic, RelocInfo::CODE_TARGET, instr); |
| 4172 } | 4194 } |
| (...skipping 222 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 4395 DoStoreKeyedExternalArray(instr); | 4417 DoStoreKeyedExternalArray(instr); |
| 4396 } else if (instr->hydrogen()->value()->representation().IsDouble()) { | 4418 } else if (instr->hydrogen()->value()->representation().IsDouble()) { |
| 4397 DoStoreKeyedFixedDoubleArray(instr); | 4419 DoStoreKeyedFixedDoubleArray(instr); |
| 4398 } else { | 4420 } else { |
| 4399 DoStoreKeyedFixedArray(instr); | 4421 DoStoreKeyedFixedArray(instr); |
| 4400 } | 4422 } |
| 4401 } | 4423 } |
| 4402 | 4424 |
| 4403 | 4425 |
| 4404 void LCodeGen::DoStoreKeyedGeneric(LStoreKeyedGeneric* instr) { | 4426 void LCodeGen::DoStoreKeyedGeneric(LStoreKeyedGeneric* instr) { |
| 4427 ASSERT(ToRegister(instr->context()).is(cp)); |
| 4405 ASSERT(ToRegister(instr->object()).is(a2)); | 4428 ASSERT(ToRegister(instr->object()).is(a2)); |
| 4406 ASSERT(ToRegister(instr->key()).is(a1)); | 4429 ASSERT(ToRegister(instr->key()).is(a1)); |
| 4407 ASSERT(ToRegister(instr->value()).is(a0)); | 4430 ASSERT(ToRegister(instr->value()).is(a0)); |
| 4408 | 4431 |
| 4409 Handle<Code> ic = (instr->strict_mode_flag() == kStrictMode) | 4432 Handle<Code> ic = (instr->strict_mode_flag() == kStrictMode) |
| 4410 ? isolate()->builtins()->KeyedStoreIC_Initialize_Strict() | 4433 ? isolate()->builtins()->KeyedStoreIC_Initialize_Strict() |
| 4411 : isolate()->builtins()->KeyedStoreIC_Initialize(); | 4434 : isolate()->builtins()->KeyedStoreIC_Initialize(); |
| 4412 CallCode(ic, RelocInfo::CODE_TARGET, instr); | 4435 CallCode(ic, RelocInfo::CODE_TARGET, instr); |
| 4413 } | 4436 } |
| 4414 | 4437 |
| (...skipping 12 matching lines...) Expand all Loading... |
| 4427 __ Branch(¬_applicable, ne, scratch, Operand(from_map)); | 4450 __ Branch(¬_applicable, ne, scratch, Operand(from_map)); |
| 4428 | 4451 |
| 4429 if (IsSimpleMapChangeTransition(from_kind, to_kind)) { | 4452 if (IsSimpleMapChangeTransition(from_kind, to_kind)) { |
| 4430 Register new_map_reg = ToRegister(instr->new_map_temp()); | 4453 Register new_map_reg = ToRegister(instr->new_map_temp()); |
| 4431 __ li(new_map_reg, Operand(to_map)); | 4454 __ li(new_map_reg, Operand(to_map)); |
| 4432 __ sw(new_map_reg, FieldMemOperand(object_reg, HeapObject::kMapOffset)); | 4455 __ sw(new_map_reg, FieldMemOperand(object_reg, HeapObject::kMapOffset)); |
| 4433 // Write barrier. | 4456 // Write barrier. |
| 4434 __ RecordWriteField(object_reg, HeapObject::kMapOffset, new_map_reg, | 4457 __ RecordWriteField(object_reg, HeapObject::kMapOffset, new_map_reg, |
| 4435 scratch, GetRAState(), kDontSaveFPRegs); | 4458 scratch, GetRAState(), kDontSaveFPRegs); |
| 4436 } else { | 4459 } else { |
| 4460 ASSERT(ToRegister(instr->context()).is(cp)); |
| 4437 PushSafepointRegistersScope scope( | 4461 PushSafepointRegistersScope scope( |
| 4438 this, Safepoint::kWithRegistersAndDoubles); | 4462 this, Safepoint::kWithRegistersAndDoubles); |
| 4439 __ mov(a0, object_reg); | 4463 __ mov(a0, object_reg); |
| 4440 __ li(a1, Operand(to_map)); | 4464 __ li(a1, Operand(to_map)); |
| 4441 TransitionElementsKindStub stub(from_kind, to_kind); | 4465 TransitionElementsKindStub stub(from_kind, to_kind); |
| 4442 __ CallStub(&stub); | 4466 __ CallStub(&stub); |
| 4443 RecordSafepointWithRegistersAndDoubles( | 4467 RecordSafepointWithRegistersAndDoubles( |
| 4444 instr->pointer_map(), 0, Safepoint::kNoLazyDeopt); | 4468 instr->pointer_map(), 0, Safepoint::kNoLazyDeopt); |
| 4445 } | 4469 } |
| 4446 __ bind(¬_applicable); | 4470 __ bind(¬_applicable); |
| 4447 } | 4471 } |
| 4448 | 4472 |
| 4449 | 4473 |
| 4450 void LCodeGen::DoTrapAllocationMemento(LTrapAllocationMemento* instr) { | 4474 void LCodeGen::DoTrapAllocationMemento(LTrapAllocationMemento* instr) { |
| 4451 Register object = ToRegister(instr->object()); | 4475 Register object = ToRegister(instr->object()); |
| 4452 Register temp = ToRegister(instr->temp()); | 4476 Register temp = ToRegister(instr->temp()); |
| 4453 Label fail; | 4477 Label fail; |
| 4454 __ TestJSArrayForAllocationMemento(object, temp, ne, &fail); | 4478 __ TestJSArrayForAllocationMemento(object, temp, ne, &fail); |
| 4455 DeoptimizeIf(al, instr->environment()); | 4479 DeoptimizeIf(al, instr->environment()); |
| 4456 __ bind(&fail); | 4480 __ bind(&fail); |
| 4457 } | 4481 } |
| 4458 | 4482 |
| 4459 | 4483 |
| 4460 void LCodeGen::DoStringAdd(LStringAdd* instr) { | 4484 void LCodeGen::DoStringAdd(LStringAdd* instr) { |
| 4485 ASSERT(ToRegister(instr->context()).is(cp)); |
| 4461 __ push(ToRegister(instr->left())); | 4486 __ push(ToRegister(instr->left())); |
| 4462 __ push(ToRegister(instr->right())); | 4487 __ push(ToRegister(instr->right())); |
| 4463 StringAddStub stub(instr->hydrogen()->flags()); | 4488 StringAddStub stub(instr->hydrogen()->flags()); |
| 4464 CallCode(stub.GetCode(isolate()), RelocInfo::CODE_TARGET, instr); | 4489 CallCode(stub.GetCode(isolate()), RelocInfo::CODE_TARGET, instr); |
| 4465 } | 4490 } |
| 4466 | 4491 |
| 4467 | 4492 |
| 4468 void LCodeGen::DoStringCharCodeAt(LStringCharCodeAt* instr) { | 4493 void LCodeGen::DoStringCharCodeAt(LStringCharCodeAt* instr) { |
| 4469 class DeferredStringCharCodeAt V8_FINAL : public LDeferredCode { | 4494 class DeferredStringCharCodeAt V8_FINAL : public LDeferredCode { |
| 4470 public: | 4495 public: |
| (...skipping 34 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 4505 // DoStringCharCodeAt above. | 4530 // DoStringCharCodeAt above. |
| 4506 if (instr->index()->IsConstantOperand()) { | 4531 if (instr->index()->IsConstantOperand()) { |
| 4507 int const_index = ToInteger32(LConstantOperand::cast(instr->index())); | 4532 int const_index = ToInteger32(LConstantOperand::cast(instr->index())); |
| 4508 __ Addu(scratch, zero_reg, Operand(Smi::FromInt(const_index))); | 4533 __ Addu(scratch, zero_reg, Operand(Smi::FromInt(const_index))); |
| 4509 __ push(scratch); | 4534 __ push(scratch); |
| 4510 } else { | 4535 } else { |
| 4511 Register index = ToRegister(instr->index()); | 4536 Register index = ToRegister(instr->index()); |
| 4512 __ SmiTag(index); | 4537 __ SmiTag(index); |
| 4513 __ push(index); | 4538 __ push(index); |
| 4514 } | 4539 } |
| 4515 CallRuntimeFromDeferred(Runtime::kStringCharCodeAt, 2, instr); | 4540 CallRuntimeFromDeferred(Runtime::kStringCharCodeAt, 2, instr, |
| 4541 instr->context()); |
| 4516 __ AssertSmi(v0); | 4542 __ AssertSmi(v0); |
| 4517 __ SmiUntag(v0); | 4543 __ SmiUntag(v0); |
| 4518 __ StoreToSafepointRegisterSlot(v0, result); | 4544 __ StoreToSafepointRegisterSlot(v0, result); |
| 4519 } | 4545 } |
| 4520 | 4546 |
| 4521 | 4547 |
| 4522 void LCodeGen::DoStringCharFromCode(LStringCharFromCode* instr) { | 4548 void LCodeGen::DoStringCharFromCode(LStringCharFromCode* instr) { |
| 4523 class DeferredStringCharFromCode V8_FINAL : public LDeferredCode { | 4549 class DeferredStringCharFromCode V8_FINAL : public LDeferredCode { |
| 4524 public: | 4550 public: |
| 4525 DeferredStringCharFromCode(LCodeGen* codegen, LStringCharFromCode* instr) | 4551 DeferredStringCharFromCode(LCodeGen* codegen, LStringCharFromCode* instr) |
| (...skipping 32 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 4558 Register result = ToRegister(instr->result()); | 4584 Register result = ToRegister(instr->result()); |
| 4559 | 4585 |
| 4560 // TODO(3095996): Get rid of this. For now, we need to make the | 4586 // TODO(3095996): Get rid of this. For now, we need to make the |
| 4561 // result register contain a valid pointer because it is already | 4587 // result register contain a valid pointer because it is already |
| 4562 // contained in the register pointer map. | 4588 // contained in the register pointer map. |
| 4563 __ mov(result, zero_reg); | 4589 __ mov(result, zero_reg); |
| 4564 | 4590 |
| 4565 PushSafepointRegistersScope scope(this, Safepoint::kWithRegisters); | 4591 PushSafepointRegistersScope scope(this, Safepoint::kWithRegisters); |
| 4566 __ SmiTag(char_code); | 4592 __ SmiTag(char_code); |
| 4567 __ push(char_code); | 4593 __ push(char_code); |
| 4568 CallRuntimeFromDeferred(Runtime::kCharFromCode, 1, instr); | 4594 CallRuntimeFromDeferred(Runtime::kCharFromCode, 1, instr, instr->context()); |
| 4569 __ StoreToSafepointRegisterSlot(v0, result); | 4595 __ StoreToSafepointRegisterSlot(v0, result); |
| 4570 } | 4596 } |
| 4571 | 4597 |
| 4572 | 4598 |
| 4573 void LCodeGen::DoInteger32ToDouble(LInteger32ToDouble* instr) { | 4599 void LCodeGen::DoInteger32ToDouble(LInteger32ToDouble* instr) { |
| 4574 LOperand* input = instr->value(); | 4600 LOperand* input = instr->value(); |
| 4575 ASSERT(input->IsRegister() || input->IsStackSlot()); | 4601 ASSERT(input->IsRegister() || input->IsStackSlot()); |
| 4576 LOperand* output = instr->result(); | 4602 LOperand* output = instr->result(); |
| 4577 ASSERT(output->IsDoubleRegister()); | 4603 ASSERT(output->IsDoubleRegister()); |
| 4578 FPURegister single_scratch = double_scratch0().low(); | 4604 FPURegister single_scratch = double_scratch0().low(); |
| (...skipping 119 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 4698 __ Branch(&done); | 4724 __ Branch(&done); |
| 4699 } | 4725 } |
| 4700 | 4726 |
| 4701 // Slow case: Call the runtime system to do the number allocation. | 4727 // Slow case: Call the runtime system to do the number allocation. |
| 4702 __ bind(&slow); | 4728 __ bind(&slow); |
| 4703 | 4729 |
| 4704 // TODO(3095996): Put a valid pointer value in the stack slot where the result | 4730 // TODO(3095996): Put a valid pointer value in the stack slot where the result |
| 4705 // register is stored, as this register is in the pointer map, but contains an | 4731 // register is stored, as this register is in the pointer map, but contains an |
| 4706 // integer value. | 4732 // integer value. |
| 4707 __ StoreToSafepointRegisterSlot(zero_reg, dst); | 4733 __ StoreToSafepointRegisterSlot(zero_reg, dst); |
| 4708 CallRuntimeFromDeferred(Runtime::kAllocateHeapNumber, 0, instr); | 4734 // NumberTagI and NumberTagD use the context from the frame, rather than |
| 4735 // the environment's HContext or HInlinedContext value. |
| 4736 // They only call Runtime::kAllocateHeapNumber. |
| 4737 // The corresponding HChange instructions are added in a phase that does |
| 4738 // not have easy access to the local context. |
| 4739 __ lw(cp, MemOperand(fp, StandardFrameConstants::kContextOffset)); |
| 4740 __ CallRuntimeSaveDoubles(Runtime::kAllocateHeapNumber); |
| 4741 RecordSafepointWithRegisters( |
| 4742 instr->pointer_map(), 0, Safepoint::kNoLazyDeopt); |
| 4709 __ Move(dst, v0); | 4743 __ Move(dst, v0); |
| 4710 __ Subu(dst, dst, kHeapObjectTag); | 4744 __ Subu(dst, dst, kHeapObjectTag); |
| 4711 | 4745 |
| 4712 // Done. Put the value in dbl_scratch into the value of the allocated heap | 4746 // Done. Put the value in dbl_scratch into the value of the allocated heap |
| 4713 // number. | 4747 // number. |
| 4714 __ bind(&done); | 4748 __ bind(&done); |
| 4715 __ sdc1(dbl_scratch, MemOperand(dst, HeapNumber::kValueOffset)); | 4749 __ sdc1(dbl_scratch, MemOperand(dst, HeapNumber::kValueOffset)); |
| 4716 __ Addu(dst, dst, kHeapObjectTag); | 4750 __ Addu(dst, dst, kHeapObjectTag); |
| 4717 __ StoreToSafepointRegisterSlot(dst, dst); | 4751 __ StoreToSafepointRegisterSlot(dst, dst); |
| 4718 } | 4752 } |
| (...skipping 35 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 4754 | 4788 |
| 4755 | 4789 |
| 4756 void LCodeGen::DoDeferredNumberTagD(LNumberTagD* instr) { | 4790 void LCodeGen::DoDeferredNumberTagD(LNumberTagD* instr) { |
| 4757 // TODO(3095996): Get rid of this. For now, we need to make the | 4791 // TODO(3095996): Get rid of this. For now, we need to make the |
| 4758 // result register contain a valid pointer because it is already | 4792 // result register contain a valid pointer because it is already |
| 4759 // contained in the register pointer map. | 4793 // contained in the register pointer map. |
| 4760 Register reg = ToRegister(instr->result()); | 4794 Register reg = ToRegister(instr->result()); |
| 4761 __ mov(reg, zero_reg); | 4795 __ mov(reg, zero_reg); |
| 4762 | 4796 |
| 4763 PushSafepointRegistersScope scope(this, Safepoint::kWithRegisters); | 4797 PushSafepointRegistersScope scope(this, Safepoint::kWithRegisters); |
| 4764 CallRuntimeFromDeferred(Runtime::kAllocateHeapNumber, 0, instr); | 4798 // NumberTagI and NumberTagD use the context from the frame, rather than |
| 4799 // the environment's HContext or HInlinedContext value. |
| 4800 // They only call Runtime::kAllocateHeapNumber. |
| 4801 // The corresponding HChange instructions are added in a phase that does |
| 4802 // not have easy access to the local context. |
| 4803 __ lw(cp, MemOperand(fp, StandardFrameConstants::kContextOffset)); |
| 4804 __ CallRuntimeSaveDoubles(Runtime::kAllocateHeapNumber); |
| 4805 RecordSafepointWithRegisters( |
| 4806 instr->pointer_map(), 0, Safepoint::kNoLazyDeopt); |
| 4765 __ Subu(v0, v0, kHeapObjectTag); | 4807 __ Subu(v0, v0, kHeapObjectTag); |
| 4766 __ StoreToSafepointRegisterSlot(v0, reg); | 4808 __ StoreToSafepointRegisterSlot(v0, reg); |
| 4767 } | 4809 } |
| 4768 | 4810 |
| 4769 | 4811 |
| 4770 void LCodeGen::DoSmiTag(LSmiTag* instr) { | 4812 void LCodeGen::DoSmiTag(LSmiTag* instr) { |
| 4771 ASSERT(!instr->hydrogen_value()->CheckFlag(HValue::kCanOverflow)); | 4813 ASSERT(!instr->hydrogen_value()->CheckFlag(HValue::kCanOverflow)); |
| 4772 __ SmiTag(ToRegister(instr->result()), ToRegister(instr->value())); | 4814 __ SmiTag(ToRegister(instr->result()), ToRegister(instr->value())); |
| 4773 } | 4815 } |
| 4774 | 4816 |
| (...skipping 324 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 5099 DeoptimizeIf(ne, instr->environment(), reg, | 5141 DeoptimizeIf(ne, instr->environment(), reg, |
| 5100 Operand(object)); | 5142 Operand(object)); |
| 5101 } | 5143 } |
| 5102 } | 5144 } |
| 5103 | 5145 |
| 5104 | 5146 |
| 5105 void LCodeGen::DoDeferredInstanceMigration(LCheckMaps* instr, Register object) { | 5147 void LCodeGen::DoDeferredInstanceMigration(LCheckMaps* instr, Register object) { |
| 5106 { | 5148 { |
| 5107 PushSafepointRegistersScope scope(this, Safepoint::kWithRegisters); | 5149 PushSafepointRegistersScope scope(this, Safepoint::kWithRegisters); |
| 5108 __ push(object); | 5150 __ push(object); |
| 5109 CallRuntimeFromDeferred(Runtime::kMigrateInstance, 1, instr); | 5151 __ mov(cp, zero_reg); |
| 5152 __ CallRuntimeSaveDoubles(Runtime::kMigrateInstance); |
| 5153 RecordSafepointWithRegisters( |
| 5154 instr->pointer_map(), 1, Safepoint::kNoLazyDeopt); |
| 5110 __ StoreToSafepointRegisterSlot(v0, scratch0()); | 5155 __ StoreToSafepointRegisterSlot(v0, scratch0()); |
| 5111 } | 5156 } |
| 5112 __ And(at, scratch0(), Operand(kSmiTagMask)); | 5157 __ And(at, scratch0(), Operand(kSmiTagMask)); |
| 5113 DeoptimizeIf(eq, instr->environment(), at, Operand(zero_reg)); | 5158 DeoptimizeIf(eq, instr->environment(), at, Operand(zero_reg)); |
| 5114 } | 5159 } |
| 5115 | 5160 |
| 5116 | 5161 |
| 5117 void LCodeGen::DoCheckMaps(LCheckMaps* instr) { | 5162 void LCodeGen::DoCheckMaps(LCheckMaps* instr) { |
| 5118 class DeferredCheckMaps V8_FINAL : public LDeferredCode { | 5163 class DeferredCheckMaps V8_FINAL : public LDeferredCode { |
| 5119 public: | 5164 public: |
| (...skipping 177 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 5297 __ SmiTag(size); | 5342 __ SmiTag(size); |
| 5298 __ push(size); | 5343 __ push(size); |
| 5299 } else { | 5344 } else { |
| 5300 int32_t size = ToInteger32(LConstantOperand::cast(instr->size())); | 5345 int32_t size = ToInteger32(LConstantOperand::cast(instr->size())); |
| 5301 __ Push(Smi::FromInt(size)); | 5346 __ Push(Smi::FromInt(size)); |
| 5302 } | 5347 } |
| 5303 | 5348 |
| 5304 if (instr->hydrogen()->IsOldPointerSpaceAllocation()) { | 5349 if (instr->hydrogen()->IsOldPointerSpaceAllocation()) { |
| 5305 ASSERT(!instr->hydrogen()->IsOldDataSpaceAllocation()); | 5350 ASSERT(!instr->hydrogen()->IsOldDataSpaceAllocation()); |
| 5306 ASSERT(!instr->hydrogen()->IsNewSpaceAllocation()); | 5351 ASSERT(!instr->hydrogen()->IsNewSpaceAllocation()); |
| 5307 CallRuntimeFromDeferred(Runtime::kAllocateInOldPointerSpace, 1, instr); | 5352 CallRuntimeFromDeferred(Runtime::kAllocateInOldPointerSpace, 1, instr, |
| 5353 instr->context()); |
| 5308 } else if (instr->hydrogen()->IsOldDataSpaceAllocation()) { | 5354 } else if (instr->hydrogen()->IsOldDataSpaceAllocation()) { |
| 5309 ASSERT(!instr->hydrogen()->IsNewSpaceAllocation()); | 5355 ASSERT(!instr->hydrogen()->IsNewSpaceAllocation()); |
| 5310 CallRuntimeFromDeferred(Runtime::kAllocateInOldDataSpace, 1, instr); | 5356 CallRuntimeFromDeferred(Runtime::kAllocateInOldDataSpace, 1, instr, |
| 5357 instr->context()); |
| 5311 } else { | 5358 } else { |
| 5312 CallRuntimeFromDeferred(Runtime::kAllocateInNewSpace, 1, instr); | 5359 CallRuntimeFromDeferred(Runtime::kAllocateInNewSpace, 1, instr, |
| 5360 instr->context()); |
| 5313 } | 5361 } |
| 5314 __ StoreToSafepointRegisterSlot(v0, result); | 5362 __ StoreToSafepointRegisterSlot(v0, result); |
| 5315 } | 5363 } |
| 5316 | 5364 |
| 5317 | 5365 |
| 5318 void LCodeGen::DoToFastProperties(LToFastProperties* instr) { | 5366 void LCodeGen::DoToFastProperties(LToFastProperties* instr) { |
| 5319 ASSERT(ToRegister(instr->value()).is(a0)); | 5367 ASSERT(ToRegister(instr->value()).is(a0)); |
| 5320 ASSERT(ToRegister(instr->result()).is(v0)); | 5368 ASSERT(ToRegister(instr->result()).is(v0)); |
| 5321 __ push(a0); | 5369 __ push(a0); |
| 5322 CallRuntime(Runtime::kToFastProperties, 1, instr); | 5370 CallRuntime(Runtime::kToFastProperties, 1, instr); |
| 5323 } | 5371 } |
| 5324 | 5372 |
| 5325 | 5373 |
| 5326 void LCodeGen::DoRegExpLiteral(LRegExpLiteral* instr) { | 5374 void LCodeGen::DoRegExpLiteral(LRegExpLiteral* instr) { |
| 5375 ASSERT(ToRegister(instr->context()).is(cp)); |
| 5327 Label materialized; | 5376 Label materialized; |
| 5328 // Registers will be used as follows: | 5377 // Registers will be used as follows: |
| 5329 // t3 = literals array. | 5378 // t3 = literals array. |
| 5330 // a1 = regexp literal. | 5379 // a1 = regexp literal. |
| 5331 // a0 = regexp literal clone. | 5380 // a0 = regexp literal clone. |
| 5332 // a2 and t0-t2 are used as temporaries. | 5381 // a2 and t0-t2 are used as temporaries. |
| 5333 int literal_offset = | 5382 int literal_offset = |
| 5334 FixedArray::OffsetOfElementAt(instr->hydrogen()->literal_index()); | 5383 FixedArray::OffsetOfElementAt(instr->hydrogen()->literal_index()); |
| 5335 __ LoadHeapObject(t3, instr->hydrogen()->literals()); | 5384 __ LoadHeapObject(t3, instr->hydrogen()->literals()); |
| 5336 __ lw(a1, FieldMemOperand(t3, literal_offset)); | 5385 __ lw(a1, FieldMemOperand(t3, literal_offset)); |
| (...skipping 32 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 5369 __ sw(a2, FieldMemOperand(v0, i + kPointerSize)); | 5418 __ sw(a2, FieldMemOperand(v0, i + kPointerSize)); |
| 5370 } | 5419 } |
| 5371 if ((size % (2 * kPointerSize)) != 0) { | 5420 if ((size % (2 * kPointerSize)) != 0) { |
| 5372 __ lw(a3, FieldMemOperand(a1, size - kPointerSize)); | 5421 __ lw(a3, FieldMemOperand(a1, size - kPointerSize)); |
| 5373 __ sw(a3, FieldMemOperand(v0, size - kPointerSize)); | 5422 __ sw(a3, FieldMemOperand(v0, size - kPointerSize)); |
| 5374 } | 5423 } |
| 5375 } | 5424 } |
| 5376 | 5425 |
| 5377 | 5426 |
| 5378 void LCodeGen::DoFunctionLiteral(LFunctionLiteral* instr) { | 5427 void LCodeGen::DoFunctionLiteral(LFunctionLiteral* instr) { |
| 5428 ASSERT(ToRegister(instr->context()).is(cp)); |
| 5379 // Use the fast case closure allocation code that allocates in new | 5429 // Use the fast case closure allocation code that allocates in new |
| 5380 // space for nested functions that don't need literals cloning. | 5430 // space for nested functions that don't need literals cloning. |
| 5381 bool pretenure = instr->hydrogen()->pretenure(); | 5431 bool pretenure = instr->hydrogen()->pretenure(); |
| 5382 if (!pretenure && instr->hydrogen()->has_no_literals()) { | 5432 if (!pretenure && instr->hydrogen()->has_no_literals()) { |
| 5383 FastNewClosureStub stub(instr->hydrogen()->language_mode(), | 5433 FastNewClosureStub stub(instr->hydrogen()->language_mode(), |
| 5384 instr->hydrogen()->is_generator()); | 5434 instr->hydrogen()->is_generator()); |
| 5385 __ li(a2, Operand(instr->hydrogen()->shared_info())); | 5435 __ li(a2, Operand(instr->hydrogen()->shared_info())); |
| 5386 CallCode(stub.GetCode(isolate()), RelocInfo::CODE_TARGET, instr); | 5436 CallCode(stub.GetCode(isolate()), RelocInfo::CODE_TARGET, instr); |
| 5387 } else { | 5437 } else { |
| 5388 __ li(a2, Operand(instr->hydrogen()->shared_info())); | 5438 __ li(a2, Operand(instr->hydrogen()->shared_info())); |
| (...skipping 162 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 5551 __ Branch(&check_frame_marker, ne, temp2, | 5601 __ Branch(&check_frame_marker, ne, temp2, |
| 5552 Operand(Smi::FromInt(StackFrame::ARGUMENTS_ADAPTOR))); | 5602 Operand(Smi::FromInt(StackFrame::ARGUMENTS_ADAPTOR))); |
| 5553 __ lw(temp1, MemOperand(temp1, StandardFrameConstants::kCallerFPOffset)); | 5603 __ lw(temp1, MemOperand(temp1, StandardFrameConstants::kCallerFPOffset)); |
| 5554 | 5604 |
| 5555 // Check the marker in the calling frame. | 5605 // Check the marker in the calling frame. |
| 5556 __ bind(&check_frame_marker); | 5606 __ bind(&check_frame_marker); |
| 5557 __ lw(temp1, MemOperand(temp1, StandardFrameConstants::kMarkerOffset)); | 5607 __ lw(temp1, MemOperand(temp1, StandardFrameConstants::kMarkerOffset)); |
| 5558 } | 5608 } |
| 5559 | 5609 |
| 5560 | 5610 |
| 5561 void LCodeGen::EnsureSpaceForLazyDeopt() { | 5611 void LCodeGen::EnsureSpaceForLazyDeopt(int space_needed) { |
| 5562 if (info()->IsStub()) return; | 5612 if (info()->IsStub()) return; |
| 5563 // Ensure that we have enough space after the previous lazy-bailout | 5613 // Ensure that we have enough space after the previous lazy-bailout |
| 5564 // instruction for patching the code here. | 5614 // instruction for patching the code here. |
| 5565 int current_pc = masm()->pc_offset(); | 5615 int current_pc = masm()->pc_offset(); |
| 5566 int patch_size = Deoptimizer::patch_size(); | 5616 if (current_pc < last_lazy_deopt_pc_ + space_needed) { |
| 5567 if (current_pc < last_lazy_deopt_pc_ + patch_size) { | 5617 int padding_size = last_lazy_deopt_pc_ + space_needed - current_pc; |
| 5568 int padding_size = last_lazy_deopt_pc_ + patch_size - current_pc; | |
| 5569 ASSERT_EQ(0, padding_size % Assembler::kInstrSize); | 5618 ASSERT_EQ(0, padding_size % Assembler::kInstrSize); |
| 5570 while (padding_size > 0) { | 5619 while (padding_size > 0) { |
| 5571 __ nop(); | 5620 __ nop(); |
| 5572 padding_size -= Assembler::kInstrSize; | 5621 padding_size -= Assembler::kInstrSize; |
| 5573 } | 5622 } |
| 5574 } | 5623 } |
| 5575 } | 5624 } |
| 5576 | 5625 |
| 5577 | 5626 |
| 5578 void LCodeGen::DoLazyBailout(LLazyBailout* instr) { | 5627 void LCodeGen::DoLazyBailout(LLazyBailout* instr) { |
| 5579 EnsureSpaceForLazyDeopt(); | 5628 EnsureSpaceForLazyDeopt(Deoptimizer::patch_size()); |
| 5580 last_lazy_deopt_pc_ = masm()->pc_offset(); | 5629 last_lazy_deopt_pc_ = masm()->pc_offset(); |
| 5581 ASSERT(instr->HasEnvironment()); | 5630 ASSERT(instr->HasEnvironment()); |
| 5582 LEnvironment* env = instr->environment(); | 5631 LEnvironment* env = instr->environment(); |
| 5583 RegisterEnvironmentForDeoptimization(env, Safepoint::kLazyDeopt); | 5632 RegisterEnvironmentForDeoptimization(env, Safepoint::kLazyDeopt); |
| 5584 safepoints_.RecordLazyDeoptimizationIndex(env->deoptimization_index()); | 5633 safepoints_.RecordLazyDeoptimizationIndex(env->deoptimization_index()); |
| 5585 } | 5634 } |
| 5586 | 5635 |
| 5587 | 5636 |
| 5588 void LCodeGen::DoDeoptimize(LDeoptimize* instr) { | 5637 void LCodeGen::DoDeoptimize(LDeoptimize* instr) { |
| 5589 Deoptimizer::BailoutType type = instr->hydrogen()->type(); | 5638 Deoptimizer::BailoutType type = instr->hydrogen()->type(); |
| (...skipping 10 matching lines...) Expand all Loading... |
| 5600 } | 5649 } |
| 5601 | 5650 |
| 5602 | 5651 |
| 5603 void LCodeGen::DoDummyUse(LDummyUse* instr) { | 5652 void LCodeGen::DoDummyUse(LDummyUse* instr) { |
| 5604 // Nothing to see here, move on! | 5653 // Nothing to see here, move on! |
| 5605 } | 5654 } |
| 5606 | 5655 |
| 5607 | 5656 |
| 5608 void LCodeGen::DoDeferredStackCheck(LStackCheck* instr) { | 5657 void LCodeGen::DoDeferredStackCheck(LStackCheck* instr) { |
| 5609 PushSafepointRegistersScope scope(this, Safepoint::kWithRegisters); | 5658 PushSafepointRegistersScope scope(this, Safepoint::kWithRegisters); |
| 5659 LoadContextFromDeferred(instr->context()); |
| 5610 __ CallRuntimeSaveDoubles(Runtime::kStackGuard); | 5660 __ CallRuntimeSaveDoubles(Runtime::kStackGuard); |
| 5611 RecordSafepointWithLazyDeopt( | 5661 RecordSafepointWithLazyDeopt( |
| 5612 instr, RECORD_SAFEPOINT_WITH_REGISTERS_AND_NO_ARGUMENTS); | 5662 instr, RECORD_SAFEPOINT_WITH_REGISTERS_AND_NO_ARGUMENTS); |
| 5613 ASSERT(instr->HasEnvironment()); | 5663 ASSERT(instr->HasEnvironment()); |
| 5614 LEnvironment* env = instr->environment(); | 5664 LEnvironment* env = instr->environment(); |
| 5615 safepoints_.RecordLazyDeoptimizationIndex(env->deoptimization_index()); | 5665 safepoints_.RecordLazyDeoptimizationIndex(env->deoptimization_index()); |
| 5616 } | 5666 } |
| 5617 | 5667 |
| 5618 | 5668 |
| 5619 void LCodeGen::DoStackCheck(LStackCheck* instr) { | 5669 void LCodeGen::DoStackCheck(LStackCheck* instr) { |
| (...skipping 11 matching lines...) Expand all Loading... |
| 5631 | 5681 |
| 5632 ASSERT(instr->HasEnvironment()); | 5682 ASSERT(instr->HasEnvironment()); |
| 5633 LEnvironment* env = instr->environment(); | 5683 LEnvironment* env = instr->environment(); |
| 5634 // There is no LLazyBailout instruction for stack-checks. We have to | 5684 // There is no LLazyBailout instruction for stack-checks. We have to |
| 5635 // prepare for lazy deoptimization explicitly here. | 5685 // prepare for lazy deoptimization explicitly here. |
| 5636 if (instr->hydrogen()->is_function_entry()) { | 5686 if (instr->hydrogen()->is_function_entry()) { |
| 5637 // Perform stack overflow check. | 5687 // Perform stack overflow check. |
| 5638 Label done; | 5688 Label done; |
| 5639 __ LoadRoot(at, Heap::kStackLimitRootIndex); | 5689 __ LoadRoot(at, Heap::kStackLimitRootIndex); |
| 5640 __ Branch(&done, hs, sp, Operand(at)); | 5690 __ Branch(&done, hs, sp, Operand(at)); |
| 5691 ASSERT(instr->context()->IsRegister()); |
| 5692 ASSERT(ToRegister(instr->context()).is(cp)); |
| 5641 CallCode(isolate()->builtins()->StackCheck(), | 5693 CallCode(isolate()->builtins()->StackCheck(), |
| 5642 RelocInfo::CODE_TARGET, | 5694 RelocInfo::CODE_TARGET, |
| 5643 instr); | 5695 instr); |
| 5644 EnsureSpaceForLazyDeopt(); | 5696 EnsureSpaceForLazyDeopt(Deoptimizer::patch_size()); |
| 5645 last_lazy_deopt_pc_ = masm()->pc_offset(); | 5697 last_lazy_deopt_pc_ = masm()->pc_offset(); |
| 5646 __ bind(&done); | 5698 __ bind(&done); |
| 5647 RegisterEnvironmentForDeoptimization(env, Safepoint::kLazyDeopt); | 5699 RegisterEnvironmentForDeoptimization(env, Safepoint::kLazyDeopt); |
| 5648 safepoints_.RecordLazyDeoptimizationIndex(env->deoptimization_index()); | 5700 safepoints_.RecordLazyDeoptimizationIndex(env->deoptimization_index()); |
| 5649 } else { | 5701 } else { |
| 5650 ASSERT(instr->hydrogen()->is_backwards_branch()); | 5702 ASSERT(instr->hydrogen()->is_backwards_branch()); |
| 5651 // Perform stack overflow check if this goto needs it before jumping. | 5703 // Perform stack overflow check if this goto needs it before jumping. |
| 5652 DeferredStackCheck* deferred_stack_check = | 5704 DeferredStackCheck* deferred_stack_check = |
| 5653 new(zone()) DeferredStackCheck(this, instr); | 5705 new(zone()) DeferredStackCheck(this, instr); |
| 5654 __ LoadRoot(at, Heap::kStackLimitRootIndex); | 5706 __ LoadRoot(at, Heap::kStackLimitRootIndex); |
| 5655 __ Branch(deferred_stack_check->entry(), lo, sp, Operand(at)); | 5707 __ Branch(deferred_stack_check->entry(), lo, sp, Operand(at)); |
| 5656 EnsureSpaceForLazyDeopt(); | 5708 EnsureSpaceForLazyDeopt(Deoptimizer::patch_size()); |
| 5657 last_lazy_deopt_pc_ = masm()->pc_offset(); | 5709 last_lazy_deopt_pc_ = masm()->pc_offset(); |
| 5658 __ bind(instr->done_label()); | 5710 __ bind(instr->done_label()); |
| 5659 deferred_stack_check->SetExit(instr->done_label()); | 5711 deferred_stack_check->SetExit(instr->done_label()); |
| 5660 RegisterEnvironmentForDeoptimization(env, Safepoint::kLazyDeopt); | 5712 RegisterEnvironmentForDeoptimization(env, Safepoint::kLazyDeopt); |
| 5661 // Don't record a deoptimization index for the safepoint here. | 5713 // Don't record a deoptimization index for the safepoint here. |
| 5662 // This will be done explicitly when emitting call and the safepoint in | 5714 // This will be done explicitly when emitting call and the safepoint in |
| 5663 // the deferred code. | 5715 // the deferred code. |
| 5664 } | 5716 } |
| 5665 } | 5717 } |
| 5666 | 5718 |
| (...skipping 101 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 5768 __ Subu(scratch, result, scratch); | 5820 __ Subu(scratch, result, scratch); |
| 5769 __ lw(result, FieldMemOperand(scratch, | 5821 __ lw(result, FieldMemOperand(scratch, |
| 5770 FixedArray::kHeaderSize - kPointerSize)); | 5822 FixedArray::kHeaderSize - kPointerSize)); |
| 5771 __ bind(&done); | 5823 __ bind(&done); |
| 5772 } | 5824 } |
| 5773 | 5825 |
| 5774 | 5826 |
| 5775 #undef __ | 5827 #undef __ |
| 5776 | 5828 |
| 5777 } } // namespace v8::internal | 5829 } } // namespace v8::internal |
| OLD | NEW |