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 |