Chromium Code Reviews| 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 422 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 433 } else if (op->IsConstantOperand()) { | 433 } else if (op->IsConstantOperand()) { |
| 434 Handle<Object> literal = chunk()->LookupLiteral(LConstantOperand::cast(op)); | 434 Handle<Object> literal = chunk()->LookupLiteral(LConstantOperand::cast(op)); |
| 435 int src_index = DefineDeoptimizationLiteral(literal); | 435 int src_index = DefineDeoptimizationLiteral(literal); |
| 436 translation->StoreLiteral(src_index); | 436 translation->StoreLiteral(src_index); |
| 437 } else { | 437 } else { |
| 438 UNREACHABLE(); | 438 UNREACHABLE(); |
| 439 } | 439 } |
| 440 } | 440 } |
| 441 | 441 |
| 442 | 442 |
| 443 void LCodeGen::CallCode(Handle<Code> code, | 443 void LCodeGen::CallCodeGeneric(Handle<Code> code, |
| 444 RelocInfo::Mode mode, | 444 RelocInfo::Mode mode, |
| 445 LInstruction* instr) { | 445 LInstruction* instr, |
| 446 SafepointMode safepoint_mode, | |
| 447 int argc) { | |
| 446 ASSERT(instr != NULL); | 448 ASSERT(instr != NULL); |
| 447 LPointerMap* pointers = instr->pointer_map(); | 449 LPointerMap* pointers = instr->pointer_map(); |
| 448 RecordPosition(pointers->position()); | 450 RecordPosition(pointers->position()); |
| 449 __ call(code, mode); | 451 __ call(code, mode); |
| 450 RegisterLazyDeoptimization(instr); | 452 RegisterLazyDeoptimization(instr, safepoint_mode, argc); |
| 451 | 453 |
| 452 // Signal that we don't inline smi code before these stubs in the | 454 // Signal that we don't inline smi code before these stubs in the |
| 453 // optimizing code generator. | 455 // optimizing code generator. |
| 454 if (code->kind() == Code::TYPE_RECORDING_BINARY_OP_IC || | 456 if (code->kind() == Code::TYPE_RECORDING_BINARY_OP_IC || |
| 455 code->kind() == Code::COMPARE_IC) { | 457 code->kind() == Code::COMPARE_IC) { |
| 456 __ nop(); | 458 __ nop(); |
| 457 } | 459 } |
| 458 } | 460 } |
| 459 | 461 |
| 460 | 462 |
| 463 void LCodeGen::CallCode(Handle<Code> code, | |
| 464 RelocInfo::Mode mode, | |
| 465 LInstruction* instr) { | |
| 466 CallCodeGeneric(code, mode, instr, RECORD_SIMPLE_SAFEPOINT, 0); | |
| 467 } | |
| 468 | |
| 469 | |
| 461 void LCodeGen::CallRuntime(const Runtime::Function* function, | 470 void LCodeGen::CallRuntime(const Runtime::Function* function, |
| 462 int num_arguments, | 471 int num_arguments, |
| 463 LInstruction* instr) { | 472 LInstruction* instr) { |
| 464 ASSERT(instr != NULL); | 473 ASSERT(instr != NULL); |
| 465 ASSERT(instr->HasPointerMap()); | 474 ASSERT(instr->HasPointerMap()); |
| 466 LPointerMap* pointers = instr->pointer_map(); | 475 LPointerMap* pointers = instr->pointer_map(); |
| 467 RecordPosition(pointers->position()); | 476 RecordPosition(pointers->position()); |
| 468 | 477 |
| 469 __ CallRuntime(function, num_arguments); | 478 __ CallRuntime(function, num_arguments); |
| 470 RegisterLazyDeoptimization(instr); | 479 RegisterLazyDeoptimization(instr, RECORD_SIMPLE_SAFEPOINT, 0); |
| 471 } | 480 } |
| 472 | 481 |
| 473 | 482 |
| 474 void LCodeGen::RegisterLazyDeoptimization(LInstruction* instr) { | 483 void LCodeGen::CallRuntimeFromDeferred(Runtime::FunctionId id, |
| 484 int argc, | |
| 485 LInstruction* instr) { | |
| 486 __ movq(rsi, Operand(rbp, StandardFrameConstants::kContextOffset)); | |
| 487 __ CallRuntimeSaveDoubles(id); | |
| 488 RecordSafepointWithRegisters( | |
| 489 instr->pointer_map(), argc, Safepoint::kNoDeoptimizationIndex); | |
| 490 } | |
| 491 | |
| 492 | |
| 493 void LCodeGen::RegisterLazyDeoptimization(LInstruction* instr, | |
| 494 SafepointMode safepoint_mode, | |
| 495 int argc) { | |
| 475 // Create the environment to bailout to. If the call has side effects | 496 // Create the environment to bailout to. If the call has side effects |
| 476 // execution has to continue after the call otherwise execution can continue | 497 // execution has to continue after the call otherwise execution can continue |
| 477 // from a previous bailout point repeating the call. | 498 // from a previous bailout point repeating the call. |
| 478 LEnvironment* deoptimization_environment; | 499 LEnvironment* deoptimization_environment; |
| 479 if (instr->HasDeoptimizationEnvironment()) { | 500 if (instr->HasDeoptimizationEnvironment()) { |
| 480 deoptimization_environment = instr->deoptimization_environment(); | 501 deoptimization_environment = instr->deoptimization_environment(); |
| 481 } else { | 502 } else { |
| 482 deoptimization_environment = instr->environment(); | 503 deoptimization_environment = instr->environment(); |
| 483 } | 504 } |
| 484 | 505 |
| 485 RegisterEnvironmentForDeoptimization(deoptimization_environment); | 506 RegisterEnvironmentForDeoptimization(deoptimization_environment); |
| 486 RecordSafepoint(instr->pointer_map(), | 507 if (safepoint_mode == RECORD_SIMPLE_SAFEPOINT) { |
| 487 deoptimization_environment->deoptimization_index()); | 508 ASSERT(argc == 0); |
| 509 RecordSafepoint(instr->pointer_map(), | |
| 510 deoptimization_environment->deoptimization_index()); | |
| 511 } else { | |
| 512 ASSERT(safepoint_mode == RECORD_SAFEPOINT_WITH_REGISTERS); | |
| 513 RecordSafepointWithRegisters( | |
| 514 instr->pointer_map(), | |
| 515 argc, | |
| 516 deoptimization_environment->deoptimization_index()); | |
| 517 } | |
| 488 } | 518 } |
| 489 | 519 |
| 490 | 520 |
| 491 void LCodeGen::RegisterEnvironmentForDeoptimization(LEnvironment* environment) { | 521 void LCodeGen::RegisterEnvironmentForDeoptimization(LEnvironment* environment) { |
| 492 if (!environment->HasBeenRegistered()) { | 522 if (!environment->HasBeenRegistered()) { |
| 493 // Physical stack frame layout: | 523 // Physical stack frame layout: |
| 494 // -x ............. -4 0 ..................................... y | 524 // -x ............. -4 0 ..................................... y |
| 495 // [incoming arguments] [spill slots] [pushed outgoing arguments] | 525 // [incoming arguments] [spill slots] [pushed outgoing arguments] |
| 496 | 526 |
| 497 // Layout of the environment: | 527 // Layout of the environment: |
| (...skipping 100 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 598 | 628 |
| 599 inlined_function_count_ = deoptimization_literals_.length(); | 629 inlined_function_count_ = deoptimization_literals_.length(); |
| 600 } | 630 } |
| 601 | 631 |
| 602 | 632 |
| 603 void LCodeGen::RecordSafepoint( | 633 void LCodeGen::RecordSafepoint( |
| 604 LPointerMap* pointers, | 634 LPointerMap* pointers, |
| 605 Safepoint::Kind kind, | 635 Safepoint::Kind kind, |
| 606 int arguments, | 636 int arguments, |
| 607 int deoptimization_index) { | 637 int deoptimization_index) { |
| 638 ASSERT(kind == expected_safepoint_kind_); | |
| 639 | |
| 608 const ZoneList<LOperand*>* operands = pointers->operands(); | 640 const ZoneList<LOperand*>* operands = pointers->operands(); |
| 609 | 641 |
| 610 Safepoint safepoint = safepoints_.DefineSafepoint(masm(), | 642 Safepoint safepoint = safepoints_.DefineSafepoint(masm(), |
| 611 kind, arguments, deoptimization_index); | 643 kind, arguments, deoptimization_index); |
| 612 for (int i = 0; i < operands->length(); i++) { | 644 for (int i = 0; i < operands->length(); i++) { |
| 613 LOperand* pointer = operands->at(i); | 645 LOperand* pointer = operands->at(i); |
| 614 if (pointer->IsStackSlot()) { | 646 if (pointer->IsStackSlot()) { |
| 615 safepoint.DefinePointerSlot(pointer->index()); | 647 safepoint.DefinePointerSlot(pointer->index()); |
| 616 } else if (pointer->IsRegister() && (kind & Safepoint::kWithRegisters)) { | 648 } else if (pointer->IsRegister() && (kind & Safepoint::kWithRegisters)) { |
| 617 safepoint.DefinePointerRegister(ToRegister(pointer)); | 649 safepoint.DefinePointerRegister(ToRegister(pointer)); |
| (...skipping 703 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1321 __ jmp(deferred_stack_check->entry()); | 1353 __ jmp(deferred_stack_check->entry()); |
| 1322 deferred_stack_check->SetExit(chunk_->GetAssemblyLabel(block)); | 1354 deferred_stack_check->SetExit(chunk_->GetAssemblyLabel(block)); |
| 1323 } else { | 1355 } else { |
| 1324 __ jmp(chunk_->GetAssemblyLabel(block)); | 1356 __ jmp(chunk_->GetAssemblyLabel(block)); |
| 1325 } | 1357 } |
| 1326 } | 1358 } |
| 1327 } | 1359 } |
| 1328 | 1360 |
| 1329 | 1361 |
| 1330 void LCodeGen::DoDeferredStackCheck(LGoto* instr) { | 1362 void LCodeGen::DoDeferredStackCheck(LGoto* instr) { |
| 1331 __ Pushad(); | 1363 PushSafepointRegistersScope scope(this); |
| 1332 __ CallRuntimeSaveDoubles(Runtime::kStackGuard); | 1364 CallRuntimeFromDeferred(Runtime::kStackGuard, 0, instr); |
| 1333 RecordSafepointWithRegisters( | |
| 1334 instr->pointer_map(), 0, Safepoint::kNoDeoptimizationIndex); | |
| 1335 __ Popad(); | |
| 1336 } | 1365 } |
| 1337 | 1366 |
| 1338 | 1367 |
| 1339 void LCodeGen::DoGoto(LGoto* instr) { | 1368 void LCodeGen::DoGoto(LGoto* instr) { |
| 1340 class DeferredStackCheck: public LDeferredCode { | 1369 class DeferredStackCheck: public LDeferredCode { |
| 1341 public: | 1370 public: |
| 1342 DeferredStackCheck(LCodeGen* codegen, LGoto* instr) | 1371 DeferredStackCheck(LCodeGen* codegen, LGoto* instr) |
| 1343 : LDeferredCode(codegen), instr_(instr) { } | 1372 : LDeferredCode(codegen), instr_(instr) { } |
| 1344 virtual void Generate() { codegen()->DoDeferredStackCheck(instr_); } | 1373 virtual void Generate() { codegen()->DoDeferredStackCheck(instr_); } |
| 1345 private: | 1374 private: |
| (...skipping 584 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1930 __ bind(&false_result); | 1959 __ bind(&false_result); |
| 1931 __ LoadRoot(ToRegister(instr->result()), Heap::kFalseValueRootIndex); | 1960 __ LoadRoot(ToRegister(instr->result()), Heap::kFalseValueRootIndex); |
| 1932 | 1961 |
| 1933 __ bind(deferred->exit()); | 1962 __ bind(deferred->exit()); |
| 1934 __ bind(&done); | 1963 __ bind(&done); |
| 1935 } | 1964 } |
| 1936 | 1965 |
| 1937 | 1966 |
| 1938 void LCodeGen::DoDeferredLInstanceOfKnownGlobal(LInstanceOfKnownGlobal* instr, | 1967 void LCodeGen::DoDeferredLInstanceOfKnownGlobal(LInstanceOfKnownGlobal* instr, |
| 1939 Label* map_check) { | 1968 Label* map_check) { |
| 1940 __ PushSafepointRegisters(); | 1969 { |
| 1941 InstanceofStub::Flags flags = static_cast<InstanceofStub::Flags>( | 1970 PushSafepointRegistersScope scope(this); |
| 1942 InstanceofStub::kNoFlags | InstanceofStub::kCallSiteInlineCheck); | 1971 InstanceofStub::Flags flags = static_cast<InstanceofStub::Flags>( |
| 1943 InstanceofStub stub(flags); | 1972 InstanceofStub::kNoFlags | InstanceofStub::kCallSiteInlineCheck); |
| 1973 InstanceofStub stub(flags); | |
| 1944 | 1974 |
| 1945 __ push(ToRegister(instr->InputAt(0))); | 1975 __ push(ToRegister(instr->InputAt(0))); |
| 1946 __ Push(instr->function()); | 1976 __ Push(instr->function()); |
| 1947 Register temp = ToRegister(instr->TempAt(0)); | 1977 |
| 1948 ASSERT(temp.is(rdi)); | 1978 Register temp = ToRegister(instr->TempAt(0)); |
| 1949 static const int kAdditionalDelta = 16; | 1979 static const int kAdditionalDelta = 13; |
| 1950 int delta = | 1980 int delta = |
| 1951 masm_->SizeOfCodeGeneratedSince(map_check) + kAdditionalDelta; | 1981 masm_->SizeOfCodeGeneratedSince(map_check) + kAdditionalDelta; |
| 1952 __ movq(temp, Immediate(delta)); | 1982 __ movq(temp, Immediate(delta)); |
| 1953 __ push(temp); | 1983 __ push(temp); |
| 1954 CallCode(stub.GetCode(), RelocInfo::CODE_TARGET, instr); | 1984 |
| 1955 __ movq(kScratchRegister, rax); | 1985 // |
|
fschneider
2011/04/07 11:28:30
Remove extra line.
| |
| 1956 __ PopSafepointRegisters(); | 1986 CallCodeGeneric(stub.GetCode(), |
| 1987 RelocInfo::CODE_TARGET, | |
| 1988 instr, | |
| 1989 RECORD_SAFEPOINT_WITH_REGISTERS, | |
| 1990 2); | |
| 1991 ASSERT(delta == masm_->SizeOfCodeGeneratedSince(map_check)); | |
| 1992 __ movq(kScratchRegister, rax); | |
| 1993 } | |
| 1957 __ testq(kScratchRegister, kScratchRegister); | 1994 __ testq(kScratchRegister, kScratchRegister); |
| 1958 Label load_false; | 1995 Label load_false; |
| 1959 Label done; | 1996 Label done; |
| 1960 __ j(not_zero, &load_false); | 1997 __ j(not_zero, &load_false); |
| 1961 __ LoadRoot(rax, Heap::kTrueValueRootIndex); | 1998 __ LoadRoot(rax, Heap::kTrueValueRootIndex); |
| 1962 __ jmp(&done); | 1999 __ jmp(&done); |
| 1963 __ bind(&load_false); | 2000 __ bind(&load_false); |
| 1964 __ LoadRoot(rax, Heap::kFalseValueRootIndex); | 2001 __ LoadRoot(rax, Heap::kFalseValueRootIndex); |
| 1965 __ bind(&done); | 2002 __ bind(&done); |
| 1966 } | 2003 } |
| (...skipping 561 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 2528 RecordPosition(pointers->position()); | 2565 RecordPosition(pointers->position()); |
| 2529 | 2566 |
| 2530 // Invoke function. | 2567 // Invoke function. |
| 2531 if (*function == *info()->closure()) { | 2568 if (*function == *info()->closure()) { |
| 2532 __ CallSelf(); | 2569 __ CallSelf(); |
| 2533 } else { | 2570 } else { |
| 2534 __ call(FieldOperand(rdi, JSFunction::kCodeEntryOffset)); | 2571 __ call(FieldOperand(rdi, JSFunction::kCodeEntryOffset)); |
| 2535 } | 2572 } |
| 2536 | 2573 |
| 2537 // Setup deoptimization. | 2574 // Setup deoptimization. |
| 2538 RegisterLazyDeoptimization(instr); | 2575 RegisterLazyDeoptimization(instr, RECORD_SIMPLE_SAFEPOINT, 0); |
| 2539 | 2576 |
| 2540 // Restore context. | 2577 // Restore context. |
| 2541 __ movq(rsi, Operand(rbp, StandardFrameConstants::kContextOffset)); | 2578 __ movq(rsi, Operand(rbp, StandardFrameConstants::kContextOffset)); |
| 2542 } | 2579 } |
| 2543 | 2580 |
| 2544 | 2581 |
| 2545 void LCodeGen::DoCallConstantFunction(LCallConstantFunction* instr) { | 2582 void LCodeGen::DoCallConstantFunction(LCallConstantFunction* instr) { |
| 2546 ASSERT(ToRegister(instr->result()).is(rax)); | 2583 ASSERT(ToRegister(instr->result()).is(rax)); |
| 2547 __ Move(rdi, instr->function()); | 2584 __ Move(rdi, instr->function()); |
| 2548 CallKnownFunction(instr->function(), instr->arity(), instr); | 2585 CallKnownFunction(instr->function(), instr->arity(), instr); |
| 2549 } | 2586 } |
| 2550 | 2587 |
| 2551 | 2588 |
| 2552 void LCodeGen::DoDeferredMathAbsTaggedHeapNumber(LUnaryMathOperation* instr) { | 2589 void LCodeGen::DoDeferredMathAbsTaggedHeapNumber(LUnaryMathOperation* instr) { |
| 2553 Register input_reg = ToRegister(instr->InputAt(0)); | 2590 Register input_reg = ToRegister(instr->InputAt(0)); |
| 2554 __ CompareRoot(FieldOperand(input_reg, HeapObject::kMapOffset), | 2591 __ CompareRoot(FieldOperand(input_reg, HeapObject::kMapOffset), |
| 2555 Heap::kHeapNumberMapRootIndex); | 2592 Heap::kHeapNumberMapRootIndex); |
| 2556 DeoptimizeIf(not_equal, instr->environment()); | 2593 DeoptimizeIf(not_equal, instr->environment()); |
| 2557 | 2594 |
| 2558 Label done; | 2595 Label done; |
| 2559 Register tmp = input_reg.is(rax) ? rcx : rax; | 2596 Register tmp = input_reg.is(rax) ? rcx : rax; |
| 2560 Register tmp2 = tmp.is(rcx) ? rdx : input_reg.is(rcx) ? rdx : rcx; | 2597 Register tmp2 = tmp.is(rcx) ? rdx : input_reg.is(rcx) ? rdx : rcx; |
| 2561 | 2598 |
| 2562 // Preserve the value of all registers. | 2599 // Preserve the value of all registers. |
| 2563 __ PushSafepointRegisters(); | 2600 PushSafepointRegistersScope scope(this); |
| 2564 | 2601 |
| 2565 Label negative; | 2602 Label negative; |
| 2566 __ movl(tmp, FieldOperand(input_reg, HeapNumber::kExponentOffset)); | 2603 __ movl(tmp, FieldOperand(input_reg, HeapNumber::kExponentOffset)); |
| 2567 // Check the sign of the argument. If the argument is positive, just | 2604 // Check the sign of the argument. If the argument is positive, just |
| 2568 // return it. We do not need to patch the stack since |input| and | 2605 // return it. We do not need to patch the stack since |input| and |
| 2569 // |result| are the same register and |input| will be restored | 2606 // |result| are the same register and |input| will be restored |
| 2570 // unchanged by popping safepoint registers. | 2607 // unchanged by popping safepoint registers. |
| 2571 __ testl(tmp, Immediate(HeapNumber::kSignMask)); | 2608 __ testl(tmp, Immediate(HeapNumber::kSignMask)); |
| 2572 __ j(not_zero, &negative); | 2609 __ j(not_zero, &negative); |
| 2573 __ jmp(&done); | 2610 __ jmp(&done); |
| 2574 | 2611 |
| 2575 __ bind(&negative); | 2612 __ bind(&negative); |
| 2576 | 2613 |
| 2577 Label allocated, slow; | 2614 Label allocated, slow; |
| 2578 __ AllocateHeapNumber(tmp, tmp2, &slow); | 2615 __ AllocateHeapNumber(tmp, tmp2, &slow); |
| 2579 __ jmp(&allocated); | 2616 __ jmp(&allocated); |
| 2580 | 2617 |
| 2581 // Slow case: Call the runtime system to do the number allocation. | 2618 // Slow case: Call the runtime system to do the number allocation. |
| 2582 __ bind(&slow); | 2619 __ bind(&slow); |
| 2583 | 2620 |
| 2584 __ CallRuntimeSaveDoubles(Runtime::kAllocateHeapNumber); | 2621 CallRuntimeFromDeferred(Runtime::kAllocateHeapNumber, 0, instr); |
| 2585 RecordSafepointWithRegisters( | |
| 2586 instr->pointer_map(), 0, Safepoint::kNoDeoptimizationIndex); | |
| 2587 // Set the pointer to the new heap number in tmp. | 2622 // Set the pointer to the new heap number in tmp. |
| 2588 if (!tmp.is(rax)) { | 2623 if (!tmp.is(rax)) { |
| 2589 __ movq(tmp, rax); | 2624 __ movq(tmp, rax); |
| 2590 } | 2625 } |
| 2591 | 2626 |
| 2592 // Restore input_reg after call to runtime. | 2627 // Restore input_reg after call to runtime. |
| 2593 __ LoadFromSafepointRegisterSlot(input_reg, input_reg); | 2628 __ LoadFromSafepointRegisterSlot(input_reg, input_reg); |
| 2594 | 2629 |
| 2595 __ bind(&allocated); | 2630 __ bind(&allocated); |
| 2596 __ movq(tmp2, FieldOperand(input_reg, HeapNumber::kValueOffset)); | 2631 __ movq(tmp2, FieldOperand(input_reg, HeapNumber::kValueOffset)); |
| 2597 __ shl(tmp2, Immediate(1)); | 2632 __ shl(tmp2, Immediate(1)); |
| 2598 __ shr(tmp2, Immediate(1)); | 2633 __ shr(tmp2, Immediate(1)); |
| 2599 __ movq(FieldOperand(tmp, HeapNumber::kValueOffset), tmp2); | 2634 __ movq(FieldOperand(tmp, HeapNumber::kValueOffset), tmp2); |
| 2600 __ StoreToSafepointRegisterSlot(input_reg, tmp); | 2635 __ StoreToSafepointRegisterSlot(input_reg, tmp); |
| 2601 | 2636 |
| 2602 __ bind(&done); | 2637 __ bind(&done); |
| 2603 __ PopSafepointRegisters(); | |
| 2604 } | 2638 } |
| 2605 | 2639 |
| 2606 | 2640 |
| 2607 void LCodeGen::EmitIntegerMathAbs(LUnaryMathOperation* instr) { | 2641 void LCodeGen::EmitIntegerMathAbs(LUnaryMathOperation* instr) { |
| 2608 Register input_reg = ToRegister(instr->InputAt(0)); | 2642 Register input_reg = ToRegister(instr->InputAt(0)); |
| 2609 __ testl(input_reg, input_reg); | 2643 __ testl(input_reg, input_reg); |
| 2610 Label is_positive; | 2644 Label is_positive; |
| 2611 __ j(not_sign, &is_positive); | 2645 __ j(not_sign, &is_positive); |
| 2612 __ negl(input_reg); // Sets flags. | 2646 __ negl(input_reg); // Sets flags. |
| 2613 DeoptimizeIf(negative, instr->environment()); | 2647 DeoptimizeIf(negative, instr->environment()); |
| (...skipping 538 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 3152 | 3186 |
| 3153 void LCodeGen::DoDeferredStringCharCodeAt(LStringCharCodeAt* instr) { | 3187 void LCodeGen::DoDeferredStringCharCodeAt(LStringCharCodeAt* instr) { |
| 3154 Register string = ToRegister(instr->string()); | 3188 Register string = ToRegister(instr->string()); |
| 3155 Register result = ToRegister(instr->result()); | 3189 Register result = ToRegister(instr->result()); |
| 3156 | 3190 |
| 3157 // TODO(3095996): Get rid of this. For now, we need to make the | 3191 // TODO(3095996): Get rid of this. For now, we need to make the |
| 3158 // result register contain a valid pointer because it is already | 3192 // result register contain a valid pointer because it is already |
| 3159 // contained in the register pointer map. | 3193 // contained in the register pointer map. |
| 3160 __ Set(result, 0); | 3194 __ Set(result, 0); |
| 3161 | 3195 |
| 3162 __ PushSafepointRegisters(); | 3196 PushSafepointRegistersScope scope(this); |
| 3163 __ push(string); | 3197 __ push(string); |
| 3164 // Push the index as a smi. This is safe because of the checks in | 3198 // Push the index as a smi. This is safe because of the checks in |
| 3165 // DoStringCharCodeAt above. | 3199 // DoStringCharCodeAt above. |
| 3166 STATIC_ASSERT(String::kMaxLength <= Smi::kMaxValue); | 3200 STATIC_ASSERT(String::kMaxLength <= Smi::kMaxValue); |
| 3167 if (instr->index()->IsConstantOperand()) { | 3201 if (instr->index()->IsConstantOperand()) { |
| 3168 int const_index = ToInteger32(LConstantOperand::cast(instr->index())); | 3202 int const_index = ToInteger32(LConstantOperand::cast(instr->index())); |
| 3169 __ Push(Smi::FromInt(const_index)); | 3203 __ Push(Smi::FromInt(const_index)); |
| 3170 } else { | 3204 } else { |
| 3171 Register index = ToRegister(instr->index()); | 3205 Register index = ToRegister(instr->index()); |
| 3172 __ Integer32ToSmi(index, index); | 3206 __ Integer32ToSmi(index, index); |
| 3173 __ push(index); | 3207 __ push(index); |
| 3174 } | 3208 } |
| 3175 __ movq(rsi, Operand(rbp, StandardFrameConstants::kContextOffset)); | 3209 CallRuntimeFromDeferred(Runtime::kStringCharCodeAt, 2, instr); |
| 3176 __ CallRuntimeSaveDoubles(Runtime::kStringCharCodeAt); | |
| 3177 RecordSafepointWithRegisters( | |
| 3178 instr->pointer_map(), 2, Safepoint::kNoDeoptimizationIndex); | |
| 3179 if (FLAG_debug_code) { | 3210 if (FLAG_debug_code) { |
| 3180 __ AbortIfNotSmi(rax); | 3211 __ AbortIfNotSmi(rax); |
| 3181 } | 3212 } |
| 3182 __ SmiToInteger32(rax, rax); | 3213 __ SmiToInteger32(rax, rax); |
| 3183 __ StoreToSafepointRegisterSlot(result, rax); | 3214 __ StoreToSafepointRegisterSlot(result, rax); |
| 3184 __ PopSafepointRegisters(); | |
| 3185 } | 3215 } |
| 3186 | 3216 |
| 3187 | 3217 |
| 3188 void LCodeGen::DoStringCharFromCode(LStringCharFromCode* instr) { | 3218 void LCodeGen::DoStringCharFromCode(LStringCharFromCode* instr) { |
| 3189 class DeferredStringCharFromCode: public LDeferredCode { | 3219 class DeferredStringCharFromCode: public LDeferredCode { |
| 3190 public: | 3220 public: |
| 3191 DeferredStringCharFromCode(LCodeGen* codegen, LStringCharFromCode* instr) | 3221 DeferredStringCharFromCode(LCodeGen* codegen, LStringCharFromCode* instr) |
| 3192 : LDeferredCode(codegen), instr_(instr) { } | 3222 : LDeferredCode(codegen), instr_(instr) { } |
| 3193 virtual void Generate() { codegen()->DoDeferredStringCharFromCode(instr_); } | 3223 virtual void Generate() { codegen()->DoDeferredStringCharFromCode(instr_); } |
| 3194 private: | 3224 private: |
| (...skipping 22 matching lines...) Expand all Loading... | |
| 3217 | 3247 |
| 3218 void LCodeGen::DoDeferredStringCharFromCode(LStringCharFromCode* instr) { | 3248 void LCodeGen::DoDeferredStringCharFromCode(LStringCharFromCode* instr) { |
| 3219 Register char_code = ToRegister(instr->char_code()); | 3249 Register char_code = ToRegister(instr->char_code()); |
| 3220 Register result = ToRegister(instr->result()); | 3250 Register result = ToRegister(instr->result()); |
| 3221 | 3251 |
| 3222 // TODO(3095996): Get rid of this. For now, we need to make the | 3252 // TODO(3095996): Get rid of this. For now, we need to make the |
| 3223 // result register contain a valid pointer because it is already | 3253 // result register contain a valid pointer because it is already |
| 3224 // contained in the register pointer map. | 3254 // contained in the register pointer map. |
| 3225 __ Set(result, 0); | 3255 __ Set(result, 0); |
| 3226 | 3256 |
| 3227 __ PushSafepointRegisters(); | 3257 PushSafepointRegistersScope scope(this); |
| 3228 __ Integer32ToSmi(char_code, char_code); | 3258 __ Integer32ToSmi(char_code, char_code); |
| 3229 __ push(char_code); | 3259 __ push(char_code); |
| 3230 __ CallRuntimeSaveDoubles(Runtime::kCharFromCode); | 3260 CallRuntimeFromDeferred(Runtime::kCharFromCode, 1, instr); |
| 3231 RecordSafepointWithRegisters( | |
| 3232 instr->pointer_map(), 1, Safepoint::kNoDeoptimizationIndex); | |
| 3233 __ StoreToSafepointRegisterSlot(result, rax); | 3261 __ StoreToSafepointRegisterSlot(result, rax); |
| 3234 __ PopSafepointRegisters(); | |
| 3235 } | 3262 } |
| 3236 | 3263 |
| 3237 | 3264 |
| 3238 void LCodeGen::DoStringLength(LStringLength* instr) { | 3265 void LCodeGen::DoStringLength(LStringLength* instr) { |
| 3239 Register string = ToRegister(instr->string()); | 3266 Register string = ToRegister(instr->string()); |
| 3240 Register result = ToRegister(instr->result()); | 3267 Register result = ToRegister(instr->result()); |
| 3241 __ movq(result, FieldOperand(string, String::kLengthOffset)); | 3268 __ movq(result, FieldOperand(string, String::kLengthOffset)); |
| 3242 } | 3269 } |
| 3243 | 3270 |
| 3244 | 3271 |
| (...skipping 44 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 3289 } | 3316 } |
| 3290 | 3317 |
| 3291 | 3318 |
| 3292 void LCodeGen::DoDeferredNumberTagD(LNumberTagD* instr) { | 3319 void LCodeGen::DoDeferredNumberTagD(LNumberTagD* instr) { |
| 3293 // TODO(3095996): Get rid of this. For now, we need to make the | 3320 // TODO(3095996): Get rid of this. For now, we need to make the |
| 3294 // result register contain a valid pointer because it is already | 3321 // result register contain a valid pointer because it is already |
| 3295 // contained in the register pointer map. | 3322 // contained in the register pointer map. |
| 3296 Register reg = ToRegister(instr->result()); | 3323 Register reg = ToRegister(instr->result()); |
| 3297 __ Move(reg, Smi::FromInt(0)); | 3324 __ Move(reg, Smi::FromInt(0)); |
| 3298 | 3325 |
| 3299 __ PushSafepointRegisters(); | 3326 { |
| 3300 __ CallRuntimeSaveDoubles(Runtime::kAllocateHeapNumber); | 3327 PushSafepointRegistersScope scope(this); |
| 3301 RecordSafepointWithRegisters( | 3328 CallRuntimeFromDeferred(Runtime::kAllocateHeapNumber, 0, instr); |
| 3302 instr->pointer_map(), 0, Safepoint::kNoDeoptimizationIndex); | 3329 // Ensure that value in rax survives popping registers. |
| 3303 // Ensure that value in rax survives popping registers. | 3330 __ movq(kScratchRegister, rax); |
| 3304 __ movq(kScratchRegister, rax); | 3331 } |
| 3305 __ PopSafepointRegisters(); | |
| 3306 __ movq(reg, kScratchRegister); | 3332 __ movq(reg, kScratchRegister); |
| 3307 } | 3333 } |
| 3308 | 3334 |
| 3309 | 3335 |
| 3310 void LCodeGen::DoSmiTag(LSmiTag* instr) { | 3336 void LCodeGen::DoSmiTag(LSmiTag* instr) { |
| 3311 ASSERT(instr->InputAt(0)->Equals(instr->result())); | 3337 ASSERT(instr->InputAt(0)->Equals(instr->result())); |
| 3312 Register input = ToRegister(instr->InputAt(0)); | 3338 Register input = ToRegister(instr->InputAt(0)); |
| 3313 ASSERT(!instr->hydrogen_value()->CheckFlag(HValue::kCanOverflow)); | 3339 ASSERT(!instr->hydrogen_value()->CheckFlag(HValue::kCanOverflow)); |
| 3314 __ Integer32ToSmi(input, input); | 3340 __ Integer32ToSmi(input, input); |
| 3315 } | 3341 } |
| (...skipping 645 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 3961 RegisterEnvironmentForDeoptimization(environment); | 3987 RegisterEnvironmentForDeoptimization(environment); |
| 3962 ASSERT(osr_pc_offset_ == -1); | 3988 ASSERT(osr_pc_offset_ == -1); |
| 3963 osr_pc_offset_ = masm()->pc_offset(); | 3989 osr_pc_offset_ = masm()->pc_offset(); |
| 3964 } | 3990 } |
| 3965 | 3991 |
| 3966 #undef __ | 3992 #undef __ |
| 3967 | 3993 |
| 3968 } } // namespace v8::internal | 3994 } } // namespace v8::internal |
| 3969 | 3995 |
| 3970 #endif // V8_TARGET_ARCH_X64 | 3996 #endif // V8_TARGET_ARCH_X64 |
| OLD | NEW |