Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(1623)

Side by Side Diff: src/mips/lithium-codegen-mips.cc

Issue 145773008: A64: Synchronize with r17104. (Closed) Base URL: https://v8.googlecode.com/svn/branches/experimental/a64
Patch Set: Created 6 years, 10 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
« no previous file with comments | « src/mips/lithium-codegen-mips.h ('k') | src/mips/lithium-mips.h » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
4427 __ Branch(&not_applicable, ne, scratch, Operand(from_map)); 4450 __ Branch(&not_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(&not_applicable); 4470 __ bind(&not_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
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
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
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
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
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
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
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
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
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
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
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
OLDNEW
« no previous file with comments | « src/mips/lithium-codegen-mips.h ('k') | src/mips/lithium-mips.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698