| 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 |