Chromium Code Reviews| 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 79 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 90 CodeStubInterfaceDescriptor* descriptor) { | 90 CodeStubInterfaceDescriptor* descriptor) { |
| 91 static Register registers[] = { r0, r1 }; | 91 static Register registers[] = { r0, r1 }; |
| 92 descriptor->register_param_count_ = 2; | 92 descriptor->register_param_count_ = 2; |
| 93 descriptor->register_params_ = registers; | 93 descriptor->register_params_ = registers; |
| 94 Address entry = | 94 Address entry = |
| 95 Runtime::FunctionForId(Runtime::kTransitionElementsKind)->entry; | 95 Runtime::FunctionForId(Runtime::kTransitionElementsKind)->entry; |
| 96 descriptor->deoptimization_handler_ = FUNCTION_ADDR(entry); | 96 descriptor->deoptimization_handler_ = FUNCTION_ADDR(entry); |
| 97 } | 97 } |
| 98 | 98 |
| 99 | 99 |
| 100 static void InitializeArrayConstructorDescriptor(Isolate* isolate, | 100 static void InitializeArrayConstructorDescriptor( |
| 101 CodeStubInterfaceDescriptor* descriptor) { | 101 Isolate* isolate, |
| 102 CodeStubInterfaceDescriptor* descriptor, | |
| 103 int constant_stack_parameter_count) { | |
| 102 // register state | 104 // register state |
| 103 // r1 -- constructor function | |
| 104 // r2 -- type info cell with elements kind | 105 // r2 -- type info cell with elements kind |
|
Hannes Payer (out of office)
2013/04/18 11:14:39
why is r1 not used?
mvstanton
2013/04/18 13:39:26
Good question and there is a decent answer. Each s
| |
| 105 // r0 -- number of arguments to the constructor function | 106 static Register registers[] = { r2 }; |
| 106 static Register registers[] = { r1, r2 }; | 107 descriptor->register_param_count_ = 1; |
| 107 descriptor->register_param_count_ = 2; | 108 if (constant_stack_parameter_count != 0) { |
| 108 // stack param count needs (constructor pointer, and single argument) | 109 // stack param count needs (constructor pointer, and single argument) |
| 109 descriptor->stack_parameter_count_ = &r0; | 110 descriptor->stack_parameter_count_ = &r0; |
| 111 } | |
| 112 descriptor->hint_stack_parameter_count_ = constant_stack_parameter_count; | |
| 110 descriptor->register_params_ = registers; | 113 descriptor->register_params_ = registers; |
| 111 descriptor->function_mode_ = JS_FUNCTION_STUB_MODE; | 114 descriptor->function_mode_ = JS_FUNCTION_STUB_MODE; |
| 112 descriptor->deoptimization_handler_ = | 115 descriptor->deoptimization_handler_ = |
| 113 FUNCTION_ADDR(ArrayConstructor_StubFailure); | 116 FUNCTION_ADDR(ArrayConstructor_StubFailure); |
| 114 } | 117 } |
| 115 | 118 |
| 116 | 119 |
| 117 void ArrayNoArgumentConstructorStub::InitializeInterfaceDescriptor( | 120 void ArrayNoArgumentConstructorStub::InitializeInterfaceDescriptor( |
| 118 Isolate* isolate, | 121 Isolate* isolate, |
| 119 CodeStubInterfaceDescriptor* descriptor) { | 122 CodeStubInterfaceDescriptor* descriptor) { |
| 120 InitializeArrayConstructorDescriptor(isolate, descriptor); | 123 InitializeArrayConstructorDescriptor(isolate, descriptor, 0); |
| 121 } | 124 } |
| 122 | 125 |
| 123 | 126 |
| 124 void ArraySingleArgumentConstructorStub::InitializeInterfaceDescriptor( | 127 void ArraySingleArgumentConstructorStub::InitializeInterfaceDescriptor( |
| 125 Isolate* isolate, | 128 Isolate* isolate, |
| 126 CodeStubInterfaceDescriptor* descriptor) { | 129 CodeStubInterfaceDescriptor* descriptor) { |
| 127 InitializeArrayConstructorDescriptor(isolate, descriptor); | 130 InitializeArrayConstructorDescriptor(isolate, descriptor, 1); |
| 128 } | 131 } |
| 129 | 132 |
| 130 | 133 |
| 131 void ArrayNArgumentsConstructorStub::InitializeInterfaceDescriptor( | 134 void ArrayNArgumentsConstructorStub::InitializeInterfaceDescriptor( |
| 132 Isolate* isolate, | 135 Isolate* isolate, |
| 133 CodeStubInterfaceDescriptor* descriptor) { | 136 CodeStubInterfaceDescriptor* descriptor) { |
| 134 InitializeArrayConstructorDescriptor(isolate, descriptor); | 137 InitializeArrayConstructorDescriptor(isolate, descriptor, -1); |
| 135 } | 138 } |
| 136 | 139 |
| 137 | 140 |
| 138 #define __ ACCESS_MASM(masm) | 141 #define __ ACCESS_MASM(masm) |
| 139 | 142 |
| 140 static void EmitIdenticalObjectComparison(MacroAssembler* masm, | 143 static void EmitIdenticalObjectComparison(MacroAssembler* masm, |
| 141 Label* slow, | 144 Label* slow, |
| 142 Condition cond); | 145 Condition cond); |
| 143 static void EmitSmiNonsmiComparison(MacroAssembler* masm, | 146 static void EmitSmiNonsmiComparison(MacroAssembler* masm, |
| 144 Register lhs, | 147 Register lhs, |
| (...skipping 3236 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 3381 result_size_ == 1; | 3384 result_size_ == 1; |
| 3382 } | 3385 } |
| 3383 | 3386 |
| 3384 | 3387 |
| 3385 void CodeStub::GenerateStubsAheadOfTime(Isolate* isolate) { | 3388 void CodeStub::GenerateStubsAheadOfTime(Isolate* isolate) { |
| 3386 CEntryStub::GenerateAheadOfTime(isolate); | 3389 CEntryStub::GenerateAheadOfTime(isolate); |
| 3387 WriteInt32ToHeapNumberStub::GenerateFixedRegStubsAheadOfTime(isolate); | 3390 WriteInt32ToHeapNumberStub::GenerateFixedRegStubsAheadOfTime(isolate); |
| 3388 StoreBufferOverflowStub::GenerateFixedRegStubsAheadOfTime(isolate); | 3391 StoreBufferOverflowStub::GenerateFixedRegStubsAheadOfTime(isolate); |
| 3389 StubFailureTrampolineStub::GenerateAheadOfTime(isolate); | 3392 StubFailureTrampolineStub::GenerateAheadOfTime(isolate); |
| 3390 RecordWriteStub::GenerateFixedRegStubsAheadOfTime(isolate); | 3393 RecordWriteStub::GenerateFixedRegStubsAheadOfTime(isolate); |
| 3394 ArrayConstructorStubBase::GenerateStubsAheadOfTime(isolate); | |
| 3391 } | 3395 } |
| 3392 | 3396 |
| 3393 | 3397 |
| 3394 void CodeStub::GenerateFPStubs(Isolate* isolate) { | 3398 void CodeStub::GenerateFPStubs(Isolate* isolate) { |
| 3395 SaveFPRegsMode mode = kSaveFPRegs; | 3399 SaveFPRegsMode mode = kSaveFPRegs; |
| 3396 CEntryStub save_doubles(1, mode); | 3400 CEntryStub save_doubles(1, mode); |
| 3397 StoreBufferOverflowStub stub(mode); | 3401 StoreBufferOverflowStub stub(mode); |
| 3398 // These stubs might already be in the snapshot, detect that and don't | 3402 // These stubs might already be in the snapshot, detect that and don't |
| 3399 // regenerate, which would lead to code stub initialization state being messed | 3403 // regenerate, which would lead to code stub initialization state being messed |
| 3400 // up. | 3404 // up. |
| (...skipping 1677 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 5078 __ CompareRoot(r3, Heap::kUndefinedValueRootIndex); | 5082 __ CompareRoot(r3, Heap::kUndefinedValueRootIndex); |
| 5079 __ b(eq, &done); | 5083 __ b(eq, &done); |
| 5080 | 5084 |
| 5081 // Special handling of the Array() function, which caches not only the | 5085 // Special handling of the Array() function, which caches not only the |
| 5082 // monomorphic Array function but the initial ElementsKind with special | 5086 // monomorphic Array function but the initial ElementsKind with special |
| 5083 // sentinels | 5087 // sentinels |
| 5084 Handle<Object> terminal_kind_sentinel = | 5088 Handle<Object> terminal_kind_sentinel = |
| 5085 TypeFeedbackCells::MonomorphicArraySentinel(masm->isolate(), | 5089 TypeFeedbackCells::MonomorphicArraySentinel(masm->isolate(), |
| 5086 LAST_FAST_ELEMENTS_KIND); | 5090 LAST_FAST_ELEMENTS_KIND); |
| 5087 __ cmp(r3, Operand(terminal_kind_sentinel)); | 5091 __ cmp(r3, Operand(terminal_kind_sentinel)); |
| 5088 __ b(ne, &miss); | 5092 __ b(gt, &miss); |
| 5089 // Make sure the function is the Array() function | 5093 // Make sure the function is the Array() function |
| 5090 __ LoadArrayFunction(r3); | 5094 __ LoadArrayFunction(r3); |
| 5091 __ cmp(r1, r3); | 5095 __ cmp(r1, r3); |
| 5092 __ b(ne, &megamorphic); | 5096 __ b(ne, &megamorphic); |
| 5093 __ jmp(&done); | 5097 __ jmp(&done); |
| 5094 | 5098 |
| 5095 __ bind(&miss); | 5099 __ bind(&miss); |
| 5096 | 5100 |
| 5097 // A monomorphic miss (i.e, here the cache is not uninitialized) goes | 5101 // A monomorphic miss (i.e, here the cache is not uninitialized) goes |
| 5098 // megamorphic. | 5102 // megamorphic. |
| (...skipping 2060 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 7159 } | 7163 } |
| 7160 } | 7164 } |
| 7161 return false; | 7165 return false; |
| 7162 } | 7166 } |
| 7163 | 7167 |
| 7164 | 7168 |
| 7165 void StoreBufferOverflowStub::GenerateFixedRegStubsAheadOfTime( | 7169 void StoreBufferOverflowStub::GenerateFixedRegStubsAheadOfTime( |
| 7166 Isolate* isolate) { | 7170 Isolate* isolate) { |
| 7167 StoreBufferOverflowStub stub1(kDontSaveFPRegs); | 7171 StoreBufferOverflowStub stub1(kDontSaveFPRegs); |
| 7168 stub1.GetCode(isolate)->set_is_pregenerated(true); | 7172 stub1.GetCode(isolate)->set_is_pregenerated(true); |
| 7173 StoreBufferOverflowStub stub2(kSaveFPRegs); | |
| 7174 stub2.GetCode(isolate)->set_is_pregenerated(true); | |
| 7169 } | 7175 } |
| 7170 | 7176 |
| 7171 | 7177 |
| 7172 void RecordWriteStub::GenerateFixedRegStubsAheadOfTime(Isolate* isolate) { | 7178 void RecordWriteStub::GenerateFixedRegStubsAheadOfTime(Isolate* isolate) { |
| 7173 for (const AheadOfTimeWriteBarrierStubList* entry = kAheadOfTime; | 7179 for (const AheadOfTimeWriteBarrierStubList* entry = kAheadOfTime; |
| 7174 !entry->object.is(no_reg); | 7180 !entry->object.is(no_reg); |
| 7175 entry++) { | 7181 entry++) { |
| 7176 RecordWriteStub stub(entry->object, | 7182 RecordWriteStub stub(entry->object, |
| 7177 entry->value, | 7183 entry->value, |
| 7178 entry->address, | 7184 entry->address, |
| (...skipping 338 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 7517 | 7523 |
| 7518 // Restore the stack pointer if needed. | 7524 // Restore the stack pointer if needed. |
| 7519 if (frame_alignment > kPointerSize) { | 7525 if (frame_alignment > kPointerSize) { |
| 7520 __ mov(sp, r5); | 7526 __ mov(sp, r5); |
| 7521 } | 7527 } |
| 7522 | 7528 |
| 7523 __ Pop(lr, r5, r1); | 7529 __ Pop(lr, r5, r1); |
| 7524 __ Ret(); | 7530 __ Ret(); |
| 7525 } | 7531 } |
| 7526 | 7532 |
| 7533 | |
| 7534 template<class T> | |
| 7535 static void CreateArrayDispatch(MacroAssembler* masm) { | |
| 7536 int last_index = GetSequenceIndexFromFastElementsKind( | |
| 7537 TERMINAL_FAST_ELEMENTS_KIND); | |
| 7538 for (int i = 0; i <= last_index; ++i) { | |
| 7539 Label next; | |
| 7540 ElementsKind kind = GetFastElementsKindFromSequenceIndex(i); | |
| 7541 __ cmp(r3, Operand(kind)); | |
| 7542 __ b(ne, &next); | |
| 7543 T stub(kind); | |
| 7544 __ TailCallStub(&stub); | |
| 7545 __ bind(&next); | |
| 7546 } | |
| 7547 | |
| 7548 // If we reached this point there is a problem. | |
| 7549 __ Abort("Unexpected ElementsKind in array constructor"); | |
| 7550 } | |
| 7551 | |
| 7552 | |
| 7553 static void CreateArrayDispatchOneArgument(MacroAssembler* masm) { | |
| 7554 // r2 - type info cell | |
| 7555 // r3 - kind | |
| 7556 // r0 - number of arguments | |
| 7557 // r1 - constructor? | |
| 7558 // sp[0] - last argument | |
| 7559 ASSERT(FAST_SMI_ELEMENTS == 0); | |
| 7560 ASSERT(FAST_HOLEY_SMI_ELEMENTS == 1); | |
| 7561 ASSERT(FAST_ELEMENTS == 2); | |
| 7562 ASSERT(FAST_HOLEY_ELEMENTS == 3); | |
| 7563 ASSERT(FAST_DOUBLE_ELEMENTS == 4); | |
| 7564 ASSERT(FAST_HOLEY_DOUBLE_ELEMENTS == 5); | |
| 7565 | |
| 7566 Handle<Object> undefined_sentinel( | |
| 7567 masm->isolate()->heap()->undefined_value(), | |
| 7568 masm->isolate()); | |
| 7569 | |
| 7570 // is the low bit set? If so, we are holey and that is good. | |
| 7571 __ tst(r3, Operand(1)); | |
| 7572 Label normal_sequence; | |
| 7573 __ b(ne, &normal_sequence); | |
| 7574 | |
| 7575 // look at the first argument | |
| 7576 __ ldr(r5, MemOperand(sp, 0)); | |
| 7577 __ cmp(r5, Operand::Zero()); | |
| 7578 __ b(eq, &normal_sequence); | |
| 7579 | |
| 7580 // We are going to create a holey array, but our kind is non-holey. | |
| 7581 // Fix kind and retry | |
| 7582 __ add(r3, r3, Operand(1)); | |
| 7583 __ cmp(r2, Operand(undefined_sentinel)); | |
| 7584 __ b(eq, &normal_sequence); | |
| 7585 | |
| 7586 // Save the resulting elements kind in type info | |
| 7587 __ SmiTag(r3); | |
| 7588 __ str(r3, FieldMemOperand(r2, kPointerSize)); | |
| 7589 __ SmiUntag(r3); | |
| 7590 | |
| 7591 __ bind(&normal_sequence); | |
| 7592 int last_index = GetSequenceIndexFromFastElementsKind( | |
| 7593 TERMINAL_FAST_ELEMENTS_KIND); | |
| 7594 for (int i = 0; i <= last_index; ++i) { | |
| 7595 Label next; | |
| 7596 ElementsKind kind = GetFastElementsKindFromSequenceIndex(i); | |
| 7597 __ cmp(r3, Operand(kind)); | |
| 7598 __ b(ne, &next); | |
| 7599 ArraySingleArgumentConstructorStub stub(kind); | |
| 7600 __ TailCallStub(&stub); | |
| 7601 __ bind(&next); | |
| 7602 } | |
| 7603 | |
| 7604 // If we reached this point there is a problem. | |
| 7605 __ Abort("Unexpected ElementsKind in array constructor"); | |
| 7606 } | |
| 7607 | |
| 7608 | |
| 7609 template<class T> | |
| 7610 static void ArrayConstructorStubAheadOfTimeHelper(Isolate* isolate) { | |
| 7611 int to_index = GetSequenceIndexFromFastElementsKind( | |
| 7612 TERMINAL_FAST_ELEMENTS_KIND); | |
| 7613 for (int i = 0; i <= to_index; ++i) { | |
| 7614 ElementsKind kind = GetFastElementsKindFromSequenceIndex(i); | |
| 7615 T stub(kind); | |
| 7616 stub.GetCode(isolate)->set_is_pregenerated(true); | |
| 7617 } | |
| 7618 } | |
| 7619 | |
| 7620 | |
| 7621 void ArrayConstructorStubBase::GenerateStubsAheadOfTime(Isolate* isolate) { | |
| 7622 ArrayConstructorStubAheadOfTimeHelper<ArrayNoArgumentConstructorStub>( | |
| 7623 isolate); | |
| 7624 ArrayConstructorStubAheadOfTimeHelper<ArraySingleArgumentConstructorStub>( | |
| 7625 isolate); | |
| 7626 ArrayConstructorStubAheadOfTimeHelper<ArrayNArgumentsConstructorStub>( | |
| 7627 isolate); | |
| 7628 } | |
| 7629 | |
| 7630 | |
| 7631 void ArrayConstructorStub::Generate(MacroAssembler* masm) { | |
| 7632 // ----------- S t a t e ------------- | |
| 7633 // -- r0 : argc (only if argument_count_ == ANY) | |
| 7634 // -- r1 : constructor | |
| 7635 // -- r2 : type info cell | |
| 7636 // -- sp[0] : return address | |
| 7637 // -- sp[4] : last argument | |
| 7638 // ----------------------------------- | |
| 7639 Handle<Object> undefined_sentinel( | |
| 7640 masm->isolate()->heap()->undefined_value(), | |
| 7641 masm->isolate()); | |
| 7642 | |
| 7643 if (FLAG_debug_code) { | |
| 7644 // The array construct code is only set for the global and natives | |
| 7645 // builtin Array functions which always have maps. | |
| 7646 | |
| 7647 // Initial map for the builtin Array function should be a map. | |
| 7648 __ ldr(r3, FieldMemOperand(r1, JSFunction::kPrototypeOrInitialMapOffset)); | |
| 7649 // Will both indicate a NULL and a Smi. | |
| 7650 __ tst(r3, Operand(kSmiTagMask)); | |
| 7651 __ Assert(ne, "Unexpected initial map for Array function"); | |
| 7652 __ CompareObjectType(r3, r3, r4, MAP_TYPE); | |
| 7653 __ Assert(eq, "Unexpected initial map for Array function"); | |
| 7654 | |
| 7655 // We should either have undefined in ebx or a valid jsglobalpropertycell | |
| 7656 Label okay_here; | |
| 7657 Handle<Map> global_property_cell_map( | |
| 7658 masm->isolate()->heap()->global_property_cell_map()); | |
| 7659 __ cmp(r2, Operand(undefined_sentinel)); | |
| 7660 __ b(eq, &okay_here); | |
| 7661 __ ldr(r3, FieldMemOperand(r2, 0)); | |
| 7662 __ cmp(r3, Operand(global_property_cell_map)); | |
| 7663 __ Assert(eq, "Expected property cell in register ebx"); | |
| 7664 __ bind(&okay_here); | |
| 7665 } | |
| 7666 | |
| 7667 if (FLAG_optimize_constructed_arrays) { | |
| 7668 Label no_info, switch_ready; | |
| 7669 // Get the elements kind and case on that. | |
| 7670 __ cmp(r2, Operand(undefined_sentinel)); | |
| 7671 __ b(eq, &no_info); | |
| 7672 __ ldr(r3, FieldMemOperand(r2, kPointerSize)); | |
| 7673 | |
| 7674 // There is no info if the call site went megamorphic either | |
| 7675 // TODO(mvstanton): Really? I thought if it was the array function that | |
| 7676 // the cell wouldn't get stamped as megamorphic. | |
| 7677 __ cmp(r3, | |
| 7678 Operand(TypeFeedbackCells::MegamorphicSentinel(masm->isolate()))); | |
| 7679 __ b(eq, &no_info); | |
| 7680 __ SmiUntag(r3); | |
| 7681 __ jmp(&switch_ready); | |
| 7682 __ bind(&no_info); | |
| 7683 __ mov(r3, Operand(GetInitialFastElementsKind())); | |
| 7684 __ bind(&switch_ready); | |
| 7685 | |
| 7686 if (argument_count_ == ANY) { | |
| 7687 Label not_zero_case, not_one_case; | |
| 7688 __ tst(r0, r0); | |
| 7689 __ b(ne, ¬_zero_case); | |
| 7690 CreateArrayDispatch<ArrayNoArgumentConstructorStub>(masm); | |
| 7691 | |
| 7692 __ bind(¬_zero_case); | |
| 7693 __ cmp(r0, Operand(1)); | |
| 7694 __ b(gt, ¬_one_case); | |
| 7695 CreateArrayDispatchOneArgument(masm); | |
| 7696 | |
| 7697 __ bind(¬_one_case); | |
| 7698 CreateArrayDispatch<ArrayNArgumentsConstructorStub>(masm); | |
| 7699 } else if (argument_count_ == NONE) { | |
| 7700 CreateArrayDispatch<ArrayNoArgumentConstructorStub>(masm); | |
| 7701 } else if (argument_count_ == ONE) { | |
| 7702 CreateArrayDispatchOneArgument(masm); | |
| 7703 } else if (argument_count_ == MORE_THAN_ONE) { | |
| 7704 CreateArrayDispatch<ArrayNArgumentsConstructorStub>(masm); | |
| 7705 } else { | |
| 7706 UNREACHABLE(); | |
| 7707 } | |
| 7708 } else { | |
| 7709 Label generic_constructor; | |
| 7710 // Run the native code for the Array function called as a constructor. | |
| 7711 ArrayNativeCode(masm, &generic_constructor); | |
| 7712 | |
| 7713 // Jump to the generic construct code in case the specialized code cannot | |
| 7714 // handle the construction. | |
| 7715 __ bind(&generic_constructor); | |
| 7716 Handle<Code> generic_construct_stub = | |
| 7717 masm->isolate()->builtins()->JSConstructStubGeneric(); | |
| 7718 __ Jump(generic_construct_stub, RelocInfo::CODE_TARGET); | |
| 7719 } | |
| 7720 } | |
| 7721 | |
| 7722 | |
| 7527 #undef __ | 7723 #undef __ |
| 7528 | 7724 |
| 7529 } } // namespace v8::internal | 7725 } } // namespace v8::internal |
| 7530 | 7726 |
| 7531 #endif // V8_TARGET_ARCH_ARM | 7727 #endif // V8_TARGET_ARCH_ARM |
| OLD | NEW |