OLD | NEW |
1 // Copyright 2012 the V8 project authors. All rights reserved. | 1 // Copyright 2012 the V8 project authors. All rights reserved. |
2 // Redistribution and use in source and binary forms, with or without | 2 // Redistribution and use in source and binary forms, with or without |
3 // modification, are permitted provided that the following conditions are | 3 // modification, are permitted provided that the following conditions are |
4 // met: | 4 // met: |
5 // | 5 // |
6 // * Redistributions of source code must retain the above copyright | 6 // * Redistributions of source code must retain the above copyright |
7 // notice, this list of conditions and the following disclaimer. | 7 // notice, this list of conditions and the following disclaimer. |
8 // * Redistributions in binary form must reproduce the above | 8 // * Redistributions in binary form must reproduce the above |
9 // copyright notice, this list of conditions and the following | 9 // copyright notice, this list of conditions and the following |
10 // disclaimer in the documentation and/or other materials provided | 10 // disclaimer in the documentation and/or other materials provided |
(...skipping 162 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
173 CodeStubInterfaceDescriptor* descriptor) { | 173 CodeStubInterfaceDescriptor* descriptor) { |
174 static Register registers[] = { eax }; | 174 static Register registers[] = { eax }; |
175 descriptor->register_param_count_ = 1; | 175 descriptor->register_param_count_ = 1; |
176 descriptor->register_params_ = registers; | 176 descriptor->register_params_ = registers; |
177 descriptor->deoptimization_handler_ = | 177 descriptor->deoptimization_handler_ = |
178 FUNCTION_ADDR(CompareNilIC_Miss); | 178 FUNCTION_ADDR(CompareNilIC_Miss); |
179 descriptor->SetMissHandler( | 179 descriptor->SetMissHandler( |
180 ExternalReference(IC_Utility(IC::kCompareNilIC_Miss), isolate)); | 180 ExternalReference(IC_Utility(IC::kCompareNilIC_Miss), isolate)); |
181 } | 181 } |
182 | 182 |
| 183 void ToBooleanStub::InitializeInterfaceDescriptor( |
| 184 Isolate* isolate, |
| 185 CodeStubInterfaceDescriptor* descriptor) { |
| 186 static Register registers[] = { eax }; |
| 187 descriptor->register_param_count_ = 1; |
| 188 descriptor->register_params_ = registers; |
| 189 descriptor->deoptimization_handler_ = |
| 190 FUNCTION_ADDR(ToBooleanIC_Miss); |
| 191 descriptor->SetMissHandler( |
| 192 ExternalReference(IC_Utility(IC::kToBooleanIC_Miss), isolate)); |
| 193 } |
| 194 |
183 | 195 |
184 #define __ ACCESS_MASM(masm) | 196 #define __ ACCESS_MASM(masm) |
185 | 197 |
186 | 198 |
187 void HydrogenCodeStub::GenerateLightweightMiss(MacroAssembler* masm) { | 199 void HydrogenCodeStub::GenerateLightweightMiss(MacroAssembler* masm) { |
188 // Update the static counter each time a new code stub is generated. | 200 // Update the static counter each time a new code stub is generated. |
189 Isolate* isolate = masm->isolate(); | 201 Isolate* isolate = masm->isolate(); |
190 isolate->counters()->code_stubs()->Increment(); | 202 isolate->counters()->code_stubs()->Increment(); |
191 | 203 |
192 CodeStubInterfaceDescriptor* descriptor = GetInterfaceDescriptor(isolate); | 204 CodeStubInterfaceDescriptor* descriptor = GetInterfaceDescriptor(isolate); |
(...skipping 269 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
462 // Return and remove the on-stack parameters. | 474 // Return and remove the on-stack parameters. |
463 __ mov(esi, eax); | 475 __ mov(esi, eax); |
464 __ ret(2 * kPointerSize); | 476 __ ret(2 * kPointerSize); |
465 | 477 |
466 // Need to collect. Call into runtime system. | 478 // Need to collect. Call into runtime system. |
467 __ bind(&gc); | 479 __ bind(&gc); |
468 __ TailCallRuntime(Runtime::kPushBlockContext, 2, 1); | 480 __ TailCallRuntime(Runtime::kPushBlockContext, 2, 1); |
469 } | 481 } |
470 | 482 |
471 | 483 |
472 // The stub expects its argument on the stack and returns its result in tos_: | |
473 // zero for false, and a non-zero value for true. | |
474 void ToBooleanStub::Generate(MacroAssembler* masm) { | |
475 // This stub overrides SometimesSetsUpAFrame() to return false. That means | |
476 // we cannot call anything that could cause a GC from this stub. | |
477 Label patch; | |
478 Factory* factory = masm->isolate()->factory(); | |
479 const Register argument = eax; | |
480 const Register map = edx; | |
481 | |
482 if (!types_.IsEmpty()) { | |
483 __ mov(argument, Operand(esp, 1 * kPointerSize)); | |
484 } | |
485 | |
486 // undefined -> false | |
487 CheckOddball(masm, UNDEFINED, Heap::kUndefinedValueRootIndex, false); | |
488 | |
489 // Boolean -> its value | |
490 CheckOddball(masm, BOOLEAN, Heap::kFalseValueRootIndex, false); | |
491 CheckOddball(masm, BOOLEAN, Heap::kTrueValueRootIndex, true); | |
492 | |
493 // 'null' -> false. | |
494 CheckOddball(masm, NULL_TYPE, Heap::kNullValueRootIndex, false); | |
495 | |
496 if (types_.Contains(SMI)) { | |
497 // Smis: 0 -> false, all other -> true | |
498 Label not_smi; | |
499 __ JumpIfNotSmi(argument, ¬_smi, Label::kNear); | |
500 // argument contains the correct return value already. | |
501 if (!tos_.is(argument)) { | |
502 __ mov(tos_, argument); | |
503 } | |
504 __ ret(1 * kPointerSize); | |
505 __ bind(¬_smi); | |
506 } else if (types_.NeedsMap()) { | |
507 // If we need a map later and have a Smi -> patch. | |
508 __ JumpIfSmi(argument, &patch, Label::kNear); | |
509 } | |
510 | |
511 if (types_.NeedsMap()) { | |
512 __ mov(map, FieldOperand(argument, HeapObject::kMapOffset)); | |
513 | |
514 if (types_.CanBeUndetectable()) { | |
515 __ test_b(FieldOperand(map, Map::kBitFieldOffset), | |
516 1 << Map::kIsUndetectable); | |
517 // Undetectable -> false. | |
518 Label not_undetectable; | |
519 __ j(zero, ¬_undetectable, Label::kNear); | |
520 __ Set(tos_, Immediate(0)); | |
521 __ ret(1 * kPointerSize); | |
522 __ bind(¬_undetectable); | |
523 } | |
524 } | |
525 | |
526 if (types_.Contains(SPEC_OBJECT)) { | |
527 // spec object -> true. | |
528 Label not_js_object; | |
529 __ CmpInstanceType(map, FIRST_SPEC_OBJECT_TYPE); | |
530 __ j(below, ¬_js_object, Label::kNear); | |
531 // argument contains the correct return value already. | |
532 if (!tos_.is(argument)) { | |
533 __ Set(tos_, Immediate(1)); | |
534 } | |
535 __ ret(1 * kPointerSize); | |
536 __ bind(¬_js_object); | |
537 } | |
538 | |
539 if (types_.Contains(STRING)) { | |
540 // String value -> false iff empty. | |
541 Label not_string; | |
542 __ CmpInstanceType(map, FIRST_NONSTRING_TYPE); | |
543 __ j(above_equal, ¬_string, Label::kNear); | |
544 __ mov(tos_, FieldOperand(argument, String::kLengthOffset)); | |
545 __ ret(1 * kPointerSize); // the string length is OK as the return value | |
546 __ bind(¬_string); | |
547 } | |
548 | |
549 if (types_.Contains(SYMBOL)) { | |
550 // Symbol value -> true. | |
551 Label not_symbol; | |
552 __ CmpInstanceType(map, SYMBOL_TYPE); | |
553 __ j(not_equal, ¬_symbol, Label::kNear); | |
554 __ bind(¬_symbol); | |
555 } | |
556 | |
557 if (types_.Contains(HEAP_NUMBER)) { | |
558 // heap number -> false iff +0, -0, or NaN. | |
559 Label not_heap_number, false_result; | |
560 __ cmp(map, factory->heap_number_map()); | |
561 __ j(not_equal, ¬_heap_number, Label::kNear); | |
562 __ fldz(); | |
563 __ fld_d(FieldOperand(argument, HeapNumber::kValueOffset)); | |
564 __ FCmp(); | |
565 __ j(zero, &false_result, Label::kNear); | |
566 // argument contains the correct return value already. | |
567 if (!tos_.is(argument)) { | |
568 __ Set(tos_, Immediate(1)); | |
569 } | |
570 __ ret(1 * kPointerSize); | |
571 __ bind(&false_result); | |
572 __ Set(tos_, Immediate(0)); | |
573 __ ret(1 * kPointerSize); | |
574 __ bind(¬_heap_number); | |
575 } | |
576 | |
577 __ bind(&patch); | |
578 GenerateTypeTransition(masm); | |
579 } | |
580 | |
581 | |
582 void StoreBufferOverflowStub::Generate(MacroAssembler* masm) { | 484 void StoreBufferOverflowStub::Generate(MacroAssembler* masm) { |
583 // We don't allow a GC during a store buffer overflow so there is no need to | 485 // We don't allow a GC during a store buffer overflow so there is no need to |
584 // store the registers in any particular way, but we do have to store and | 486 // store the registers in any particular way, but we do have to store and |
585 // restore them. | 487 // restore them. |
586 __ pushad(); | 488 __ pushad(); |
587 if (save_doubles_ == kSaveFPRegs) { | 489 if (save_doubles_ == kSaveFPRegs) { |
588 CpuFeatureScope scope(masm, SSE2); | 490 CpuFeatureScope scope(masm, SSE2); |
589 __ sub(esp, Immediate(kDoubleSize * XMMRegister::kNumRegisters)); | 491 __ sub(esp, Immediate(kDoubleSize * XMMRegister::kNumRegisters)); |
590 for (int i = 0; i < XMMRegister::kNumRegisters; i++) { | 492 for (int i = 0; i < XMMRegister::kNumRegisters; i++) { |
591 XMMRegister reg = XMMRegister::from_code(i); | 493 XMMRegister reg = XMMRegister::from_code(i); |
(...skipping 15 matching lines...) Expand all Loading... |
607 XMMRegister reg = XMMRegister::from_code(i); | 509 XMMRegister reg = XMMRegister::from_code(i); |
608 __ movdbl(reg, Operand(esp, i * kDoubleSize)); | 510 __ movdbl(reg, Operand(esp, i * kDoubleSize)); |
609 } | 511 } |
610 __ add(esp, Immediate(kDoubleSize * XMMRegister::kNumRegisters)); | 512 __ add(esp, Immediate(kDoubleSize * XMMRegister::kNumRegisters)); |
611 } | 513 } |
612 __ popad(); | 514 __ popad(); |
613 __ ret(0); | 515 __ ret(0); |
614 } | 516 } |
615 | 517 |
616 | 518 |
617 void ToBooleanStub::CheckOddball(MacroAssembler* masm, | |
618 Type type, | |
619 Heap::RootListIndex value, | |
620 bool result) { | |
621 const Register argument = eax; | |
622 if (types_.Contains(type)) { | |
623 // If we see an expected oddball, return its ToBoolean value tos_. | |
624 Label different_value; | |
625 __ CompareRoot(argument, value); | |
626 __ j(not_equal, &different_value, Label::kNear); | |
627 if (!result) { | |
628 // If we have to return zero, there is no way around clearing tos_. | |
629 __ Set(tos_, Immediate(0)); | |
630 } else if (!tos_.is(argument)) { | |
631 // If we have to return non-zero, we can re-use the argument if it is the | |
632 // same register as the result, because we never see Smi-zero here. | |
633 __ Set(tos_, Immediate(1)); | |
634 } | |
635 __ ret(1 * kPointerSize); | |
636 __ bind(&different_value); | |
637 } | |
638 } | |
639 | |
640 | |
641 void ToBooleanStub::GenerateTypeTransition(MacroAssembler* masm) { | |
642 __ pop(ecx); // Get return address, operand is now on top of stack. | |
643 __ push(Immediate(Smi::FromInt(tos_.code()))); | |
644 __ push(Immediate(Smi::FromInt(types_.ToByte()))); | |
645 __ push(ecx); // Push return address. | |
646 // Patch the caller to an appropriate specialized stub and return the | |
647 // operation result to the caller of the stub. | |
648 __ TailCallExternalReference( | |
649 ExternalReference(IC_Utility(IC::kToBoolean_Patch), masm->isolate()), | |
650 3, | |
651 1); | |
652 } | |
653 | |
654 | |
655 class FloatingPointHelper : public AllStatic { | 519 class FloatingPointHelper : public AllStatic { |
656 public: | 520 public: |
657 enum ArgLocation { | 521 enum ArgLocation { |
658 ARGS_ON_STACK, | 522 ARGS_ON_STACK, |
659 ARGS_IN_REGISTERS | 523 ARGS_IN_REGISTERS |
660 }; | 524 }; |
661 | 525 |
662 // Code pattern for loading a floating point value. Input value must | 526 // Code pattern for loading a floating point value. Input value must |
663 // be either a smi or a heap number object (fp value). Requirements: | 527 // be either a smi or a heap number object (fp value). Requirements: |
664 // operand in register number. Returns operand as floating point number | 528 // operand in register number. Returns operand as floating point number |
(...skipping 7398 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
8063 __ jmp(generic_construct_stub, RelocInfo::CODE_TARGET); | 7927 __ jmp(generic_construct_stub, RelocInfo::CODE_TARGET); |
8064 } | 7928 } |
8065 } | 7929 } |
8066 | 7930 |
8067 | 7931 |
8068 #undef __ | 7932 #undef __ |
8069 | 7933 |
8070 } } // namespace v8::internal | 7934 } } // namespace v8::internal |
8071 | 7935 |
8072 #endif // V8_TARGET_ARCH_IA32 | 7936 #endif // V8_TARGET_ARCH_IA32 |
OLD | NEW |