| OLD | NEW |
| 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 447 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 458 translation->StoreLiteral(src_index); | 458 translation->StoreLiteral(src_index); |
| 459 } else { | 459 } else { |
| 460 UNREACHABLE(); | 460 UNREACHABLE(); |
| 461 } | 461 } |
| 462 } | 462 } |
| 463 | 463 |
| 464 | 464 |
| 465 void LCodeGen::CallCode(Handle<Code> code, | 465 void LCodeGen::CallCode(Handle<Code> code, |
| 466 RelocInfo::Mode mode, | 466 RelocInfo::Mode mode, |
| 467 LInstruction* instr) { | 467 LInstruction* instr) { |
| 468 CallCodeGeneric(code, mode, instr, RECORD_SIMPLE_SAFEPOINT); |
| 469 } |
| 470 |
| 471 |
| 472 void LCodeGen::CallCodeGeneric(Handle<Code> code, |
| 473 RelocInfo::Mode mode, |
| 474 LInstruction* instr, |
| 475 SafepointMode safepoint_mode) { |
| 468 ASSERT(instr != NULL); | 476 ASSERT(instr != NULL); |
| 469 LPointerMap* pointers = instr->pointer_map(); | 477 LPointerMap* pointers = instr->pointer_map(); |
| 470 RecordPosition(pointers->position()); | 478 RecordPosition(pointers->position()); |
| 471 __ Call(code, mode); | 479 __ Call(code, mode); |
| 472 RegisterLazyDeoptimization(instr); | 480 RegisterLazyDeoptimization(instr, safepoint_mode); |
| 473 } | 481 } |
| 474 | 482 |
| 475 | 483 |
| 476 void LCodeGen::CallRuntime(Runtime::Function* function, | 484 void LCodeGen::CallRuntime(Runtime::Function* function, |
| 477 int num_arguments, | 485 int num_arguments, |
| 478 LInstruction* instr) { | 486 LInstruction* instr) { |
| 479 ASSERT(instr != NULL); | 487 ASSERT(instr != NULL); |
| 480 LPointerMap* pointers = instr->pointer_map(); | 488 LPointerMap* pointers = instr->pointer_map(); |
| 481 ASSERT(pointers != NULL); | 489 ASSERT(pointers != NULL); |
| 482 RecordPosition(pointers->position()); | 490 RecordPosition(pointers->position()); |
| 483 | 491 |
| 484 __ CallRuntime(function, num_arguments); | 492 __ CallRuntime(function, num_arguments); |
| 485 RegisterLazyDeoptimization(instr); | 493 RegisterLazyDeoptimization(instr, RECORD_SIMPLE_SAFEPOINT); |
| 486 } | 494 } |
| 487 | 495 |
| 488 | 496 |
| 489 void LCodeGen::RegisterLazyDeoptimization(LInstruction* instr) { | 497 void LCodeGen::CallRuntimeFromDeferred(Runtime::FunctionId id, |
| 498 int argc, |
| 499 LInstruction* instr) { |
| 500 __ CallRuntimeSaveDoubles(id); |
| 501 RecordSafepointWithRegisters( |
| 502 instr->pointer_map(), argc, Safepoint::kNoDeoptimizationIndex); |
| 503 } |
| 504 |
| 505 |
| 506 void LCodeGen::RegisterLazyDeoptimization(LInstruction* instr, |
| 507 SafepointMode safepoint_mode) { |
| 490 // Create the environment to bailout to. If the call has side effects | 508 // Create the environment to bailout to. If the call has side effects |
| 491 // execution has to continue after the call otherwise execution can continue | 509 // execution has to continue after the call otherwise execution can continue |
| 492 // from a previous bailout point repeating the call. | 510 // from a previous bailout point repeating the call. |
| 493 LEnvironment* deoptimization_environment; | 511 LEnvironment* deoptimization_environment; |
| 494 if (instr->HasDeoptimizationEnvironment()) { | 512 if (instr->HasDeoptimizationEnvironment()) { |
| 495 deoptimization_environment = instr->deoptimization_environment(); | 513 deoptimization_environment = instr->deoptimization_environment(); |
| 496 } else { | 514 } else { |
| 497 deoptimization_environment = instr->environment(); | 515 deoptimization_environment = instr->environment(); |
| 498 } | 516 } |
| 499 | 517 |
| 500 RegisterEnvironmentForDeoptimization(deoptimization_environment); | 518 RegisterEnvironmentForDeoptimization(deoptimization_environment); |
| 501 RecordSafepoint(instr->pointer_map(), | 519 if (safepoint_mode == RECORD_SIMPLE_SAFEPOINT) { |
| 502 deoptimization_environment->deoptimization_index()); | 520 RecordSafepoint(instr->pointer_map(), |
| 521 deoptimization_environment->deoptimization_index()); |
| 522 } else { |
| 523 ASSERT(safepoint_mode == RECORD_SAFEPOINT_WITH_REGISTERS_AND_NO_ARGUMENTS); |
| 524 RecordSafepointWithRegisters( |
| 525 instr->pointer_map(), |
| 526 0, |
| 527 deoptimization_environment->deoptimization_index()); |
| 528 } |
| 503 } | 529 } |
| 504 | 530 |
| 505 | 531 |
| 506 void LCodeGen::RegisterEnvironmentForDeoptimization(LEnvironment* environment) { | 532 void LCodeGen::RegisterEnvironmentForDeoptimization(LEnvironment* environment) { |
| 507 if (!environment->HasBeenRegistered()) { | 533 if (!environment->HasBeenRegistered()) { |
| 508 // Physical stack frame layout: | 534 // Physical stack frame layout: |
| 509 // -x ............. -4 0 ..................................... y | 535 // -x ............. -4 0 ..................................... y |
| 510 // [incoming arguments] [spill slots] [pushed outgoing arguments] | 536 // [incoming arguments] [spill slots] [pushed outgoing arguments] |
| 511 | 537 |
| 512 // Layout of the environment: | 538 // Layout of the environment: |
| (...skipping 111 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 624 | 650 |
| 625 inlined_function_count_ = deoptimization_literals_.length(); | 651 inlined_function_count_ = deoptimization_literals_.length(); |
| 626 } | 652 } |
| 627 | 653 |
| 628 | 654 |
| 629 void LCodeGen::RecordSafepoint( | 655 void LCodeGen::RecordSafepoint( |
| 630 LPointerMap* pointers, | 656 LPointerMap* pointers, |
| 631 Safepoint::Kind kind, | 657 Safepoint::Kind kind, |
| 632 int arguments, | 658 int arguments, |
| 633 int deoptimization_index) { | 659 int deoptimization_index) { |
| 660 ASSERT(expected_safepoint_kind_ == kind); |
| 661 |
| 634 const ZoneList<LOperand*>* operands = pointers->operands(); | 662 const ZoneList<LOperand*>* operands = pointers->operands(); |
| 635 Safepoint safepoint = safepoints_.DefineSafepoint(masm(), | 663 Safepoint safepoint = safepoints_.DefineSafepoint(masm(), |
| 636 kind, arguments, deoptimization_index); | 664 kind, arguments, deoptimization_index); |
| 637 for (int i = 0; i < operands->length(); i++) { | 665 for (int i = 0; i < operands->length(); i++) { |
| 638 LOperand* pointer = operands->at(i); | 666 LOperand* pointer = operands->at(i); |
| 639 if (pointer->IsStackSlot()) { | 667 if (pointer->IsStackSlot()) { |
| 640 safepoint.DefinePointerSlot(pointer->index()); | 668 safepoint.DefinePointerSlot(pointer->index()); |
| 641 } else if (pointer->IsRegister() && (kind & Safepoint::kWithRegisters)) { | 669 } else if (pointer->IsRegister() && (kind & Safepoint::kWithRegisters)) { |
| 642 safepoint.DefinePointerRegister(ToRegister(pointer)); | 670 safepoint.DefinePointerRegister(ToRegister(pointer)); |
| 643 } | 671 } |
| (...skipping 300 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 944 __ bind(&done); | 972 __ bind(&done); |
| 945 } | 973 } |
| 946 | 974 |
| 947 | 975 |
| 948 template<int T> | 976 template<int T> |
| 949 void LCodeGen::DoDeferredBinaryOpStub(LTemplateInstruction<1, 2, T>* instr, | 977 void LCodeGen::DoDeferredBinaryOpStub(LTemplateInstruction<1, 2, T>* instr, |
| 950 Token::Value op) { | 978 Token::Value op) { |
| 951 Register left = ToRegister(instr->InputAt(0)); | 979 Register left = ToRegister(instr->InputAt(0)); |
| 952 Register right = ToRegister(instr->InputAt(1)); | 980 Register right = ToRegister(instr->InputAt(1)); |
| 953 | 981 |
| 954 __ PushSafepointRegistersAndDoubles(); | 982 PushSafepointRegistersScope scope(this, Safepoint::kWithRegistersAndDoubles); |
| 955 // Move left to r1 and right to r0 for the stub call. | 983 // Move left to r1 and right to r0 for the stub call. |
| 956 if (left.is(r1)) { | 984 if (left.is(r1)) { |
| 957 __ Move(r0, right); | 985 __ Move(r0, right); |
| 958 } else if (left.is(r0) && right.is(r1)) { | 986 } else if (left.is(r0) && right.is(r1)) { |
| 959 __ Swap(r0, r1, r2); | 987 __ Swap(r0, r1, r2); |
| 960 } else if (left.is(r0)) { | 988 } else if (left.is(r0)) { |
| 961 ASSERT(!right.is(r1)); | 989 ASSERT(!right.is(r1)); |
| 962 __ mov(r1, r0); | 990 __ mov(r1, r0); |
| 963 __ mov(r0, right); | 991 __ mov(r0, right); |
| 964 } else { | 992 } else { |
| 965 ASSERT(!left.is(r0) && !right.is(r0)); | 993 ASSERT(!left.is(r0) && !right.is(r0)); |
| 966 __ mov(r0, right); | 994 __ mov(r0, right); |
| 967 __ mov(r1, left); | 995 __ mov(r1, left); |
| 968 } | 996 } |
| 969 TypeRecordingBinaryOpStub stub(op, OVERWRITE_LEFT); | 997 TypeRecordingBinaryOpStub stub(op, OVERWRITE_LEFT); |
| 970 __ CallStub(&stub); | 998 __ CallStub(&stub); |
| 971 RecordSafepointWithRegistersAndDoubles(instr->pointer_map(), | 999 RecordSafepointWithRegistersAndDoubles(instr->pointer_map(), |
| 972 0, | 1000 0, |
| 973 Safepoint::kNoDeoptimizationIndex); | 1001 Safepoint::kNoDeoptimizationIndex); |
| 974 // Overwrite the stored value of r0 with the result of the stub. | 1002 // Overwrite the stored value of r0 with the result of the stub. |
| 975 __ StoreToSafepointRegistersAndDoublesSlot(r0, r0); | 1003 __ StoreToSafepointRegistersAndDoublesSlot(r0, r0); |
| 976 __ PopSafepointRegistersAndDoubles(); | |
| 977 } | 1004 } |
| 978 | 1005 |
| 979 | 1006 |
| 980 void LCodeGen::DoMulI(LMulI* instr) { | 1007 void LCodeGen::DoMulI(LMulI* instr) { |
| 981 Register scratch = scratch0(); | 1008 Register scratch = scratch0(); |
| 982 Register left = ToRegister(instr->InputAt(0)); | 1009 Register left = ToRegister(instr->InputAt(0)); |
| 983 Register right = EmitLoadRegister(instr->InputAt(1), scratch); | 1010 Register right = EmitLoadRegister(instr->InputAt(1), scratch); |
| 984 | 1011 |
| 985 if (instr->hydrogen()->CheckFlag(HValue::kBailoutOnMinusZero) && | 1012 if (instr->hydrogen()->CheckFlag(HValue::kBailoutOnMinusZero) && |
| 986 !instr->InputAt(1)->IsConstantOperand()) { | 1013 !instr->InputAt(1)->IsConstantOperand()) { |
| (...skipping 375 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1362 __ jmp(deferred_stack_check->entry()); | 1389 __ jmp(deferred_stack_check->entry()); |
| 1363 deferred_stack_check->SetExit(chunk_->GetAssemblyLabel(block)); | 1390 deferred_stack_check->SetExit(chunk_->GetAssemblyLabel(block)); |
| 1364 } else { | 1391 } else { |
| 1365 __ jmp(chunk_->GetAssemblyLabel(block)); | 1392 __ jmp(chunk_->GetAssemblyLabel(block)); |
| 1366 } | 1393 } |
| 1367 } | 1394 } |
| 1368 } | 1395 } |
| 1369 | 1396 |
| 1370 | 1397 |
| 1371 void LCodeGen::DoDeferredStackCheck(LGoto* instr) { | 1398 void LCodeGen::DoDeferredStackCheck(LGoto* instr) { |
| 1372 __ PushSafepointRegisters(); | 1399 PushSafepointRegistersScope scope(this, Safepoint::kWithRegisters); |
| 1373 __ CallRuntimeSaveDoubles(Runtime::kStackGuard); | 1400 CallRuntimeFromDeferred(Runtime::kStackGuard, 0, instr); |
| 1374 RecordSafepointWithRegisters( | |
| 1375 instr->pointer_map(), 0, Safepoint::kNoDeoptimizationIndex); | |
| 1376 __ PopSafepointRegisters(); | |
| 1377 } | 1401 } |
| 1378 | 1402 |
| 1379 | 1403 |
| 1380 void LCodeGen::DoGoto(LGoto* instr) { | 1404 void LCodeGen::DoGoto(LGoto* instr) { |
| 1381 class DeferredStackCheck: public LDeferredCode { | 1405 class DeferredStackCheck: public LDeferredCode { |
| 1382 public: | 1406 public: |
| 1383 DeferredStackCheck(LCodeGen* codegen, LGoto* instr) | 1407 DeferredStackCheck(LCodeGen* codegen, LGoto* instr) |
| 1384 : LDeferredCode(codegen), instr_(instr) { } | 1408 : LDeferredCode(codegen), instr_(instr) { } |
| 1385 virtual void Generate() { codegen()->DoDeferredStackCheck(instr_); } | 1409 virtual void Generate() { codegen()->DoDeferredStackCheck(instr_); } |
| 1386 private: | 1410 private: |
| (...skipping 578 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1965 | 1989 |
| 1966 InstanceofStub::Flags flags = InstanceofStub::kNoFlags; | 1990 InstanceofStub::Flags flags = InstanceofStub::kNoFlags; |
| 1967 flags = static_cast<InstanceofStub::Flags>( | 1991 flags = static_cast<InstanceofStub::Flags>( |
| 1968 flags | InstanceofStub::kArgsInRegisters); | 1992 flags | InstanceofStub::kArgsInRegisters); |
| 1969 flags = static_cast<InstanceofStub::Flags>( | 1993 flags = static_cast<InstanceofStub::Flags>( |
| 1970 flags | InstanceofStub::kCallSiteInlineCheck); | 1994 flags | InstanceofStub::kCallSiteInlineCheck); |
| 1971 flags = static_cast<InstanceofStub::Flags>( | 1995 flags = static_cast<InstanceofStub::Flags>( |
| 1972 flags | InstanceofStub::kReturnTrueFalseObject); | 1996 flags | InstanceofStub::kReturnTrueFalseObject); |
| 1973 InstanceofStub stub(flags); | 1997 InstanceofStub stub(flags); |
| 1974 | 1998 |
| 1975 __ PushSafepointRegisters(); | 1999 PushSafepointRegistersScope scope(this, Safepoint::kWithRegisters); |
| 1976 | 2000 |
| 1977 // Get the temp register reserved by the instruction. This needs to be r4 as | 2001 // Get the temp register reserved by the instruction. This needs to be r4 as |
| 1978 // its slot of the pushing of safepoint registers is used to communicate the | 2002 // its slot of the pushing of safepoint registers is used to communicate the |
| 1979 // offset to the location of the map check. | 2003 // offset to the location of the map check. |
| 1980 Register temp = ToRegister(instr->TempAt(0)); | 2004 Register temp = ToRegister(instr->TempAt(0)); |
| 1981 ASSERT(temp.is(r4)); | 2005 ASSERT(temp.is(r4)); |
| 1982 __ mov(InstanceofStub::right(), Operand(instr->function())); | 2006 __ mov(InstanceofStub::right(), Operand(instr->function())); |
| 1983 static const int kAdditionalDelta = 4; | 2007 static const int kAdditionalDelta = 4; |
| 1984 int delta = masm_->InstructionsGeneratedSince(map_check) + kAdditionalDelta; | 2008 int delta = masm_->InstructionsGeneratedSince(map_check) + kAdditionalDelta; |
| 1985 Label before_push_delta; | 2009 Label before_push_delta; |
| 1986 __ bind(&before_push_delta); | 2010 __ bind(&before_push_delta); |
| 1987 __ BlockConstPoolFor(kAdditionalDelta); | 2011 __ BlockConstPoolFor(kAdditionalDelta); |
| 1988 __ mov(temp, Operand(delta * kPointerSize)); | 2012 __ mov(temp, Operand(delta * kPointerSize)); |
| 1989 __ StoreToSafepointRegisterSlot(temp, temp); | 2013 __ StoreToSafepointRegisterSlot(temp, temp); |
| 1990 CallCode(stub.GetCode(), RelocInfo::CODE_TARGET, instr); | 2014 CallCodeGeneric(stub.GetCode(), |
| 2015 RelocInfo::CODE_TARGET, |
| 2016 instr, |
| 2017 RECORD_SAFEPOINT_WITH_REGISTERS_AND_NO_ARGUMENTS); |
| 1991 // Put the result value into the result register slot and | 2018 // Put the result value into the result register slot and |
| 1992 // restore all registers. | 2019 // restore all registers. |
| 1993 __ StoreToSafepointRegisterSlot(result, result); | 2020 __ StoreToSafepointRegisterSlot(result, result); |
| 1994 | |
| 1995 __ PopSafepointRegisters(); | |
| 1996 } | 2021 } |
| 1997 | 2022 |
| 1998 | 2023 |
| 1999 static Condition ComputeCompareCondition(Token::Value op) { | 2024 static Condition ComputeCompareCondition(Token::Value op) { |
| 2000 switch (op) { | 2025 switch (op) { |
| 2001 case Token::EQ_STRICT: | 2026 case Token::EQ_STRICT: |
| 2002 case Token::EQ: | 2027 case Token::EQ: |
| 2003 return eq; | 2028 return eq; |
| 2004 case Token::LT: | 2029 case Token::LT: |
| 2005 return lt; | 2030 return lt; |
| (...skipping 443 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2449 } | 2474 } |
| 2450 | 2475 |
| 2451 LPointerMap* pointers = instr->pointer_map(); | 2476 LPointerMap* pointers = instr->pointer_map(); |
| 2452 RecordPosition(pointers->position()); | 2477 RecordPosition(pointers->position()); |
| 2453 | 2478 |
| 2454 // Invoke function. | 2479 // Invoke function. |
| 2455 __ ldr(ip, FieldMemOperand(r1, JSFunction::kCodeEntryOffset)); | 2480 __ ldr(ip, FieldMemOperand(r1, JSFunction::kCodeEntryOffset)); |
| 2456 __ Call(ip); | 2481 __ Call(ip); |
| 2457 | 2482 |
| 2458 // Setup deoptimization. | 2483 // Setup deoptimization. |
| 2459 RegisterLazyDeoptimization(instr); | 2484 RegisterLazyDeoptimization(instr, RECORD_SIMPLE_SAFEPOINT); |
| 2460 | 2485 |
| 2461 // Restore context. | 2486 // Restore context. |
| 2462 __ ldr(cp, MemOperand(fp, StandardFrameConstants::kContextOffset)); | 2487 __ ldr(cp, MemOperand(fp, StandardFrameConstants::kContextOffset)); |
| 2463 } | 2488 } |
| 2464 | 2489 |
| 2465 | 2490 |
| 2466 void LCodeGen::DoCallConstantFunction(LCallConstantFunction* instr) { | 2491 void LCodeGen::DoCallConstantFunction(LCallConstantFunction* instr) { |
| 2467 ASSERT(ToRegister(instr->result()).is(r0)); | 2492 ASSERT(ToRegister(instr->result()).is(r0)); |
| 2468 __ mov(r1, Operand(instr->function())); | 2493 __ mov(r1, Operand(instr->function())); |
| 2469 CallKnownFunction(instr->function(), instr->arity(), instr); | 2494 CallKnownFunction(instr->function(), instr->arity(), instr); |
| (...skipping 17 matching lines...) Expand all Loading... |
| 2487 __ ldr(exponent, FieldMemOperand(input, HeapNumber::kExponentOffset)); | 2512 __ ldr(exponent, FieldMemOperand(input, HeapNumber::kExponentOffset)); |
| 2488 // Check the sign of the argument. If the argument is positive, just | 2513 // Check the sign of the argument. If the argument is positive, just |
| 2489 // return it. We do not need to patch the stack since |input| and | 2514 // return it. We do not need to patch the stack since |input| and |
| 2490 // |result| are the same register and |input| would be restored | 2515 // |result| are the same register and |input| would be restored |
| 2491 // unchanged by popping safepoint registers. | 2516 // unchanged by popping safepoint registers. |
| 2492 __ tst(exponent, Operand(HeapNumber::kSignMask)); | 2517 __ tst(exponent, Operand(HeapNumber::kSignMask)); |
| 2493 __ b(eq, &done); | 2518 __ b(eq, &done); |
| 2494 | 2519 |
| 2495 // Input is negative. Reverse its sign. | 2520 // Input is negative. Reverse its sign. |
| 2496 // Preserve the value of all registers. | 2521 // Preserve the value of all registers. |
| 2497 __ PushSafepointRegisters(); | 2522 { |
| 2523 PushSafepointRegistersScope scope(this, Safepoint::kWithRegisters); |
| 2498 | 2524 |
| 2499 // Registers were saved at the safepoint, so we can use | 2525 // Registers were saved at the safepoint, so we can use |
| 2500 // many scratch registers. | 2526 // many scratch registers. |
| 2501 Register tmp1 = input.is(r1) ? r0 : r1; | 2527 Register tmp1 = input.is(r1) ? r0 : r1; |
| 2502 Register tmp2 = input.is(r2) ? r0 : r2; | 2528 Register tmp2 = input.is(r2) ? r0 : r2; |
| 2503 Register tmp3 = input.is(r3) ? r0 : r3; | 2529 Register tmp3 = input.is(r3) ? r0 : r3; |
| 2504 Register tmp4 = input.is(r4) ? r0 : r4; | 2530 Register tmp4 = input.is(r4) ? r0 : r4; |
| 2505 | 2531 |
| 2506 // exponent: floating point exponent value. | 2532 // exponent: floating point exponent value. |
| 2507 | 2533 |
| 2508 Label allocated, slow; | 2534 Label allocated, slow; |
| 2509 __ LoadRoot(tmp4, Heap::kHeapNumberMapRootIndex); | 2535 __ LoadRoot(tmp4, Heap::kHeapNumberMapRootIndex); |
| 2510 __ AllocateHeapNumber(tmp1, tmp2, tmp3, tmp4, &slow); | 2536 __ AllocateHeapNumber(tmp1, tmp2, tmp3, tmp4, &slow); |
| 2511 __ b(&allocated); | 2537 __ b(&allocated); |
| 2512 | 2538 |
| 2513 // Slow case: Call the runtime system to do the number allocation. | 2539 // Slow case: Call the runtime system to do the number allocation. |
| 2514 __ bind(&slow); | 2540 __ bind(&slow); |
| 2515 | 2541 |
| 2516 __ CallRuntimeSaveDoubles(Runtime::kAllocateHeapNumber); | 2542 CallRuntimeFromDeferred(Runtime::kAllocateHeapNumber, 0, instr); |
| 2517 RecordSafepointWithRegisters( | 2543 // Set the pointer to the new heap number in tmp. |
| 2518 instr->pointer_map(), 0, Safepoint::kNoDeoptimizationIndex); | 2544 if (!tmp1.is(r0)) __ mov(tmp1, Operand(r0)); |
| 2519 // Set the pointer to the new heap number in tmp. | 2545 // Restore input_reg after call to runtime. |
| 2520 if (!tmp1.is(r0)) __ mov(tmp1, Operand(r0)); | 2546 __ LoadFromSafepointRegisterSlot(input, input); |
| 2521 // Restore input_reg after call to runtime. | 2547 __ ldr(exponent, FieldMemOperand(input, HeapNumber::kExponentOffset)); |
| 2522 __ LoadFromSafepointRegisterSlot(input, input); | |
| 2523 __ ldr(exponent, FieldMemOperand(input, HeapNumber::kExponentOffset)); | |
| 2524 | 2548 |
| 2525 __ bind(&allocated); | 2549 __ bind(&allocated); |
| 2526 // exponent: floating point exponent value. | 2550 // exponent: floating point exponent value. |
| 2527 // tmp1: allocated heap number. | 2551 // tmp1: allocated heap number. |
| 2528 __ bic(exponent, exponent, Operand(HeapNumber::kSignMask)); | 2552 __ bic(exponent, exponent, Operand(HeapNumber::kSignMask)); |
| 2529 __ str(exponent, FieldMemOperand(tmp1, HeapNumber::kExponentOffset)); | 2553 __ str(exponent, FieldMemOperand(tmp1, HeapNumber::kExponentOffset)); |
| 2530 __ ldr(tmp2, FieldMemOperand(input, HeapNumber::kMantissaOffset)); | 2554 __ ldr(tmp2, FieldMemOperand(input, HeapNumber::kMantissaOffset)); |
| 2531 __ str(tmp2, FieldMemOperand(tmp1, HeapNumber::kMantissaOffset)); | 2555 __ str(tmp2, FieldMemOperand(tmp1, HeapNumber::kMantissaOffset)); |
| 2532 | 2556 |
| 2533 __ StoreToSafepointRegisterSlot(tmp1, input); | 2557 __ StoreToSafepointRegisterSlot(tmp1, input); |
| 2534 __ PopSafepointRegisters(); | 2558 } |
| 2535 | 2559 |
| 2536 __ bind(&done); | 2560 __ bind(&done); |
| 2537 } | 2561 } |
| 2538 | 2562 |
| 2539 | 2563 |
| 2540 void LCodeGen::EmitIntegerMathAbs(LUnaryMathOperation* instr) { | 2564 void LCodeGen::EmitIntegerMathAbs(LUnaryMathOperation* instr) { |
| 2541 Register input = ToRegister(instr->InputAt(0)); | 2565 Register input = ToRegister(instr->InputAt(0)); |
| 2542 __ cmp(input, Operand(0)); | 2566 __ cmp(input, Operand(0)); |
| 2543 // We can make rsb conditional because the previous cmp instruction | 2567 // We can make rsb conditional because the previous cmp instruction |
| 2544 // will clear the V (overflow) flag and rsb won't set this flag | 2568 // will clear the V (overflow) flag and rsb won't set this flag |
| (...skipping 441 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2986 void LCodeGen::DoDeferredStringCharCodeAt(LStringCharCodeAt* instr) { | 3010 void LCodeGen::DoDeferredStringCharCodeAt(LStringCharCodeAt* instr) { |
| 2987 Register string = ToRegister(instr->string()); | 3011 Register string = ToRegister(instr->string()); |
| 2988 Register result = ToRegister(instr->result()); | 3012 Register result = ToRegister(instr->result()); |
| 2989 Register scratch = scratch0(); | 3013 Register scratch = scratch0(); |
| 2990 | 3014 |
| 2991 // TODO(3095996): Get rid of this. For now, we need to make the | 3015 // TODO(3095996): Get rid of this. For now, we need to make the |
| 2992 // result register contain a valid pointer because it is already | 3016 // result register contain a valid pointer because it is already |
| 2993 // contained in the register pointer map. | 3017 // contained in the register pointer map. |
| 2994 __ mov(result, Operand(0)); | 3018 __ mov(result, Operand(0)); |
| 2995 | 3019 |
| 2996 __ PushSafepointRegisters(); | 3020 PushSafepointRegistersScope scope(this, Safepoint::kWithRegisters); |
| 2997 __ push(string); | 3021 __ push(string); |
| 2998 // Push the index as a smi. This is safe because of the checks in | 3022 // Push the index as a smi. This is safe because of the checks in |
| 2999 // DoStringCharCodeAt above. | 3023 // DoStringCharCodeAt above. |
| 3000 if (instr->index()->IsConstantOperand()) { | 3024 if (instr->index()->IsConstantOperand()) { |
| 3001 int const_index = ToInteger32(LConstantOperand::cast(instr->index())); | 3025 int const_index = ToInteger32(LConstantOperand::cast(instr->index())); |
| 3002 __ mov(scratch, Operand(Smi::FromInt(const_index))); | 3026 __ mov(scratch, Operand(Smi::FromInt(const_index))); |
| 3003 __ push(scratch); | 3027 __ push(scratch); |
| 3004 } else { | 3028 } else { |
| 3005 Register index = ToRegister(instr->index()); | 3029 Register index = ToRegister(instr->index()); |
| 3006 __ SmiTag(index); | 3030 __ SmiTag(index); |
| 3007 __ push(index); | 3031 __ push(index); |
| 3008 } | 3032 } |
| 3009 __ CallRuntimeSaveDoubles(Runtime::kStringCharCodeAt); | 3033 CallRuntimeFromDeferred(Runtime::kStringCharCodeAt, 2, instr); |
| 3010 RecordSafepointWithRegisters( | |
| 3011 instr->pointer_map(), 2, Safepoint::kNoDeoptimizationIndex); | |
| 3012 if (FLAG_debug_code) { | 3034 if (FLAG_debug_code) { |
| 3013 __ AbortIfNotSmi(r0); | 3035 __ AbortIfNotSmi(r0); |
| 3014 } | 3036 } |
| 3015 __ SmiUntag(r0); | 3037 __ SmiUntag(r0); |
| 3016 __ StoreToSafepointRegisterSlot(r0, result); | 3038 __ StoreToSafepointRegisterSlot(r0, result); |
| 3017 __ PopSafepointRegisters(); | |
| 3018 } | 3039 } |
| 3019 | 3040 |
| 3020 | 3041 |
| 3021 void LCodeGen::DoStringLength(LStringLength* instr) { | 3042 void LCodeGen::DoStringLength(LStringLength* instr) { |
| 3022 Register string = ToRegister(instr->InputAt(0)); | 3043 Register string = ToRegister(instr->InputAt(0)); |
| 3023 Register result = ToRegister(instr->result()); | 3044 Register result = ToRegister(instr->result()); |
| 3024 __ ldr(result, FieldMemOperand(string, String::kLengthOffset)); | 3045 __ ldr(result, FieldMemOperand(string, String::kLengthOffset)); |
| 3025 } | 3046 } |
| 3026 | 3047 |
| 3027 | 3048 |
| (...skipping 35 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 3063 } | 3084 } |
| 3064 | 3085 |
| 3065 | 3086 |
| 3066 void LCodeGen::DoDeferredNumberTagI(LNumberTagI* instr) { | 3087 void LCodeGen::DoDeferredNumberTagI(LNumberTagI* instr) { |
| 3067 Label slow; | 3088 Label slow; |
| 3068 Register reg = ToRegister(instr->InputAt(0)); | 3089 Register reg = ToRegister(instr->InputAt(0)); |
| 3069 DoubleRegister dbl_scratch = d0; | 3090 DoubleRegister dbl_scratch = d0; |
| 3070 SwVfpRegister flt_scratch = s0; | 3091 SwVfpRegister flt_scratch = s0; |
| 3071 | 3092 |
| 3072 // Preserve the value of all registers. | 3093 // Preserve the value of all registers. |
| 3073 __ PushSafepointRegisters(); | 3094 PushSafepointRegistersScope scope(this, Safepoint::kWithRegisters); |
| 3074 | 3095 |
| 3075 // There was overflow, so bits 30 and 31 of the original integer | 3096 // There was overflow, so bits 30 and 31 of the original integer |
| 3076 // disagree. Try to allocate a heap number in new space and store | 3097 // disagree. Try to allocate a heap number in new space and store |
| 3077 // the value in there. If that fails, call the runtime system. | 3098 // the value in there. If that fails, call the runtime system. |
| 3078 Label done; | 3099 Label done; |
| 3079 __ SmiUntag(reg); | 3100 __ SmiUntag(reg); |
| 3080 __ eor(reg, reg, Operand(0x80000000)); | 3101 __ eor(reg, reg, Operand(0x80000000)); |
| 3081 __ vmov(flt_scratch, reg); | 3102 __ vmov(flt_scratch, reg); |
| 3082 __ vcvt_f64_s32(dbl_scratch, flt_scratch); | 3103 __ vcvt_f64_s32(dbl_scratch, flt_scratch); |
| 3083 if (FLAG_inline_new) { | 3104 if (FLAG_inline_new) { |
| 3084 __ LoadRoot(r6, Heap::kHeapNumberMapRootIndex); | 3105 __ LoadRoot(r6, Heap::kHeapNumberMapRootIndex); |
| 3085 __ AllocateHeapNumber(r5, r3, r4, r6, &slow); | 3106 __ AllocateHeapNumber(r5, r3, r4, r6, &slow); |
| 3086 if (!reg.is(r5)) __ mov(reg, r5); | 3107 if (!reg.is(r5)) __ mov(reg, r5); |
| 3087 __ b(&done); | 3108 __ b(&done); |
| 3088 } | 3109 } |
| 3089 | 3110 |
| 3090 // Slow case: Call the runtime system to do the number allocation. | 3111 // Slow case: Call the runtime system to do the number allocation. |
| 3091 __ bind(&slow); | 3112 __ bind(&slow); |
| 3092 | 3113 |
| 3093 // TODO(3095996): Put a valid pointer value in the stack slot where the result | 3114 // TODO(3095996): Put a valid pointer value in the stack slot where the result |
| 3094 // register is stored, as this register is in the pointer map, but contains an | 3115 // register is stored, as this register is in the pointer map, but contains an |
| 3095 // integer value. | 3116 // integer value. |
| 3096 __ mov(ip, Operand(0)); | 3117 __ mov(ip, Operand(0)); |
| 3097 __ StoreToSafepointRegisterSlot(ip, reg); | 3118 __ StoreToSafepointRegisterSlot(ip, reg); |
| 3098 __ CallRuntimeSaveDoubles(Runtime::kAllocateHeapNumber); | 3119 CallRuntimeFromDeferred(Runtime::kAllocateHeapNumber, 0, instr); |
| 3099 RecordSafepointWithRegisters( | |
| 3100 instr->pointer_map(), 0, Safepoint::kNoDeoptimizationIndex); | |
| 3101 if (!reg.is(r0)) __ mov(reg, r0); | 3120 if (!reg.is(r0)) __ mov(reg, r0); |
| 3102 | 3121 |
| 3103 // Done. Put the value in dbl_scratch into the value of the allocated heap | 3122 // Done. Put the value in dbl_scratch into the value of the allocated heap |
| 3104 // number. | 3123 // number. |
| 3105 __ bind(&done); | 3124 __ bind(&done); |
| 3106 __ sub(ip, reg, Operand(kHeapObjectTag)); | 3125 __ sub(ip, reg, Operand(kHeapObjectTag)); |
| 3107 __ vstr(dbl_scratch, ip, HeapNumber::kValueOffset); | 3126 __ vstr(dbl_scratch, ip, HeapNumber::kValueOffset); |
| 3108 __ StoreToSafepointRegisterSlot(reg, reg); | 3127 __ StoreToSafepointRegisterSlot(reg, reg); |
| 3109 __ PopSafepointRegisters(); | |
| 3110 } | 3128 } |
| 3111 | 3129 |
| 3112 | 3130 |
| 3113 void LCodeGen::DoNumberTagD(LNumberTagD* instr) { | 3131 void LCodeGen::DoNumberTagD(LNumberTagD* instr) { |
| 3114 class DeferredNumberTagD: public LDeferredCode { | 3132 class DeferredNumberTagD: public LDeferredCode { |
| 3115 public: | 3133 public: |
| 3116 DeferredNumberTagD(LCodeGen* codegen, LNumberTagD* instr) | 3134 DeferredNumberTagD(LCodeGen* codegen, LNumberTagD* instr) |
| 3117 : LDeferredCode(codegen), instr_(instr) { } | 3135 : LDeferredCode(codegen), instr_(instr) { } |
| 3118 virtual void Generate() { codegen()->DoDeferredNumberTagD(instr_); } | 3136 virtual void Generate() { codegen()->DoDeferredNumberTagD(instr_); } |
| 3119 private: | 3137 private: |
| (...skipping 19 matching lines...) Expand all Loading... |
| 3139 } | 3157 } |
| 3140 | 3158 |
| 3141 | 3159 |
| 3142 void LCodeGen::DoDeferredNumberTagD(LNumberTagD* instr) { | 3160 void LCodeGen::DoDeferredNumberTagD(LNumberTagD* instr) { |
| 3143 // TODO(3095996): Get rid of this. For now, we need to make the | 3161 // TODO(3095996): Get rid of this. For now, we need to make the |
| 3144 // result register contain a valid pointer because it is already | 3162 // result register contain a valid pointer because it is already |
| 3145 // contained in the register pointer map. | 3163 // contained in the register pointer map. |
| 3146 Register reg = ToRegister(instr->result()); | 3164 Register reg = ToRegister(instr->result()); |
| 3147 __ mov(reg, Operand(0)); | 3165 __ mov(reg, Operand(0)); |
| 3148 | 3166 |
| 3149 __ PushSafepointRegisters(); | 3167 PushSafepointRegistersScope scope(this, Safepoint::kWithRegisters); |
| 3150 __ CallRuntimeSaveDoubles(Runtime::kAllocateHeapNumber); | 3168 CallRuntimeFromDeferred(Runtime::kAllocateHeapNumber, 0, instr); |
| 3151 RecordSafepointWithRegisters( | |
| 3152 instr->pointer_map(), 0, Safepoint::kNoDeoptimizationIndex); | |
| 3153 __ StoreToSafepointRegisterSlot(r0, reg); | 3169 __ StoreToSafepointRegisterSlot(r0, reg); |
| 3154 __ PopSafepointRegisters(); | |
| 3155 } | 3170 } |
| 3156 | 3171 |
| 3157 | 3172 |
| 3158 void LCodeGen::DoSmiTag(LSmiTag* instr) { | 3173 void LCodeGen::DoSmiTag(LSmiTag* instr) { |
| 3159 LOperand* input = instr->InputAt(0); | 3174 LOperand* input = instr->InputAt(0); |
| 3160 ASSERT(input->IsRegister() && input->Equals(instr->result())); | 3175 ASSERT(input->IsRegister() && input->Equals(instr->result())); |
| 3161 ASSERT(!instr->hydrogen_value()->CheckFlag(HValue::kCanOverflow)); | 3176 ASSERT(!instr->hydrogen_value()->CheckFlag(HValue::kCanOverflow)); |
| 3162 __ SmiTag(ToRegister(input)); | 3177 __ SmiTag(ToRegister(input)); |
| 3163 } | 3178 } |
| 3164 | 3179 |
| (...skipping 649 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 3814 ASSERT(!environment->HasBeenRegistered()); | 3829 ASSERT(!environment->HasBeenRegistered()); |
| 3815 RegisterEnvironmentForDeoptimization(environment); | 3830 RegisterEnvironmentForDeoptimization(environment); |
| 3816 ASSERT(osr_pc_offset_ == -1); | 3831 ASSERT(osr_pc_offset_ == -1); |
| 3817 osr_pc_offset_ = masm()->pc_offset(); | 3832 osr_pc_offset_ = masm()->pc_offset(); |
| 3818 } | 3833 } |
| 3819 | 3834 |
| 3820 | 3835 |
| 3821 #undef __ | 3836 #undef __ |
| 3822 | 3837 |
| 3823 } } // namespace v8::internal | 3838 } } // namespace v8::internal |
| OLD | NEW |