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

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

Issue 6606002: Merge revision 6500-6600 from bleeding_edge to the isolates branch. (Closed) Base URL: http://v8.googlecode.com/svn/branches/experimental/isolates/
Patch Set: '' Created 9 years, 9 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
OLDNEW
1 // Copyright 2011 the V8 project authors. All rights reserved. 1 // Copyright 2011 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 544 matching lines...) Expand 10 before | Expand all | Expand 10 after
555 translation->StoreLiteral(src_index); 555 translation->StoreLiteral(src_index);
556 } else { 556 } else {
557 UNREACHABLE(); 557 UNREACHABLE();
558 } 558 }
559 } 559 }
560 560
561 561
562 void LCodeGen::CallCode(Handle<Code> code, 562 void LCodeGen::CallCode(Handle<Code> code,
563 RelocInfo::Mode mode, 563 RelocInfo::Mode mode,
564 LInstruction* instr) { 564 LInstruction* instr) {
565 if (instr != NULL) { 565 ASSERT(instr != NULL);
566 LPointerMap* pointers = instr->pointer_map(); 566 LPointerMap* pointers = instr->pointer_map();
567 RecordPosition(pointers->position()); 567 RecordPosition(pointers->position());
568 __ Call(code, mode); 568 __ Call(code, mode);
569 RegisterLazyDeoptimization(instr); 569 RegisterLazyDeoptimization(instr);
570 } else {
571 LPointerMap no_pointers(0);
572 RecordPosition(no_pointers.position());
573 __ Call(code, mode);
574 RecordSafepoint(&no_pointers, Safepoint::kNoDeoptimizationIndex);
575 }
576 } 570 }
577 571
578 572
579 void LCodeGen::CallRuntime(const Runtime::Function* function, 573 void LCodeGen::CallRuntime(const Runtime::Function* function,
580 int num_arguments, 574 int num_arguments,
581 LInstruction* instr) { 575 LInstruction* instr) {
582 ASSERT(instr != NULL); 576 ASSERT(instr != NULL);
583 LPointerMap* pointers = instr->pointer_map(); 577 LPointerMap* pointers = instr->pointer_map();
584 ASSERT(pointers != NULL); 578 ASSERT(pointers != NULL);
585 RecordPosition(pointers->position()); 579 RecordPosition(pointers->position());
586 580
587 __ CallRuntime(function, num_arguments); 581 __ CallRuntime(function, num_arguments);
588 // Runtime calls to Throw are not supposed to ever return at the 582 RegisterLazyDeoptimization(instr);
589 // call site, so don't register lazy deoptimization for these. We do
590 // however have to record a safepoint since throwing exceptions can
591 // cause garbage collections.
592 if (!instr->IsThrow()) {
593 RegisterLazyDeoptimization(instr);
594 } else {
595 RecordSafepoint(instr->pointer_map(), Safepoint::kNoDeoptimizationIndex);
596 }
597 } 583 }
598 584
599 585
600 void LCodeGen::RegisterLazyDeoptimization(LInstruction* instr) { 586 void LCodeGen::RegisterLazyDeoptimization(LInstruction* instr) {
601 // Create the environment to bailout to. If the call has side effects 587 // Create the environment to bailout to. If the call has side effects
602 // execution has to continue after the call otherwise execution can continue 588 // execution has to continue after the call otherwise execution can continue
603 // from a previous bailout point repeating the call. 589 // from a previous bailout point repeating the call.
604 LEnvironment* deoptimization_environment; 590 LEnvironment* deoptimization_environment;
605 if (instr->HasDeoptimizationEnvironment()) { 591 if (instr->HasDeoptimizationEnvironment()) {
606 deoptimization_environment = instr->deoptimization_environment(); 592 deoptimization_environment = instr->deoptimization_environment();
(...skipping 122 matching lines...) Expand 10 before | Expand all | Expand 10 after
729 for (int i = 0, length = inlined_closures->length(); 715 for (int i = 0, length = inlined_closures->length();
730 i < length; 716 i < length;
731 i++) { 717 i++) {
732 DefineDeoptimizationLiteral(inlined_closures->at(i)); 718 DefineDeoptimizationLiteral(inlined_closures->at(i));
733 } 719 }
734 720
735 inlined_function_count_ = deoptimization_literals_.length(); 721 inlined_function_count_ = deoptimization_literals_.length();
736 } 722 }
737 723
738 724
725 void LCodeGen::RecordSafepoint(
726 LPointerMap* pointers,
727 Safepoint::Kind kind,
728 int arguments,
729 int deoptimization_index) {
730 const ZoneList<LOperand*>* operands = pointers->operands();
731 Safepoint safepoint = safepoints_.DefineSafepoint(masm(),
732 kind, arguments, deoptimization_index);
733 for (int i = 0; i < operands->length(); i++) {
734 LOperand* pointer = operands->at(i);
735 if (pointer->IsStackSlot()) {
736 safepoint.DefinePointerSlot(pointer->index());
737 } else if (pointer->IsRegister() && (kind & Safepoint::kWithRegisters)) {
738 safepoint.DefinePointerRegister(ToRegister(pointer));
739 }
740 }
741 if (kind & Safepoint::kWithRegisters) {
742 // Register cp always contains a pointer to the context.
743 safepoint.DefinePointerRegister(cp);
744 }
745 }
746
747
739 void LCodeGen::RecordSafepoint(LPointerMap* pointers, 748 void LCodeGen::RecordSafepoint(LPointerMap* pointers,
740 int deoptimization_index) { 749 int deoptimization_index) {
741 const ZoneList<LOperand*>* operands = pointers->operands(); 750 RecordSafepoint(pointers, Safepoint::kSimple, 0, deoptimization_index);
742 Safepoint safepoint = safepoints_.DefineSafepoint(masm(),
743 deoptimization_index);
744 for (int i = 0; i < operands->length(); i++) {
745 LOperand* pointer = operands->at(i);
746 if (pointer->IsStackSlot()) {
747 safepoint.DefinePointerSlot(pointer->index());
748 }
749 }
750 } 751 }
751 752
752 753
753 void LCodeGen::RecordSafepointWithRegisters(LPointerMap* pointers, 754 void LCodeGen::RecordSafepointWithRegisters(LPointerMap* pointers,
754 int arguments, 755 int arguments,
755 int deoptimization_index) { 756 int deoptimization_index) {
756 const ZoneList<LOperand*>* operands = pointers->operands(); 757 RecordSafepoint(pointers, Safepoint::kWithRegisters, arguments,
757 Safepoint safepoint = 758 deoptimization_index);
758 safepoints_.DefineSafepointWithRegisters(
759 masm(), arguments, deoptimization_index);
760 for (int i = 0; i < operands->length(); i++) {
761 LOperand* pointer = operands->at(i);
762 if (pointer->IsStackSlot()) {
763 safepoint.DefinePointerSlot(pointer->index());
764 } else if (pointer->IsRegister()) {
765 safepoint.DefinePointerRegister(ToRegister(pointer));
766 }
767 }
768 // Register cp always contains a pointer to the context.
769 safepoint.DefinePointerRegister(cp);
770 } 759 }
771 760
772 761
773 void LCodeGen::RecordSafepointWithRegistersAndDoubles( 762 void LCodeGen::RecordSafepointWithRegistersAndDoubles(
774 LPointerMap* pointers, 763 LPointerMap* pointers,
775 int arguments, 764 int arguments,
776 int deoptimization_index) { 765 int deoptimization_index) {
777 const ZoneList<LOperand*>* operands = pointers->operands(); 766 RecordSafepoint(pointers, Safepoint::kWithRegistersAndDoubles, arguments,
778 Safepoint safepoint = 767 deoptimization_index);
779 safepoints_.DefineSafepointWithRegistersAndDoubles(
780 masm(), arguments, deoptimization_index);
781 for (int i = 0; i < operands->length(); i++) {
782 LOperand* pointer = operands->at(i);
783 if (pointer->IsStackSlot()) {
784 safepoint.DefinePointerSlot(pointer->index());
785 } else if (pointer->IsRegister()) {
786 safepoint.DefinePointerRegister(ToRegister(pointer));
787 }
788 }
789 // Register cp always contains a pointer to the context.
790 safepoint.DefinePointerRegister(cp);
791 } 768 }
792 769
793 770
794 void LCodeGen::RecordPosition(int position) { 771 void LCodeGen::RecordPosition(int position) {
795 if (!FLAG_debug_info || position == RelocInfo::kNoPosition) return; 772 if (!FLAG_debug_info || position == RelocInfo::kNoPosition) return;
796 masm()->positions_recorder()->RecordPosition(position); 773 masm()->positions_recorder()->RecordPosition(position);
797 } 774 }
798 775
799 776
800 void LCodeGen::DoLabel(LLabel* label) { 777 void LCodeGen::DoLabel(LLabel* label) {
(...skipping 254 matching lines...) Expand 10 before | Expand all | Expand 10 after
1055 // the right hand side. 1032 // the right hand side.
1056 __ cmp(scratch, right); 1033 __ cmp(scratch, right);
1057 __ mov(result, scratch, LeaveCC, lt); 1034 __ mov(result, scratch, LeaveCC, lt);
1058 __ b(lt, &done); 1035 __ b(lt, &done);
1059 // If not, reduce the left hand side by the right hand 1036 // If not, reduce the left hand side by the right hand
1060 // side and check again. 1037 // side and check again.
1061 if (i < kUnfolds - 1) __ sub(scratch, scratch, right); 1038 if (i < kUnfolds - 1) __ sub(scratch, scratch, right);
1062 } 1039 }
1063 1040
1064 // Check for power of two on the right hand side. 1041 // Check for power of two on the right hand side.
1065 __ sub(scratch, right, Operand(1), SetCC); 1042 __ JumpIfNotPowerOfTwoOrZero(right, scratch, &call_stub);
1066 __ b(mi, &call_stub); 1043 // Perform modulo operation (scratch contains right - 1).
1067 __ tst(scratch, right);
1068 __ b(ne, &call_stub);
1069 // Perform modulo operation.
1070 __ and_(result, scratch, Operand(left)); 1044 __ and_(result, scratch, Operand(left));
1071 1045
1072 __ bind(&call_stub); 1046 __ bind(&call_stub);
1073 // Call the generic stub. The numbers in r0 and r1 have 1047 // Call the generic stub. The numbers in r0 and r1 have
1074 // to be tagged to Smis. If that is not possible, deoptimize. 1048 // to be tagged to Smis. If that is not possible, deoptimize.
1075 DeferredModI* deferred = new DeferredModI(this, instr); 1049 DeferredModI* deferred = new DeferredModI(this, instr);
1076 __ TrySmiTag(left, &deoptimize, scratch); 1050 __ TrySmiTag(left, &deoptimize, scratch);
1077 __ TrySmiTag(right, &deoptimize, scratch); 1051 __ TrySmiTag(right, &deoptimize, scratch);
1078 1052
1079 __ b(al, deferred->entry()); 1053 __ b(al, deferred->entry());
(...skipping 96 matching lines...) Expand 10 before | Expand all | Expand 10 after
1176 Register left = ToRegister(instr->InputAt(0)); 1150 Register left = ToRegister(instr->InputAt(0));
1177 Register right = ToRegister(instr->InputAt(1)); 1151 Register right = ToRegister(instr->InputAt(1));
1178 1152
1179 __ PushSafepointRegistersAndDoubles(); 1153 __ PushSafepointRegistersAndDoubles();
1180 GenericBinaryOpStub stub(op, OVERWRITE_LEFT, left, right); 1154 GenericBinaryOpStub stub(op, OVERWRITE_LEFT, left, right);
1181 __ CallStub(&stub); 1155 __ CallStub(&stub);
1182 RecordSafepointWithRegistersAndDoubles(instr->pointer_map(), 1156 RecordSafepointWithRegistersAndDoubles(instr->pointer_map(),
1183 0, 1157 0,
1184 Safepoint::kNoDeoptimizationIndex); 1158 Safepoint::kNoDeoptimizationIndex);
1185 // Overwrite the stored value of r0 with the result of the stub. 1159 // Overwrite the stored value of r0 with the result of the stub.
1186 __ str(r0, MemOperand(sp, DwVfpRegister::kNumAllocatableRegisters * 1160 __ StoreToSafepointRegistersAndDoublesSlot(r0);
1187 kDoubleSize));
1188 __ PopSafepointRegistersAndDoubles(); 1161 __ PopSafepointRegistersAndDoubles();
1189 } 1162 }
1190 1163
1191 1164
1192 void LCodeGen::DoMulI(LMulI* instr) { 1165 void LCodeGen::DoMulI(LMulI* instr) {
1193 Register scratch = scratch0(); 1166 Register scratch = scratch0();
1194 Register left = ToRegister(instr->InputAt(0)); 1167 Register left = ToRegister(instr->InputAt(0));
1195 Register right = EmitLoadRegister(instr->InputAt(1), scratch); 1168 Register right = EmitLoadRegister(instr->InputAt(1), scratch);
1196 1169
1197 if (instr->hydrogen()->CheckFlag(HValue::kBailoutOnMinusZero) && 1170 if (instr->hydrogen()->CheckFlag(HValue::kBailoutOnMinusZero) &&
(...skipping 220 matching lines...) Expand 10 before | Expand all | Expand 10 after
1418 case Token::SUB: 1391 case Token::SUB:
1419 __ vsub(left, left, right); 1392 __ vsub(left, left, right);
1420 break; 1393 break;
1421 case Token::MUL: 1394 case Token::MUL:
1422 __ vmul(left, left, right); 1395 __ vmul(left, left, right);
1423 break; 1396 break;
1424 case Token::DIV: 1397 case Token::DIV:
1425 __ vdiv(left, left, right); 1398 __ vdiv(left, left, right);
1426 break; 1399 break;
1427 case Token::MOD: { 1400 case Token::MOD: {
1428 Abort("DoArithmeticD unimplemented for MOD."); 1401 // Save r0-r3 on the stack.
1402 __ stm(db_w, sp, r0.bit() | r1.bit() | r2.bit() | r3.bit());
1403
1404 __ PrepareCallCFunction(4, scratch0());
1405 __ vmov(r0, r1, left);
1406 __ vmov(r2, r3, right);
1407 __ CallCFunction(ExternalReference::double_fp_operation(Token::MOD), 4);
1408 // Move the result in the double result register.
1409 __ vmov(ToDoubleRegister(instr->result()), r0, r1);
1410
1411 // Restore r0-r3.
1412 __ ldm(ia_w, sp, r0.bit() | r1.bit() | r2.bit() | r3.bit());
1429 break; 1413 break;
1430 } 1414 }
1431 default: 1415 default:
1432 UNREACHABLE(); 1416 UNREACHABLE();
1433 break; 1417 break;
1434 } 1418 }
1435 } 1419 }
1436 1420
1437 1421
1438 void LCodeGen::DoArithmeticT(LArithmeticT* instr) { 1422 void LCodeGen::DoArithmeticT(LArithmeticT* instr) {
(...skipping 554 matching lines...) Expand 10 before | Expand all | Expand 10 after
1993 CallCode(stub.GetCode(), RelocInfo::CODE_TARGET, instr); 1977 CallCode(stub.GetCode(), RelocInfo::CODE_TARGET, instr);
1994 1978
1995 Label true_value, done; 1979 Label true_value, done;
1996 __ tst(r0, r0); 1980 __ tst(r0, r0);
1997 __ mov(r0, Operand(FACTORY->false_value()), LeaveCC, ne); 1981 __ mov(r0, Operand(FACTORY->false_value()), LeaveCC, ne);
1998 __ mov(r0, Operand(FACTORY->true_value()), LeaveCC, eq); 1982 __ mov(r0, Operand(FACTORY->true_value()), LeaveCC, eq);
1999 } 1983 }
2000 1984
2001 1985
2002 void LCodeGen::DoInstanceOfAndBranch(LInstanceOfAndBranch* instr) { 1986 void LCodeGen::DoInstanceOfAndBranch(LInstanceOfAndBranch* instr) {
2003 Abort("DoInstanceOfAndBranch unimplemented."); 1987 ASSERT(ToRegister(instr->InputAt(0)).is(r0)); // Object is in r0.
1988 ASSERT(ToRegister(instr->InputAt(1)).is(r1)); // Function is in r1.
1989
1990 int true_block = chunk_->LookupDestination(instr->true_block_id());
1991 int false_block = chunk_->LookupDestination(instr->false_block_id());
1992
1993 InstanceofStub stub(InstanceofStub::kArgsInRegisters);
1994 CallCode(stub.GetCode(), RelocInfo::CODE_TARGET, instr);
1995 __ tst(r0, Operand(r0));
1996 EmitBranch(true_block, false_block, eq);
2004 } 1997 }
2005 1998
2006 1999
2007 void LCodeGen::DoInstanceOfKnownGlobal(LInstanceOfKnownGlobal* instr) { 2000 void LCodeGen::DoInstanceOfKnownGlobal(LInstanceOfKnownGlobal* instr) {
2008 class DeferredInstanceOfKnownGlobal: public LDeferredCode { 2001 class DeferredInstanceOfKnownGlobal: public LDeferredCode {
2009 public: 2002 public:
2010 DeferredInstanceOfKnownGlobal(LCodeGen* codegen, 2003 DeferredInstanceOfKnownGlobal(LCodeGen* codegen,
2011 LInstanceOfKnownGlobal* instr) 2004 LInstanceOfKnownGlobal* instr)
2012 : LDeferredCode(codegen), instr_(instr) { } 2005 : LDeferredCode(codegen), instr_(instr) { }
2013 virtual void Generate() { 2006 virtual void Generate() {
(...skipping 174 matching lines...) Expand 10 before | Expand all | Expand 10 after
2188 if (instr->hydrogen()->check_hole_value()) { 2181 if (instr->hydrogen()->check_hole_value()) {
2189 __ LoadRoot(ip, Heap::kTheHoleValueRootIndex); 2182 __ LoadRoot(ip, Heap::kTheHoleValueRootIndex);
2190 __ cmp(result, ip); 2183 __ cmp(result, ip);
2191 DeoptimizeIf(eq, instr->environment()); 2184 DeoptimizeIf(eq, instr->environment());
2192 } 2185 }
2193 } 2186 }
2194 2187
2195 2188
2196 void LCodeGen::DoStoreGlobal(LStoreGlobal* instr) { 2189 void LCodeGen::DoStoreGlobal(LStoreGlobal* instr) {
2197 Register value = ToRegister(instr->InputAt(0)); 2190 Register value = ToRegister(instr->InputAt(0));
2198 __ mov(ip, Operand(Handle<Object>(instr->hydrogen()->cell()))); 2191 Register scratch = scratch0();
2199 __ str(value, FieldMemOperand(ip, JSGlobalPropertyCell::kValueOffset)); 2192
2193 // Load the cell.
2194 __ mov(scratch, Operand(Handle<Object>(instr->hydrogen()->cell())));
2195
2196 // If the cell we are storing to contains the hole it could have
2197 // been deleted from the property dictionary. In that case, we need
2198 // to update the property details in the property dictionary to mark
2199 // it as no longer deleted.
2200 if (instr->hydrogen()->check_hole_value()) {
2201 Register scratch2 = ToRegister(instr->TempAt(0));
2202 __ ldr(scratch2,
2203 FieldMemOperand(scratch, JSGlobalPropertyCell::kValueOffset));
2204 __ LoadRoot(ip, Heap::kTheHoleValueRootIndex);
2205 __ cmp(scratch2, ip);
2206 DeoptimizeIf(eq, instr->environment());
2207 }
2208
2209 // Store the value.
2210 __ str(value, FieldMemOperand(scratch, JSGlobalPropertyCell::kValueOffset));
2200 } 2211 }
2201 2212
2202 2213
2203 void LCodeGen::DoLoadContextSlot(LLoadContextSlot* instr) { 2214 void LCodeGen::DoLoadContextSlot(LLoadContextSlot* instr) {
2204 // TODO(antonm): load a context with a separate instruction. 2215 // TODO(antonm): load a context with a separate instruction.
2205 Register result = ToRegister(instr->result()); 2216 Register result = ToRegister(instr->result());
2206 __ LoadContext(result, instr->context_chain_length()); 2217 __ LoadContext(result, instr->context_chain_length());
2207 __ ldr(result, ContextOperand(result, instr->slot_index())); 2218 __ ldr(result, ContextOperand(result, instr->slot_index()));
2208 } 2219 }
2209 2220
(...skipping 217 matching lines...) Expand 10 before | Expand all | Expand 10 after
2427 // length is a small non-negative integer, due to the test above. 2438 // length is a small non-negative integer, due to the test above.
2428 __ tst(length, Operand(length)); 2439 __ tst(length, Operand(length));
2429 __ b(eq, &invoke); 2440 __ b(eq, &invoke);
2430 __ bind(&loop); 2441 __ bind(&loop);
2431 __ ldr(scratch, MemOperand(elements, length, LSL, 2)); 2442 __ ldr(scratch, MemOperand(elements, length, LSL, 2));
2432 __ push(scratch); 2443 __ push(scratch);
2433 __ sub(length, length, Operand(1), SetCC); 2444 __ sub(length, length, Operand(1), SetCC);
2434 __ b(ne, &loop); 2445 __ b(ne, &loop);
2435 2446
2436 __ bind(&invoke); 2447 __ bind(&invoke);
2437 // Invoke the function. The number of arguments is stored in receiver 2448 ASSERT(instr->HasPointerMap() && instr->HasDeoptimizationEnvironment());
2438 // which is r0, as expected by InvokeFunction. 2449 LPointerMap* pointers = instr->pointer_map();
2450 LEnvironment* env = instr->deoptimization_environment();
2451 RecordPosition(pointers->position());
2452 RegisterEnvironmentForDeoptimization(env);
2453 SafepointGenerator safepoint_generator(this,
2454 pointers,
2455 env->deoptimization_index());
2456 // The number of arguments is stored in receiver which is r0, as expected
2457 // by InvokeFunction.
2439 v8::internal::ParameterCount actual(receiver); 2458 v8::internal::ParameterCount actual(receiver);
2440 SafepointGenerator safepoint_generator(this,
2441 instr->pointer_map(),
2442 Safepoint::kNoDeoptimizationIndex);
2443 __ InvokeFunction(function, actual, CALL_FUNCTION, &safepoint_generator); 2459 __ InvokeFunction(function, actual, CALL_FUNCTION, &safepoint_generator);
2444 } 2460 }
2445 2461
2446 2462
2447 void LCodeGen::DoPushArgument(LPushArgument* instr) { 2463 void LCodeGen::DoPushArgument(LPushArgument* instr) {
2448 LOperand* argument = instr->InputAt(0); 2464 LOperand* argument = instr->InputAt(0);
2449 if (argument->IsDoubleRegister() || argument->IsDoubleStackSlot()) { 2465 if (argument->IsDoubleRegister() || argument->IsDoubleStackSlot()) {
2450 Abort("DoPushArgument not implemented for double type."); 2466 Abort("DoPushArgument not implemented for double type.");
2451 } else { 2467 } else {
2452 Register argument_reg = EmitLoadRegister(argument, ip); 2468 Register argument_reg = EmitLoadRegister(argument, ip);
(...skipping 49 matching lines...) Expand 10 before | Expand all | Expand 10 after
2502 2518
2503 2519
2504 void LCodeGen::DoCallConstantFunction(LCallConstantFunction* instr) { 2520 void LCodeGen::DoCallConstantFunction(LCallConstantFunction* instr) {
2505 ASSERT(ToRegister(instr->result()).is(r0)); 2521 ASSERT(ToRegister(instr->result()).is(r0));
2506 __ mov(r1, Operand(instr->function())); 2522 __ mov(r1, Operand(instr->function()));
2507 CallKnownFunction(instr->function(), instr->arity(), instr); 2523 CallKnownFunction(instr->function(), instr->arity(), instr);
2508 } 2524 }
2509 2525
2510 2526
2511 void LCodeGen::DoDeferredMathAbsTaggedHeapNumber(LUnaryMathOperation* instr) { 2527 void LCodeGen::DoDeferredMathAbsTaggedHeapNumber(LUnaryMathOperation* instr) {
2528 ASSERT(instr->InputAt(0)->Equals(instr->result()));
2512 Register input = ToRegister(instr->InputAt(0)); 2529 Register input = ToRegister(instr->InputAt(0));
2513 Register scratch = scratch0(); 2530 Register scratch = scratch0();
2514 2531
2515 // Deoptimize if not a heap number. 2532 // Deoptimize if not a heap number.
2516 __ ldr(scratch, FieldMemOperand(input, HeapObject::kMapOffset)); 2533 __ ldr(scratch, FieldMemOperand(input, HeapObject::kMapOffset));
2517 __ LoadRoot(ip, Heap::kHeapNumberMapRootIndex); 2534 __ LoadRoot(ip, Heap::kHeapNumberMapRootIndex);
2518 __ cmp(scratch, Operand(ip)); 2535 __ cmp(scratch, Operand(ip));
2519 DeoptimizeIf(ne, instr->environment()); 2536 DeoptimizeIf(ne, instr->environment());
2520 2537
2521 Label done; 2538 Label done;
2522 2539 Register exponent = scratch0();
2523 Label negative; 2540 scratch = no_reg;
2524 __ ldr(scratch, FieldMemOperand(input, HeapNumber::kExponentOffset)); 2541 __ ldr(exponent, FieldMemOperand(input, HeapNumber::kExponentOffset));
2525 // Check the sign of the argument. If the argument is positive, just 2542 // Check the sign of the argument. If the argument is positive, just
2526 // return it. We do not need to patch the stack since |input| and 2543 // return it. We do not need to patch the stack since |input| and
2527 // |result| are the same register and |input| will be restored 2544 // |result| are the same register and |input| would be restored
2528 // unchanged by popping safepoint registers. 2545 // unchanged by popping safepoint registers.
2529 __ tst(scratch, Operand(HeapNumber::kSignMask)); 2546 __ tst(exponent, Operand(HeapNumber::kSignMask));
2530 __ b(ne, &negative); 2547 __ b(eq, &done);
2531 __ jmp(&done);
2532 2548
2533 __ bind(&negative); 2549 // Input is negative. Reverse its sign.
2534 // Preserve the value of all registers. 2550 // Preserve the value of all registers.
2535 __ PushSafepointRegisters(); 2551 __ PushSafepointRegisters();
2536 2552
2537 Register tmp = input.is(r0) ? r1 : r0; 2553 // Registers were saved at the safepoint, so we can use
2538 Register tmp2 = input.is(r2) ? r3 : r2; 2554 // many scratch registers.
2539 Register tmp3 = input.is(r4) ? r5 : r4; 2555 Register tmp1 = input.is(r1) ? r0 : r1;
2556 Register tmp2 = input.is(r2) ? r0 : r2;
2557 Register tmp3 = input.is(r3) ? r0 : r3;
2558 Register tmp4 = input.is(r4) ? r0 : r4;
2559
2560 // exponent: floating point exponent value.
2540 2561
2541 Label allocated, slow; 2562 Label allocated, slow;
2542 __ LoadRoot(scratch, Heap::kHeapNumberMapRootIndex); 2563 __ LoadRoot(tmp4, Heap::kHeapNumberMapRootIndex);
2543 __ AllocateHeapNumber(tmp, tmp2, tmp3, scratch, &slow); 2564 __ AllocateHeapNumber(tmp1, tmp2, tmp3, tmp4, &slow);
2544 __ b(&allocated); 2565 __ b(&allocated);
2545 2566
2546 // Slow case: Call the runtime system to do the number allocation. 2567 // Slow case: Call the runtime system to do the number allocation.
2547 __ bind(&slow); 2568 __ bind(&slow);
2548 2569
2549 __ CallRuntimeSaveDoubles(Runtime::kAllocateHeapNumber); 2570 __ CallRuntimeSaveDoubles(Runtime::kAllocateHeapNumber);
2550 RecordSafepointWithRegisters( 2571 RecordSafepointWithRegisters(
2551 instr->pointer_map(), 0, Safepoint::kNoDeoptimizationIndex); 2572 instr->pointer_map(), 0, Safepoint::kNoDeoptimizationIndex);
2552 // Set the pointer to the new heap number in tmp. 2573 // Set the pointer to the new heap number in tmp.
2553 if (!tmp.is(r0)) __ mov(tmp, Operand(r0)); 2574 if (!tmp1.is(r0)) __ mov(tmp1, Operand(r0));
2554
2555 // Restore input_reg after call to runtime. 2575 // Restore input_reg after call to runtime.
2556 MemOperand input_register_slot = masm()->SafepointRegisterSlot(input); 2576 __ LoadFromSafepointRegisterSlot(input);
2557 __ ldr(input, input_register_slot); 2577 __ ldr(exponent, FieldMemOperand(input, HeapNumber::kExponentOffset));
2558 2578
2559 __ bind(&allocated); 2579 __ bind(&allocated);
2560 __ ldr(tmp2, FieldMemOperand(input, HeapNumber::kExponentOffset)); 2580 // exponent: floating point exponent value.
2561 __ bic(tmp2, tmp2, Operand(HeapNumber::kSignMask)); 2581 // tmp1: allocated heap number.
2562 __ str(tmp2, FieldMemOperand(tmp, HeapNumber::kExponentOffset)); 2582 __ bic(exponent, exponent, Operand(HeapNumber::kSignMask));
2583 __ str(exponent, FieldMemOperand(tmp1, HeapNumber::kExponentOffset));
2563 __ ldr(tmp2, FieldMemOperand(input, HeapNumber::kMantissaOffset)); 2584 __ ldr(tmp2, FieldMemOperand(input, HeapNumber::kMantissaOffset));
2564 __ str(tmp2, FieldMemOperand(tmp, HeapNumber::kMantissaOffset)); 2585 __ str(tmp2, FieldMemOperand(tmp1, HeapNumber::kMantissaOffset));
2565 2586
2566 __ str(tmp, input_register_slot); 2587 __ str(tmp1, masm()->SafepointRegisterSlot(input));
2567 __ PopSafepointRegisters(); 2588 __ PopSafepointRegisters();
2568 2589
2569 __ bind(&done); 2590 __ bind(&done);
2570 } 2591 }
2571 2592
2572 2593
2573 void LCodeGen::EmitIntegerMathAbs(LUnaryMathOperation* instr) { 2594 void LCodeGen::EmitIntegerMathAbs(LUnaryMathOperation* instr) {
2574 Label is_positive;
2575 uint32_t kSignMask = 0x80000000u;
2576 Register input = ToRegister(instr->InputAt(0)); 2595 Register input = ToRegister(instr->InputAt(0));
2577 __ tst(input, Operand(kSignMask)); 2596 __ cmp(input, Operand(0));
2578 __ b(eq, &is_positive); 2597 // We can make rsb conditional because the previous cmp instruction
2579 __ rsb(input, input, Operand(0), SetCC); 2598 // will clear the V (overflow) flag and rsb won't set this flag
2599 // if input is positive.
2600 __ rsb(input, input, Operand(0), SetCC, mi);
2580 // Deoptimize on overflow. 2601 // Deoptimize on overflow.
2581 DeoptimizeIf(vs, instr->environment()); 2602 DeoptimizeIf(vs, instr->environment());
2582 __ bind(&is_positive);
2583 } 2603 }
2584 2604
2585 2605
2586 void LCodeGen::DoMathAbs(LUnaryMathOperation* instr) { 2606 void LCodeGen::DoMathAbs(LUnaryMathOperation* instr) {
2587 // Class for deferred case. 2607 // Class for deferred case.
2588 class DeferredMathAbsTaggedHeapNumber: public LDeferredCode { 2608 class DeferredMathAbsTaggedHeapNumber: public LDeferredCode {
2589 public: 2609 public:
2590 DeferredMathAbsTaggedHeapNumber(LCodeGen* codegen, 2610 DeferredMathAbsTaggedHeapNumber(LCodeGen* codegen,
2591 LUnaryMathOperation* instr) 2611 LUnaryMathOperation* instr)
2592 : LDeferredCode(codegen), instr_(instr) { } 2612 : LDeferredCode(codegen), instr_(instr) { }
2593 virtual void Generate() { 2613 virtual void Generate() {
2594 codegen()->DoDeferredMathAbsTaggedHeapNumber(instr_); 2614 codegen()->DoDeferredMathAbsTaggedHeapNumber(instr_);
2595 } 2615 }
2596 private: 2616 private:
2597 LUnaryMathOperation* instr_; 2617 LUnaryMathOperation* instr_;
2598 }; 2618 };
2599 2619
2600 ASSERT(instr->InputAt(0)->Equals(instr->result())); 2620 ASSERT(instr->InputAt(0)->Equals(instr->result()));
2601 Representation r = instr->hydrogen()->value()->representation(); 2621 Representation r = instr->hydrogen()->value()->representation();
2602 if (r.IsDouble()) { 2622 if (r.IsDouble()) {
2603 DwVfpRegister input = ToDoubleRegister(instr->InputAt(0)); 2623 DwVfpRegister input = ToDoubleRegister(instr->InputAt(0));
2604 // __ vabs(input, input); 2624 __ vabs(input, input);
2605 Abort("Double DoMathAbs unimplemented");
2606 } else if (r.IsInteger32()) { 2625 } else if (r.IsInteger32()) {
2607 EmitIntegerMathAbs(instr); 2626 EmitIntegerMathAbs(instr);
2608 } else { 2627 } else {
2609 // Representation is tagged. 2628 // Representation is tagged.
2610 DeferredMathAbsTaggedHeapNumber* deferred = 2629 DeferredMathAbsTaggedHeapNumber* deferred =
2611 new DeferredMathAbsTaggedHeapNumber(this, instr); 2630 new DeferredMathAbsTaggedHeapNumber(this, instr);
2612 Register input = ToRegister(instr->InputAt(0)); 2631 Register input = ToRegister(instr->InputAt(0));
2613 // Smi check. 2632 // Smi check.
2614 __ JumpIfNotSmi(input, deferred->entry()); 2633 __ JumpIfNotSmi(input, deferred->entry());
2615 // If smi, handle it directly. 2634 // If smi, handle it directly.
(...skipping 1036 matching lines...) Expand 10 before | Expand all | Expand 10 after
3652 3671
3653 void LCodeGen::DoDeoptimize(LDeoptimize* instr) { 3672 void LCodeGen::DoDeoptimize(LDeoptimize* instr) {
3654 DeoptimizeIf(kNoCondition, instr->environment()); 3673 DeoptimizeIf(kNoCondition, instr->environment());
3655 } 3674 }
3656 3675
3657 3676
3658 void LCodeGen::DoDeleteProperty(LDeleteProperty* instr) { 3677 void LCodeGen::DoDeleteProperty(LDeleteProperty* instr) {
3659 Register object = ToRegister(instr->object()); 3678 Register object = ToRegister(instr->object());
3660 Register key = ToRegister(instr->key()); 3679 Register key = ToRegister(instr->key());
3661 __ Push(object, key); 3680 __ Push(object, key);
3662 RecordPosition(instr->pointer_map()->position()); 3681 ASSERT(instr->HasPointerMap() && instr->HasDeoptimizationEnvironment());
3682 LPointerMap* pointers = instr->pointer_map();
3683 LEnvironment* env = instr->deoptimization_environment();
3684 RecordPosition(pointers->position());
3685 RegisterEnvironmentForDeoptimization(env);
3663 SafepointGenerator safepoint_generator(this, 3686 SafepointGenerator safepoint_generator(this,
3664 instr->pointer_map(), 3687 pointers,
3665 Safepoint::kNoDeoptimizationIndex); 3688 env->deoptimization_index());
3666 __ InvokeBuiltin(Builtins::DELETE, CALL_JS, &safepoint_generator); 3689 __ InvokeBuiltin(Builtins::DELETE, CALL_JS, &safepoint_generator);
3667 } 3690 }
3668 3691
3669 3692
3670 void LCodeGen::DoStackCheck(LStackCheck* instr) { 3693 void LCodeGen::DoStackCheck(LStackCheck* instr) {
3671 // Perform stack overflow check. 3694 // Perform stack overflow check.
3672 Label ok; 3695 Label ok;
3673 __ LoadRoot(ip, Heap::kStackLimitRootIndex); 3696 __ LoadRoot(ip, Heap::kStackLimitRootIndex);
3674 __ cmp(sp, Operand(ip)); 3697 __ cmp(sp, Operand(ip));
3675 __ b(hs, &ok); 3698 __ b(hs, &ok);
3676 StackCheckStub stub; 3699 StackCheckStub stub;
3677 CallCode(stub.GetCode(), RelocInfo::CODE_TARGET, instr); 3700 CallCode(stub.GetCode(), RelocInfo::CODE_TARGET, instr);
3678 __ bind(&ok); 3701 __ bind(&ok);
3679 } 3702 }
3680 3703
3681 3704
3682 void LCodeGen::DoOsrEntry(LOsrEntry* instr) { 3705 void LCodeGen::DoOsrEntry(LOsrEntry* instr) {
3683 Abort("DoOsrEntry unimplemented."); 3706 Abort("DoOsrEntry unimplemented.");
3684 } 3707 }
3685 3708
3686 3709
3687 #undef __ 3710 #undef __
3688 3711
3689 } } // namespace v8::internal 3712 } } // namespace v8::internal
OLDNEW
« no previous file with comments | « src/arm/lithium-codegen-arm.h ('k') | src/arm/macro-assembler-arm.h » ('j') | src/ast.cc » ('J')

Powered by Google App Engine
This is Rietveld 408576698