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 89 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
100 __ pop(offset); | 100 __ pop(offset); |
101 } | 101 } |
102 } | 102 } |
103 | 103 |
104 | 104 |
105 // Helper function used to check that the dictionary doesn't contain | 105 // Helper function used to check that the dictionary doesn't contain |
106 // the property. This function may return false negatives, so miss_label | 106 // the property. This function may return false negatives, so miss_label |
107 // must always call a backup property check that is complete. | 107 // must always call a backup property check that is complete. |
108 // This function is safe to call if the receiver has fast properties. | 108 // This function is safe to call if the receiver has fast properties. |
109 // Name must be a symbol and receiver must be a heap object. | 109 // Name must be a symbol and receiver must be a heap object. |
110 static MaybeObject* GenerateDictionaryNegativeLookup(MacroAssembler* masm, | 110 static void GenerateDictionaryNegativeLookup(MacroAssembler* masm, |
111 Label* miss_label, | 111 Label* miss_label, |
112 Register receiver, | 112 Register receiver, |
113 String* name, | 113 Handle<String> name, |
114 Register r0, | 114 Register r0, |
115 Register r1) { | 115 Register r1) { |
116 ASSERT(name->IsSymbol()); | 116 ASSERT(name->IsSymbol()); |
117 Counters* counters = masm->isolate()->counters(); | 117 Counters* counters = masm->isolate()->counters(); |
118 __ IncrementCounter(counters->negative_lookups(), 1); | 118 __ IncrementCounter(counters->negative_lookups(), 1); |
119 __ IncrementCounter(counters->negative_lookups_miss(), 1); | 119 __ IncrementCounter(counters->negative_lookups_miss(), 1); |
120 | 120 |
121 __ mov(r0, FieldOperand(receiver, HeapObject::kMapOffset)); | 121 __ mov(r0, FieldOperand(receiver, HeapObject::kMapOffset)); |
122 | 122 |
123 const int kInterceptorOrAccessCheckNeededMask = | 123 const int kInterceptorOrAccessCheckNeededMask = |
124 (1 << Map::kHasNamedInterceptor) | (1 << Map::kIsAccessCheckNeeded); | 124 (1 << Map::kHasNamedInterceptor) | (1 << Map::kIsAccessCheckNeeded); |
125 | 125 |
126 // Bail out if the receiver has a named interceptor or requires access checks. | 126 // Bail out if the receiver has a named interceptor or requires access checks. |
127 __ test_b(FieldOperand(r0, Map::kBitFieldOffset), | 127 __ test_b(FieldOperand(r0, Map::kBitFieldOffset), |
128 kInterceptorOrAccessCheckNeededMask); | 128 kInterceptorOrAccessCheckNeededMask); |
129 __ j(not_zero, miss_label); | 129 __ j(not_zero, miss_label); |
130 | 130 |
131 // Check that receiver is a JSObject. | 131 // Check that receiver is a JSObject. |
132 __ CmpInstanceType(r0, FIRST_SPEC_OBJECT_TYPE); | 132 __ CmpInstanceType(r0, FIRST_SPEC_OBJECT_TYPE); |
133 __ j(below, miss_label); | 133 __ j(below, miss_label); |
134 | 134 |
135 // Load properties array. | 135 // Load properties array. |
136 Register properties = r0; | 136 Register properties = r0; |
137 __ mov(properties, FieldOperand(receiver, JSObject::kPropertiesOffset)); | 137 __ mov(properties, FieldOperand(receiver, JSObject::kPropertiesOffset)); |
138 | 138 |
139 // Check that the properties array is a dictionary. | 139 // Check that the properties array is a dictionary. |
140 __ cmp(FieldOperand(properties, HeapObject::kMapOffset), | 140 __ cmp(FieldOperand(properties, HeapObject::kMapOffset), |
141 Immediate(masm->isolate()->factory()->hash_table_map())); | 141 Immediate(masm->isolate()->factory()->hash_table_map())); |
142 __ j(not_equal, miss_label); | 142 __ j(not_equal, miss_label); |
143 | 143 |
144 Label done; | 144 Label done; |
| 145 StringDictionaryLookupStub::GenerateNegativeLookup(masm, |
| 146 miss_label, |
| 147 &done, |
| 148 properties, |
| 149 name, |
| 150 r1); |
| 151 __ bind(&done); |
| 152 __ DecrementCounter(counters->negative_lookups_miss(), 1); |
| 153 } |
| 154 |
| 155 |
| 156 // TODO(kmillikin): Eliminate this function when the stub cache is fully |
| 157 // handlified. |
| 158 static MaybeObject* TryGenerateDictionaryNegativeLookup(MacroAssembler* masm, |
| 159 Label* miss_label, |
| 160 Register receiver, |
| 161 String* name, |
| 162 Register r0, |
| 163 Register r1) { |
| 164 ASSERT(name->IsSymbol()); |
| 165 Counters* counters = masm->isolate()->counters(); |
| 166 __ IncrementCounter(counters->negative_lookups(), 1); |
| 167 __ IncrementCounter(counters->negative_lookups_miss(), 1); |
| 168 |
| 169 __ mov(r0, FieldOperand(receiver, HeapObject::kMapOffset)); |
| 170 |
| 171 const int kInterceptorOrAccessCheckNeededMask = |
| 172 (1 << Map::kHasNamedInterceptor) | (1 << Map::kIsAccessCheckNeeded); |
| 173 |
| 174 // Bail out if the receiver has a named interceptor or requires access checks. |
| 175 __ test_b(FieldOperand(r0, Map::kBitFieldOffset), |
| 176 kInterceptorOrAccessCheckNeededMask); |
| 177 __ j(not_zero, miss_label); |
| 178 |
| 179 // Check that receiver is a JSObject. |
| 180 __ CmpInstanceType(r0, FIRST_SPEC_OBJECT_TYPE); |
| 181 __ j(below, miss_label); |
| 182 |
| 183 // Load properties array. |
| 184 Register properties = r0; |
| 185 __ mov(properties, FieldOperand(receiver, JSObject::kPropertiesOffset)); |
| 186 |
| 187 // Check that the properties array is a dictionary. |
| 188 __ cmp(FieldOperand(properties, HeapObject::kMapOffset), |
| 189 Immediate(masm->isolate()->factory()->hash_table_map())); |
| 190 __ j(not_equal, miss_label); |
| 191 |
| 192 Label done; |
145 MaybeObject* result = | 193 MaybeObject* result = |
146 StringDictionaryLookupStub::GenerateNegativeLookup(masm, | 194 StringDictionaryLookupStub::TryGenerateNegativeLookup(masm, |
147 miss_label, | 195 miss_label, |
148 &done, | 196 &done, |
149 properties, | 197 properties, |
150 name, | 198 name, |
151 r1); | 199 r1); |
152 if (result->IsFailure()) return result; | 200 if (result->IsFailure()) return result; |
153 | 201 |
154 __ bind(&done); | 202 __ bind(&done); |
155 __ DecrementCounter(counters->negative_lookups_miss(), 1); | 203 __ DecrementCounter(counters->negative_lookups_miss(), 1); |
156 | 204 |
157 return result; | 205 return result; |
158 } | 206 } |
159 | 207 |
160 | 208 |
161 void StubCache::GenerateProbe(MacroAssembler* masm, | 209 void StubCache::GenerateProbe(MacroAssembler* masm, |
162 Code::Flags flags, | 210 Code::Flags flags, |
163 Register receiver, | 211 Register receiver, |
164 Register name, | 212 Register name, |
165 Register scratch, | 213 Register scratch, |
166 Register extra, | 214 Register extra, |
167 Register extra2) { | 215 Register extra2) { |
168 Isolate* isolate = Isolate::Current(); | |
169 Label miss; | 216 Label miss; |
170 USE(extra2); // The register extra2 is not used on the ia32 platform. | |
171 | 217 |
172 // Make sure that code is valid. The shifting code relies on the | 218 // Assert that code is valid. The shifting code relies on the entry size |
173 // entry size being 8. | 219 // being 8. |
174 ASSERT(sizeof(Entry) == 8); | 220 ASSERT(sizeof(Entry) == 8); |
175 | 221 |
176 // Make sure the flags does not name a specific type. | 222 // Assert the flags do not name a specific type. |
177 ASSERT(Code::ExtractTypeFromFlags(flags) == 0); | 223 ASSERT(Code::ExtractTypeFromFlags(flags) == 0); |
178 | 224 |
179 // Make sure that there are no register conflicts. | 225 // Assert that there are no register conflicts. |
180 ASSERT(!scratch.is(receiver)); | 226 ASSERT(!scratch.is(receiver)); |
181 ASSERT(!scratch.is(name)); | 227 ASSERT(!scratch.is(name)); |
182 ASSERT(!extra.is(receiver)); | 228 ASSERT(!extra.is(receiver)); |
183 ASSERT(!extra.is(name)); | 229 ASSERT(!extra.is(name)); |
184 ASSERT(!extra.is(scratch)); | 230 ASSERT(!extra.is(scratch)); |
185 | 231 |
186 // Check scratch and extra registers are valid, and extra2 is unused. | 232 // Assert scratch and extra registers are valid, and extra2 is unused. |
187 ASSERT(!scratch.is(no_reg)); | 233 ASSERT(!scratch.is(no_reg)); |
188 ASSERT(extra2.is(no_reg)); | 234 ASSERT(extra2.is(no_reg)); |
189 | 235 |
190 // Check that the receiver isn't a smi. | 236 // Check that the receiver isn't a smi. |
191 __ JumpIfSmi(receiver, &miss); | 237 __ JumpIfSmi(receiver, &miss); |
192 | 238 |
193 // Get the map of the receiver and compute the hash. | 239 // Get the map of the receiver and compute the hash. |
194 __ mov(scratch, FieldOperand(name, String::kHashFieldOffset)); | 240 __ mov(scratch, FieldOperand(name, String::kHashFieldOffset)); |
195 __ add(scratch, FieldOperand(receiver, HeapObject::kMapOffset)); | 241 __ add(scratch, FieldOperand(receiver, HeapObject::kMapOffset)); |
196 __ xor_(scratch, flags); | 242 __ xor_(scratch, flags); |
197 __ and_(scratch, (kPrimaryTableSize - 1) << kHeapObjectTagSize); | 243 __ and_(scratch, (kPrimaryTableSize - 1) << kHeapObjectTagSize); |
198 | 244 |
199 // Probe the primary table. | 245 // Probe the primary table. |
200 ProbeTable(isolate, masm, flags, kPrimary, name, scratch, extra); | 246 ProbeTable(isolate(), masm, flags, kPrimary, name, scratch, extra); |
201 | 247 |
202 // Primary miss: Compute hash for secondary probe. | 248 // Primary miss: Compute hash for secondary probe. |
203 __ mov(scratch, FieldOperand(name, String::kHashFieldOffset)); | 249 __ mov(scratch, FieldOperand(name, String::kHashFieldOffset)); |
204 __ add(scratch, FieldOperand(receiver, HeapObject::kMapOffset)); | 250 __ add(scratch, FieldOperand(receiver, HeapObject::kMapOffset)); |
205 __ xor_(scratch, flags); | 251 __ xor_(scratch, flags); |
206 __ and_(scratch, (kPrimaryTableSize - 1) << kHeapObjectTagSize); | 252 __ and_(scratch, (kPrimaryTableSize - 1) << kHeapObjectTagSize); |
207 __ sub(scratch, name); | 253 __ sub(scratch, name); |
208 __ add(scratch, Immediate(flags)); | 254 __ add(scratch, Immediate(flags)); |
209 __ and_(scratch, (kSecondaryTableSize - 1) << kHeapObjectTagSize); | 255 __ and_(scratch, (kSecondaryTableSize - 1) << kHeapObjectTagSize); |
210 | 256 |
211 // Probe the secondary table. | 257 // Probe the secondary table. |
212 ProbeTable(isolate, masm, flags, kSecondary, name, scratch, extra); | 258 ProbeTable(isolate(), masm, flags, kSecondary, name, scratch, extra); |
213 | 259 |
214 // Cache miss: Fall-through and let caller handle the miss by | 260 // Cache miss: Fall-through and let caller handle the miss by |
215 // entering the runtime system. | 261 // entering the runtime system. |
216 __ bind(&miss); | 262 __ bind(&miss); |
217 } | 263 } |
218 | 264 |
219 | 265 |
220 void StubCompiler::GenerateLoadGlobalFunctionPrototype(MacroAssembler* masm, | 266 void StubCompiler::GenerateLoadGlobalFunctionPrototype(MacroAssembler* masm, |
221 int index, | 267 int index, |
222 Register prototype) { | 268 Register prototype) { |
(...skipping 97 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
320 __ TryGetFunctionPrototype(receiver, scratch1, scratch2, miss_label); | 366 __ TryGetFunctionPrototype(receiver, scratch1, scratch2, miss_label); |
321 __ mov(eax, scratch1); | 367 __ mov(eax, scratch1); |
322 __ ret(0); | 368 __ ret(0); |
323 } | 369 } |
324 | 370 |
325 | 371 |
326 // Load a fast property out of a holder object (src). In-object properties | 372 // Load a fast property out of a holder object (src). In-object properties |
327 // are loaded directly otherwise the property is loaded from the properties | 373 // are loaded directly otherwise the property is loaded from the properties |
328 // fixed array. | 374 // fixed array. |
329 void StubCompiler::GenerateFastPropertyLoad(MacroAssembler* masm, | 375 void StubCompiler::GenerateFastPropertyLoad(MacroAssembler* masm, |
330 Register dst, Register src, | 376 Register dst, |
331 JSObject* holder, int index) { | 377 Register src, |
| 378 Handle<JSObject> holder, |
| 379 int index) { |
332 // Adjust for the number of properties stored in the holder. | 380 // Adjust for the number of properties stored in the holder. |
333 index -= holder->map()->inobject_properties(); | 381 index -= holder->map()->inobject_properties(); |
334 if (index < 0) { | 382 if (index < 0) { |
335 // Get the property straight out of the holder. | 383 // Get the property straight out of the holder. |
336 int offset = holder->map()->instance_size() + (index * kPointerSize); | 384 int offset = holder->map()->instance_size() + (index * kPointerSize); |
337 __ mov(dst, FieldOperand(src, offset)); | 385 __ mov(dst, FieldOperand(src, offset)); |
338 } else { | 386 } else { |
339 // Calculate the offset into the properties array. | 387 // Calculate the offset into the properties array. |
340 int offset = index * kPointerSize + FixedArray::kHeaderSize; | 388 int offset = index * kPointerSize + FixedArray::kHeaderSize; |
341 __ mov(dst, FieldOperand(src, JSObject::kPropertiesOffset)); | 389 __ mov(dst, FieldOperand(src, JSObject::kPropertiesOffset)); |
(...skipping 137 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
479 return masm->TryCallApiFunctionAndReturn(&fun, | 527 return masm->TryCallApiFunctionAndReturn(&fun, |
480 argc + kFastApiCallArguments + 1); | 528 argc + kFastApiCallArguments + 1); |
481 } | 529 } |
482 | 530 |
483 | 531 |
484 class CallInterceptorCompiler BASE_EMBEDDED { | 532 class CallInterceptorCompiler BASE_EMBEDDED { |
485 public: | 533 public: |
486 CallInterceptorCompiler(StubCompiler* stub_compiler, | 534 CallInterceptorCompiler(StubCompiler* stub_compiler, |
487 const ParameterCount& arguments, | 535 const ParameterCount& arguments, |
488 Register name, | 536 Register name, |
489 Code::ExtraICState extra_ic_state) | 537 Code::ExtraICState extra_state) |
490 : stub_compiler_(stub_compiler), | 538 : stub_compiler_(stub_compiler), |
491 arguments_(arguments), | 539 arguments_(arguments), |
492 name_(name), | 540 name_(name), |
493 extra_ic_state_(extra_ic_state) {} | 541 extra_state_(extra_state) {} |
494 | 542 |
495 MaybeObject* Compile(MacroAssembler* masm, | 543 MaybeObject* Compile(MacroAssembler* masm, |
496 JSObject* object, | 544 JSObject* object, |
497 JSObject* holder, | 545 JSObject* holder, |
498 String* name, | 546 String* name, |
499 LookupResult* lookup, | 547 LookupResult* lookup, |
500 Register receiver, | 548 Register receiver, |
501 Register scratch1, | 549 Register scratch1, |
502 Register scratch2, | 550 Register scratch2, |
503 Register scratch3, | 551 Register scratch3, |
(...skipping 103 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
607 // by the previous CheckPrototypes. | 655 // by the previous CheckPrototypes. |
608 ASSERT(depth2 == kInvalidProtoDepth); | 656 ASSERT(depth2 == kInvalidProtoDepth); |
609 } | 657 } |
610 | 658 |
611 // Invoke function. | 659 // Invoke function. |
612 if (can_do_fast_api_call) { | 660 if (can_do_fast_api_call) { |
613 MaybeObject* result = | 661 MaybeObject* result = |
614 GenerateFastApiCall(masm, optimization, arguments_.immediate()); | 662 GenerateFastApiCall(masm, optimization, arguments_.immediate()); |
615 if (result->IsFailure()) return result; | 663 if (result->IsFailure()) return result; |
616 } else { | 664 } else { |
617 CallKind call_kind = CallICBase::Contextual::decode(extra_ic_state_) | 665 CallKind call_kind = CallICBase::Contextual::decode(extra_state_) |
618 ? CALL_AS_FUNCTION | 666 ? CALL_AS_FUNCTION |
619 : CALL_AS_METHOD; | 667 : CALL_AS_METHOD; |
620 __ InvokeFunction(optimization.constant_function(), arguments_, | 668 __ InvokeFunction(optimization.constant_function(), arguments_, |
621 JUMP_FUNCTION, NullCallWrapper(), call_kind); | 669 JUMP_FUNCTION, NullCallWrapper(), call_kind); |
622 } | 670 } |
623 | 671 |
624 // Deferred code for fast API call case---clean preallocated space. | 672 // Deferred code for fast API call case---clean preallocated space. |
625 if (can_do_fast_api_call) { | 673 if (can_do_fast_api_call) { |
626 __ bind(&miss_cleanup); | 674 __ bind(&miss_cleanup); |
627 FreeSpaceForFastApiCall(masm, scratch1); | 675 FreeSpaceForFastApiCall(masm, scratch1); |
(...skipping 65 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
693 // Leave the internal frame. | 741 // Leave the internal frame. |
694 } | 742 } |
695 | 743 |
696 __ cmp(eax, masm->isolate()->factory()->no_interceptor_result_sentinel()); | 744 __ cmp(eax, masm->isolate()->factory()->no_interceptor_result_sentinel()); |
697 __ j(not_equal, interceptor_succeeded); | 745 __ j(not_equal, interceptor_succeeded); |
698 } | 746 } |
699 | 747 |
700 StubCompiler* stub_compiler_; | 748 StubCompiler* stub_compiler_; |
701 const ParameterCount& arguments_; | 749 const ParameterCount& arguments_; |
702 Register name_; | 750 Register name_; |
703 Code::ExtraICState extra_ic_state_; | 751 Code::ExtraICState extra_state_; |
704 }; | 752 }; |
705 | 753 |
706 | 754 |
707 void StubCompiler::GenerateLoadMiss(MacroAssembler* masm, Code::Kind kind) { | 755 void StubCompiler::GenerateLoadMiss(MacroAssembler* masm, Code::Kind kind) { |
708 ASSERT(kind == Code::LOAD_IC || kind == Code::KEYED_LOAD_IC); | 756 ASSERT(kind == Code::LOAD_IC || kind == Code::KEYED_LOAD_IC); |
709 Code* code = NULL; | 757 Handle<Code> code = (kind == Code::LOAD_IC) |
710 if (kind == Code::LOAD_IC) { | 758 ? masm->isolate()->builtins()->LoadIC_Miss() |
711 code = masm->isolate()->builtins()->builtin(Builtins::kLoadIC_Miss); | 759 : masm->isolate()->builtins()->KeyedLoadIC_Miss(); |
712 } else { | 760 __ jmp(code, RelocInfo::CODE_TARGET); |
713 code = masm->isolate()->builtins()->builtin(Builtins::kKeyedLoadIC_Miss); | |
714 } | |
715 | |
716 Handle<Code> ic(code); | |
717 __ jmp(ic, RelocInfo::CODE_TARGET); | |
718 } | 761 } |
719 | 762 |
720 | 763 |
721 void StubCompiler::GenerateKeyedLoadMissForceGeneric(MacroAssembler* masm) { | 764 void StubCompiler::GenerateKeyedLoadMissForceGeneric(MacroAssembler* masm) { |
722 Code* code = masm->isolate()->builtins()->builtin( | 765 Code* code = masm->isolate()->builtins()->builtin( |
723 Builtins::kKeyedLoadIC_MissForceGeneric); | 766 Builtins::kKeyedLoadIC_MissForceGeneric); |
724 Handle<Code> ic(code); | 767 Handle<Code> ic(code); |
725 __ jmp(ic, RelocInfo::CODE_TARGET); | 768 __ jmp(ic, RelocInfo::CODE_TARGET); |
726 } | 769 } |
727 | 770 |
728 | 771 |
729 // Both name_reg and receiver_reg are preserved on jumps to miss_label, | 772 // Both name_reg and receiver_reg are preserved on jumps to miss_label, |
730 // but may be destroyed if store is successful. | 773 // but may be destroyed if store is successful. |
731 void StubCompiler::GenerateStoreField(MacroAssembler* masm, | 774 void StubCompiler::GenerateStoreField(MacroAssembler* masm, |
732 JSObject* object, | 775 Handle<JSObject> object, |
733 int index, | 776 int index, |
734 Map* transition, | 777 Handle<Map> transition, |
735 Register receiver_reg, | 778 Register receiver_reg, |
736 Register name_reg, | 779 Register name_reg, |
737 Register scratch, | 780 Register scratch, |
738 Label* miss_label) { | 781 Label* miss_label) { |
739 // Check that the object isn't a smi. | 782 // Check that the object isn't a smi. |
740 __ JumpIfSmi(receiver_reg, miss_label); | 783 __ JumpIfSmi(receiver_reg, miss_label); |
741 | 784 |
742 // Check that the map of the object hasn't changed. | 785 // Check that the map of the object hasn't changed. |
743 __ cmp(FieldOperand(receiver_reg, HeapObject::kMapOffset), | 786 __ cmp(FieldOperand(receiver_reg, HeapObject::kMapOffset), |
744 Immediate(Handle<Map>(object->map()))); | 787 Immediate(Handle<Map>(object->map()))); |
745 __ j(not_equal, miss_label); | 788 __ j(not_equal, miss_label); |
746 | 789 |
747 // Perform global security token check if needed. | 790 // Perform global security token check if needed. |
748 if (object->IsJSGlobalProxy()) { | 791 if (object->IsJSGlobalProxy()) { |
749 __ CheckAccessGlobalProxy(receiver_reg, scratch, miss_label); | 792 __ CheckAccessGlobalProxy(receiver_reg, scratch, miss_label); |
750 } | 793 } |
751 | 794 |
752 // Stub never generated for non-global objects that require access | 795 // Stub never generated for non-global objects that require access |
753 // checks. | 796 // checks. |
754 ASSERT(object->IsJSGlobalProxy() || !object->IsAccessCheckNeeded()); | 797 ASSERT(object->IsJSGlobalProxy() || !object->IsAccessCheckNeeded()); |
755 | 798 |
756 // Perform map transition for the receiver if necessary. | 799 // Perform map transition for the receiver if necessary. |
757 if ((transition != NULL) && (object->map()->unused_property_fields() == 0)) { | 800 if (!transition.is_null() && (object->map()->unused_property_fields() == 0)) { |
758 // The properties must be extended before we can store the value. | 801 // The properties must be extended before we can store the value. |
759 // We jump to a runtime call that extends the properties array. | 802 // We jump to a runtime call that extends the properties array. |
760 __ pop(scratch); // Return address. | 803 __ pop(scratch); // Return address. |
761 __ push(receiver_reg); | 804 __ push(receiver_reg); |
762 __ push(Immediate(Handle<Map>(transition))); | 805 __ push(Immediate(transition)); |
763 __ push(eax); | 806 __ push(eax); |
764 __ push(scratch); | 807 __ push(scratch); |
765 __ TailCallExternalReference( | 808 __ TailCallExternalReference( |
766 ExternalReference(IC_Utility(IC::kSharedStoreIC_ExtendStorage), | 809 ExternalReference(IC_Utility(IC::kSharedStoreIC_ExtendStorage), |
767 masm->isolate()), | 810 masm->isolate()), |
768 3, | 811 3, |
769 1); | 812 1); |
770 return; | 813 return; |
771 } | 814 } |
772 | 815 |
773 if (transition != NULL) { | 816 if (!transition.is_null()) { |
774 // Update the map of the object; no write barrier updating is | 817 // Update the map of the object; no write barrier updating is |
775 // needed because the map is never in new space. | 818 // needed because the map is never in new space. |
776 __ mov(FieldOperand(receiver_reg, HeapObject::kMapOffset), | 819 __ mov(FieldOperand(receiver_reg, HeapObject::kMapOffset), |
777 Immediate(Handle<Map>(transition))); | 820 Immediate(transition)); |
778 } | 821 } |
779 | 822 |
780 // Adjust for the number of properties stored in the object. Even in the | 823 // Adjust for the number of properties stored in the object. Even in the |
781 // face of a transition we can use the old map here because the size of the | 824 // face of a transition we can use the old map here because the size of the |
782 // object and the number of in-object properties is not going to change. | 825 // object and the number of in-object properties is not going to change. |
783 index -= object->map()->inobject_properties(); | 826 index -= object->map()->inobject_properties(); |
784 | 827 |
785 if (index < 0) { | 828 if (index < 0) { |
786 // Set the property straight into the object. | 829 // Set the property straight into the object. |
787 int offset = object->map()->instance_size() + (index * kPointerSize); | 830 int offset = object->map()->instance_size() + (index * kPointerSize); |
(...skipping 25 matching lines...) Expand all Loading... |
813 } | 856 } |
814 | 857 |
815 // Return the value (register eax). | 858 // Return the value (register eax). |
816 __ ret(0); | 859 __ ret(0); |
817 } | 860 } |
818 | 861 |
819 | 862 |
820 // Generate code to check that a global property cell is empty. Create | 863 // Generate code to check that a global property cell is empty. Create |
821 // the property cell at compilation time if no cell exists for the | 864 // the property cell at compilation time if no cell exists for the |
822 // property. | 865 // property. |
823 MUST_USE_RESULT static MaybeObject* GenerateCheckPropertyCell( | 866 static void GenerateCheckPropertyCell(MacroAssembler* masm, |
| 867 Handle<GlobalObject> global, |
| 868 Handle<String> name, |
| 869 Register scratch, |
| 870 Label* miss) { |
| 871 Handle<JSGlobalPropertyCell> cell = |
| 872 GlobalObject::EnsurePropertyCell(global, name); |
| 873 ASSERT(cell->value()->IsTheHole()); |
| 874 Handle<Oddball> the_hole = masm->isolate()->factory()->the_hole_value(); |
| 875 if (Serializer::enabled()) { |
| 876 __ mov(scratch, Immediate(cell)); |
| 877 __ cmp(FieldOperand(scratch, JSGlobalPropertyCell::kValueOffset), |
| 878 Immediate(the_hole)); |
| 879 } else { |
| 880 __ cmp(Operand::Cell(cell), Immediate(the_hole)); |
| 881 } |
| 882 __ j(not_equal, miss); |
| 883 } |
| 884 |
| 885 |
| 886 // TODO(kmillikin): Eliminate this function when the stub cache is fully |
| 887 // handlified. |
| 888 MUST_USE_RESULT static MaybeObject* TryGenerateCheckPropertyCell( |
824 MacroAssembler* masm, | 889 MacroAssembler* masm, |
825 GlobalObject* global, | 890 GlobalObject* global, |
826 String* name, | 891 String* name, |
827 Register scratch, | 892 Register scratch, |
828 Label* miss) { | 893 Label* miss) { |
829 Object* probe; | 894 Object* probe; |
830 { MaybeObject* maybe_probe = global->EnsurePropertyCell(name); | 895 { MaybeObject* maybe_probe = global->EnsurePropertyCell(name); |
831 if (!maybe_probe->ToObject(&probe)) return maybe_probe; | 896 if (!maybe_probe->ToObject(&probe)) return maybe_probe; |
832 } | 897 } |
833 JSGlobalPropertyCell* cell = JSGlobalPropertyCell::cast(probe); | 898 JSGlobalPropertyCell* cell = JSGlobalPropertyCell::cast(probe); |
834 ASSERT(cell->value()->IsTheHole()); | 899 ASSERT(cell->value()->IsTheHole()); |
835 if (Serializer::enabled()) { | 900 if (Serializer::enabled()) { |
836 __ mov(scratch, Immediate(Handle<Object>(cell))); | 901 __ mov(scratch, Immediate(Handle<Object>(cell))); |
837 __ cmp(FieldOperand(scratch, JSGlobalPropertyCell::kValueOffset), | 902 __ cmp(FieldOperand(scratch, JSGlobalPropertyCell::kValueOffset), |
838 Immediate(masm->isolate()->factory()->the_hole_value())); | 903 Immediate(masm->isolate()->factory()->the_hole_value())); |
839 } else { | 904 } else { |
840 __ cmp(Operand::Cell(Handle<JSGlobalPropertyCell>(cell)), | 905 __ cmp(Operand::Cell(Handle<JSGlobalPropertyCell>(cell)), |
841 Immediate(masm->isolate()->factory()->the_hole_value())); | 906 Immediate(masm->isolate()->factory()->the_hole_value())); |
842 } | 907 } |
843 __ j(not_equal, miss); | 908 __ j(not_equal, miss); |
844 return cell; | 909 return cell; |
845 } | 910 } |
846 | 911 |
847 | 912 |
848 // Calls GenerateCheckPropertyCell for each global object in the prototype chain | 913 // Calls GenerateCheckPropertyCell for each global object in the prototype chain |
849 // from object to (but not including) holder. | 914 // from object to (but not including) holder. |
850 MUST_USE_RESULT static MaybeObject* GenerateCheckPropertyCells( | 915 static void GenerateCheckPropertyCells(MacroAssembler* masm, |
| 916 Handle<JSObject> object, |
| 917 Handle<JSObject> holder, |
| 918 Handle<String> name, |
| 919 Register scratch, |
| 920 Label* miss) { |
| 921 Handle<JSObject> current = object; |
| 922 while (!current.is_identical_to(holder)) { |
| 923 if (current->IsGlobalObject()) { |
| 924 GenerateCheckPropertyCell(masm, |
| 925 Handle<GlobalObject>::cast(current), |
| 926 name, |
| 927 scratch, |
| 928 miss); |
| 929 } |
| 930 current = Handle<JSObject>(JSObject::cast(current->GetPrototype())); |
| 931 } |
| 932 } |
| 933 |
| 934 |
| 935 // TODO(kmillikin): Eliminate this function when the stub cache is fully |
| 936 // handlified. |
| 937 MUST_USE_RESULT static MaybeObject* TryGenerateCheckPropertyCells( |
851 MacroAssembler* masm, | 938 MacroAssembler* masm, |
852 JSObject* object, | 939 JSObject* object, |
853 JSObject* holder, | 940 JSObject* holder, |
854 String* name, | 941 String* name, |
855 Register scratch, | 942 Register scratch, |
856 Label* miss) { | 943 Label* miss) { |
857 JSObject* current = object; | 944 JSObject* current = object; |
858 while (current != holder) { | 945 while (current != holder) { |
859 if (current->IsGlobalObject()) { | 946 if (current->IsGlobalObject()) { |
860 // Returns a cell or a failure. | 947 // Returns a cell or a failure. |
861 MaybeObject* result = GenerateCheckPropertyCell( | 948 MaybeObject* result = TryGenerateCheckPropertyCell( |
862 masm, | 949 masm, |
863 GlobalObject::cast(current), | 950 GlobalObject::cast(current), |
864 name, | 951 name, |
865 scratch, | 952 scratch, |
866 miss); | 953 miss); |
867 if (result->IsFailure()) return result; | 954 if (result->IsFailure()) return result; |
868 } | 955 } |
869 ASSERT(current->IsJSObject()); | 956 ASSERT(current->IsJSObject()); |
870 current = JSObject::cast(current->GetPrototype()); | 957 current = JSObject::cast(current->GetPrototype()); |
871 } | 958 } |
872 return NULL; | 959 return NULL; |
873 } | 960 } |
874 | 961 |
875 | 962 |
876 #undef __ | 963 #undef __ |
877 #define __ ACCESS_MASM(masm()) | 964 #define __ ACCESS_MASM(masm()) |
878 | 965 |
879 | 966 |
| 967 Register StubCompiler::CheckPrototypes(Handle<JSObject> object, |
| 968 Register object_reg, |
| 969 Handle<JSObject> holder, |
| 970 Register holder_reg, |
| 971 Register scratch1, |
| 972 Register scratch2, |
| 973 Handle<String> name, |
| 974 int save_at_depth, |
| 975 Label* miss) { |
| 976 // Make sure there's no overlap between holder and object registers. |
| 977 ASSERT(!scratch1.is(object_reg) && !scratch1.is(holder_reg)); |
| 978 ASSERT(!scratch2.is(object_reg) && !scratch2.is(holder_reg) |
| 979 && !scratch2.is(scratch1)); |
| 980 |
| 981 // Keep track of the current object in register reg. |
| 982 Register reg = object_reg; |
| 983 Handle<JSObject> current = object; |
| 984 int depth = 0; |
| 985 |
| 986 if (save_at_depth == depth) { |
| 987 __ mov(Operand(esp, kPointerSize), reg); |
| 988 } |
| 989 |
| 990 // Traverse the prototype chain and check the maps in the prototype chain for |
| 991 // fast and global objects or do negative lookup for normal objects. |
| 992 while (!current.is_identical_to(holder)) { |
| 993 ++depth; |
| 994 |
| 995 // Only global objects and objects that do not require access |
| 996 // checks are allowed in stubs. |
| 997 ASSERT(current->IsJSGlobalProxy() || !current->IsAccessCheckNeeded()); |
| 998 |
| 999 Handle<JSObject> prototype(JSObject::cast(current->GetPrototype())); |
| 1000 if (!current->HasFastProperties() && |
| 1001 !current->IsJSGlobalObject() && |
| 1002 !current->IsJSGlobalProxy()) { |
| 1003 if (!name->IsSymbol()) { |
| 1004 name = factory()->LookupSymbol(name); |
| 1005 } |
| 1006 ASSERT(current->property_dictionary()->FindEntry(*name) == |
| 1007 StringDictionary::kNotFound); |
| 1008 |
| 1009 GenerateDictionaryNegativeLookup(masm(), miss, reg, name, |
| 1010 scratch1, scratch2); |
| 1011 |
| 1012 __ mov(scratch1, FieldOperand(reg, HeapObject::kMapOffset)); |
| 1013 reg = holder_reg; // From now on the object will be in holder_reg. |
| 1014 __ mov(reg, FieldOperand(scratch1, Map::kPrototypeOffset)); |
| 1015 } else { |
| 1016 bool in_new_space = heap()->InNewSpace(*prototype); |
| 1017 Handle<Map> current_map(current->map()); |
| 1018 if (in_new_space) { |
| 1019 // Save the map in scratch1 for later. |
| 1020 __ mov(scratch1, FieldOperand(reg, HeapObject::kMapOffset)); |
| 1021 __ cmp(scratch1, Immediate(current_map)); |
| 1022 } else { |
| 1023 __ cmp(FieldOperand(reg, HeapObject::kMapOffset), |
| 1024 Immediate(current_map)); |
| 1025 } |
| 1026 // Branch on the result of the map check. |
| 1027 __ j(not_equal, miss); |
| 1028 // Check access rights to the global object. This has to happen after |
| 1029 // the map check so that we know that the object is actually a global |
| 1030 // object. |
| 1031 if (current->IsJSGlobalProxy()) { |
| 1032 __ CheckAccessGlobalProxy(reg, scratch2, miss); |
| 1033 } |
| 1034 reg = holder_reg; // From now on the object will be in holder_reg. |
| 1035 |
| 1036 if (in_new_space) { |
| 1037 // The prototype is in new space; we cannot store a reference to it |
| 1038 // in the code. Load it from the map. |
| 1039 __ mov(reg, FieldOperand(scratch1, Map::kPrototypeOffset)); |
| 1040 } else { |
| 1041 // The prototype is in old space; load it directly. |
| 1042 __ mov(reg, prototype); |
| 1043 } |
| 1044 } |
| 1045 |
| 1046 if (save_at_depth == depth) { |
| 1047 __ mov(Operand(esp, kPointerSize), reg); |
| 1048 } |
| 1049 |
| 1050 // Go to the next object in the prototype chain. |
| 1051 current = prototype; |
| 1052 } |
| 1053 ASSERT(current.is_identical_to(holder)); |
| 1054 |
| 1055 // Log the check depth. |
| 1056 LOG(isolate(), IntEvent("check-maps-depth", depth + 1)); |
| 1057 |
| 1058 // Check the holder map. |
| 1059 __ cmp(FieldOperand(reg, HeapObject::kMapOffset), |
| 1060 Immediate(Handle<Map>(holder->map()))); |
| 1061 __ j(not_equal, miss); |
| 1062 |
| 1063 // Perform security check for access to the global object. |
| 1064 ASSERT(holder->IsJSGlobalProxy() || !holder->IsAccessCheckNeeded()); |
| 1065 if (holder->IsJSGlobalProxy()) { |
| 1066 __ CheckAccessGlobalProxy(reg, scratch1, miss); |
| 1067 } |
| 1068 |
| 1069 // If we've skipped any global objects, it's not enough to verify that |
| 1070 // their maps haven't changed. We also need to check that the property |
| 1071 // cell for the property is still empty. |
| 1072 GenerateCheckPropertyCells(masm(), object, holder, name, scratch1, miss); |
| 1073 |
| 1074 // Return the register containing the holder. |
| 1075 return reg; |
| 1076 } |
| 1077 |
| 1078 |
| 1079 // TODO(kmillikin): Eliminate this function when the stub cache is fully |
| 1080 // handlified. |
880 Register StubCompiler::CheckPrototypes(JSObject* object, | 1081 Register StubCompiler::CheckPrototypes(JSObject* object, |
881 Register object_reg, | 1082 Register object_reg, |
882 JSObject* holder, | 1083 JSObject* holder, |
883 Register holder_reg, | 1084 Register holder_reg, |
884 Register scratch1, | 1085 Register scratch1, |
885 Register scratch2, | 1086 Register scratch2, |
886 String* name, | 1087 String* name, |
887 int save_at_depth, | 1088 int save_at_depth, |
888 Label* miss) { | 1089 Label* miss) { |
889 // Make sure there's no overlap between holder and object registers. | 1090 // Make sure there's no overlap between holder and object registers. |
(...skipping 29 matching lines...) Expand all Loading... |
919 Object* lookup_result = NULL; // Initialization to please compiler. | 1120 Object* lookup_result = NULL; // Initialization to please compiler. |
920 if (!maybe_lookup_result->ToObject(&lookup_result)) { | 1121 if (!maybe_lookup_result->ToObject(&lookup_result)) { |
921 set_failure(Failure::cast(maybe_lookup_result)); | 1122 set_failure(Failure::cast(maybe_lookup_result)); |
922 return reg; | 1123 return reg; |
923 } | 1124 } |
924 name = String::cast(lookup_result); | 1125 name = String::cast(lookup_result); |
925 } | 1126 } |
926 ASSERT(current->property_dictionary()->FindEntry(name) == | 1127 ASSERT(current->property_dictionary()->FindEntry(name) == |
927 StringDictionary::kNotFound); | 1128 StringDictionary::kNotFound); |
928 | 1129 |
929 MaybeObject* negative_lookup = GenerateDictionaryNegativeLookup(masm(), | 1130 MaybeObject* negative_lookup = |
930 miss, | 1131 TryGenerateDictionaryNegativeLookup(masm(), miss, reg, name, |
931 reg, | 1132 scratch1, scratch2); |
932 name, | |
933 scratch1, | |
934 scratch2); | |
935 if (negative_lookup->IsFailure()) { | 1133 if (negative_lookup->IsFailure()) { |
936 set_failure(Failure::cast(negative_lookup)); | 1134 set_failure(Failure::cast(negative_lookup)); |
937 return reg; | 1135 return reg; |
938 } | 1136 } |
939 | 1137 |
940 __ mov(scratch1, FieldOperand(reg, HeapObject::kMapOffset)); | 1138 __ mov(scratch1, FieldOperand(reg, HeapObject::kMapOffset)); |
941 reg = holder_reg; // from now the object is in holder_reg | 1139 reg = holder_reg; // from now the object is in holder_reg |
942 __ mov(reg, FieldOperand(scratch1, Map::kPrototypeOffset)); | 1140 __ mov(reg, FieldOperand(scratch1, Map::kPrototypeOffset)); |
943 } else if (heap()->InNewSpace(prototype)) { | 1141 } else if (heap()->InNewSpace(prototype)) { |
944 // Get the map of the current object. | 1142 // Get the map of the current object. |
(...skipping 46 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
991 | 1189 |
992 // Check the holder map. | 1190 // Check the holder map. |
993 __ cmp(FieldOperand(reg, HeapObject::kMapOffset), | 1191 __ cmp(FieldOperand(reg, HeapObject::kMapOffset), |
994 Immediate(Handle<Map>(holder->map()))); | 1192 Immediate(Handle<Map>(holder->map()))); |
995 __ j(not_equal, miss); | 1193 __ j(not_equal, miss); |
996 | 1194 |
997 // Perform security check for access to the global object. | 1195 // Perform security check for access to the global object. |
998 ASSERT(holder->IsJSGlobalProxy() || !holder->IsAccessCheckNeeded()); | 1196 ASSERT(holder->IsJSGlobalProxy() || !holder->IsAccessCheckNeeded()); |
999 if (holder->IsJSGlobalProxy()) { | 1197 if (holder->IsJSGlobalProxy()) { |
1000 __ CheckAccessGlobalProxy(reg, scratch1, miss); | 1198 __ CheckAccessGlobalProxy(reg, scratch1, miss); |
1001 }; | 1199 } |
1002 | 1200 |
1003 // If we've skipped any global objects, it's not enough to verify | 1201 // If we've skipped any global objects, it's not enough to verify |
1004 // that their maps haven't changed. We also need to check that the | 1202 // that their maps haven't changed. We also need to check that the |
1005 // property cell for the property is still empty. | 1203 // property cell for the property is still empty. |
1006 MaybeObject* result = GenerateCheckPropertyCells(masm(), | 1204 MaybeObject* result = TryGenerateCheckPropertyCells(masm(), |
1007 object, | 1205 object, |
1008 holder, | 1206 holder, |
1009 name, | 1207 name, |
1010 scratch1, | 1208 scratch1, |
1011 miss); | 1209 miss); |
1012 if (result->IsFailure()) set_failure(Failure::cast(result)); | 1210 if (result->IsFailure()) set_failure(Failure::cast(result)); |
1013 | 1211 |
1014 // Return the register containing the holder. | 1212 // Return the register containing the holder. |
1015 return reg; | 1213 return reg; |
1016 } | 1214 } |
1017 | 1215 |
1018 | 1216 |
1019 void StubCompiler::GenerateLoadField(JSObject* object, | 1217 void StubCompiler::GenerateLoadField(Handle<JSObject> object, |
1020 JSObject* holder, | 1218 Handle<JSObject> holder, |
1021 Register receiver, | 1219 Register receiver, |
1022 Register scratch1, | 1220 Register scratch1, |
1023 Register scratch2, | 1221 Register scratch2, |
1024 Register scratch3, | 1222 Register scratch3, |
1025 int index, | 1223 int index, |
1026 String* name, | 1224 Handle<String> name, |
1027 Label* miss) { | 1225 Label* miss) { |
1028 // Check that the receiver isn't a smi. | 1226 // Check that the receiver isn't a smi. |
1029 __ JumpIfSmi(receiver, miss); | 1227 __ JumpIfSmi(receiver, miss); |
1030 | 1228 |
1031 // Check the prototype chain. | 1229 // Check the prototype chain. |
1032 Register reg = | 1230 Register reg = CheckPrototypes( |
1033 CheckPrototypes(object, receiver, holder, | 1231 object, receiver, holder, scratch1, scratch2, scratch3, name, miss); |
1034 scratch1, scratch2, scratch3, name, miss); | |
1035 | 1232 |
1036 // Get the value from the properties. | 1233 // Get the value from the properties. |
1037 GenerateFastPropertyLoad(masm(), eax, reg, holder, index); | 1234 GenerateFastPropertyLoad(masm(), eax, reg, holder, index); |
1038 __ ret(0); | 1235 __ ret(0); |
1039 } | 1236 } |
1040 | 1237 |
1041 | 1238 |
1042 MaybeObject* StubCompiler::GenerateLoadCallback(JSObject* object, | 1239 MaybeObject* StubCompiler::GenerateLoadCallback(JSObject* object, |
1043 JSObject* holder, | 1240 JSObject* holder, |
1044 Register receiver, | 1241 Register receiver, |
(...skipping 54 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1099 __ mov(ApiParameterOperand(1), ebx); // arguments pointer. | 1296 __ mov(ApiParameterOperand(1), ebx); // arguments pointer. |
1100 | 1297 |
1101 // Emitting a stub call may try to allocate (if the code is not | 1298 // Emitting a stub call may try to allocate (if the code is not |
1102 // already generated). Do not allow the assembler to perform a | 1299 // already generated). Do not allow the assembler to perform a |
1103 // garbage collection but instead return the allocation failure | 1300 // garbage collection but instead return the allocation failure |
1104 // object. | 1301 // object. |
1105 return masm()->TryCallApiFunctionAndReturn(&fun, kStackSpace); | 1302 return masm()->TryCallApiFunctionAndReturn(&fun, kStackSpace); |
1106 } | 1303 } |
1107 | 1304 |
1108 | 1305 |
1109 void StubCompiler::GenerateLoadConstant(JSObject* object, | 1306 void StubCompiler::GenerateLoadConstant(Handle<JSObject> object, |
1110 JSObject* holder, | 1307 Handle<JSObject> holder, |
1111 Register receiver, | 1308 Register receiver, |
1112 Register scratch1, | 1309 Register scratch1, |
1113 Register scratch2, | 1310 Register scratch2, |
1114 Register scratch3, | 1311 Register scratch3, |
1115 Object* value, | 1312 Handle<Object> value, |
1116 String* name, | 1313 Handle<String> name, |
1117 Label* miss) { | 1314 Label* miss) { |
1118 // Check that the receiver isn't a smi. | 1315 // Check that the receiver isn't a smi. |
1119 __ JumpIfSmi(receiver, miss); | 1316 __ JumpIfSmi(receiver, miss); |
1120 | 1317 |
1121 // Check that the maps haven't changed. | 1318 // Check that the maps haven't changed. |
1122 CheckPrototypes(object, receiver, holder, | 1319 CheckPrototypes( |
1123 scratch1, scratch2, scratch3, name, miss); | 1320 object, receiver, holder, scratch1, scratch2, scratch3, name, miss); |
1124 | 1321 |
1125 // Return the constant value. | 1322 // Return the constant value. |
1126 __ mov(eax, Handle<Object>(value)); | 1323 __ mov(eax, value); |
1127 __ ret(0); | 1324 __ ret(0); |
1128 } | 1325 } |
1129 | 1326 |
1130 | 1327 |
1131 void StubCompiler::GenerateLoadInterceptor(JSObject* object, | 1328 void StubCompiler::GenerateLoadInterceptor(JSObject* object, |
1132 JSObject* interceptor_holder, | 1329 JSObject* interceptor_holder, |
1133 LookupResult* lookup, | 1330 LookupResult* lookup, |
1134 Register receiver, | 1331 Register receiver, |
1135 Register name_reg, | 1332 Register name_reg, |
1136 Register scratch1, | 1333 Register scratch1, |
(...skipping 79 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1216 scratch2, | 1413 scratch2, |
1217 scratch3, | 1414 scratch3, |
1218 name, | 1415 name, |
1219 miss); | 1416 miss); |
1220 } | 1417 } |
1221 | 1418 |
1222 if (lookup->type() == FIELD) { | 1419 if (lookup->type() == FIELD) { |
1223 // We found FIELD property in prototype chain of interceptor's holder. | 1420 // We found FIELD property in prototype chain of interceptor's holder. |
1224 // Retrieve a field from field's holder. | 1421 // Retrieve a field from field's holder. |
1225 GenerateFastPropertyLoad(masm(), eax, holder_reg, | 1422 GenerateFastPropertyLoad(masm(), eax, holder_reg, |
1226 lookup->holder(), lookup->GetFieldIndex()); | 1423 Handle<JSObject>(lookup->holder()), |
| 1424 lookup->GetFieldIndex()); |
1227 __ ret(0); | 1425 __ ret(0); |
1228 } else { | 1426 } else { |
1229 // We found CALLBACKS property in prototype chain of interceptor's | 1427 // We found CALLBACKS property in prototype chain of interceptor's |
1230 // holder. | 1428 // holder. |
1231 ASSERT(lookup->type() == CALLBACKS); | 1429 ASSERT(lookup->type() == CALLBACKS); |
1232 ASSERT(lookup->GetCallbackObject()->IsAccessorInfo()); | 1430 ASSERT(lookup->GetCallbackObject()->IsAccessorInfo()); |
1233 AccessorInfo* callback = AccessorInfo::cast(lookup->GetCallbackObject()); | 1431 AccessorInfo* callback = AccessorInfo::cast(lookup->GetCallbackObject()); |
1234 ASSERT(callback != NULL); | 1432 ASSERT(callback != NULL); |
1235 ASSERT(callback->getter() != NULL); | 1433 ASSERT(callback->getter() != NULL); |
1236 | 1434 |
(...skipping 26 matching lines...) Expand all Loading... |
1263 __ push(scratch2); // restore old return address | 1461 __ push(scratch2); // restore old return address |
1264 | 1462 |
1265 ExternalReference ref = | 1463 ExternalReference ref = |
1266 ExternalReference(IC_Utility(IC::kLoadPropertyWithInterceptorForLoad), | 1464 ExternalReference(IC_Utility(IC::kLoadPropertyWithInterceptorForLoad), |
1267 isolate()); | 1465 isolate()); |
1268 __ TailCallExternalReference(ref, 5, 1); | 1466 __ TailCallExternalReference(ref, 5, 1); |
1269 } | 1467 } |
1270 } | 1468 } |
1271 | 1469 |
1272 | 1470 |
1273 void CallStubCompiler::GenerateNameCheck(String* name, Label* miss) { | 1471 void CallStubCompiler::GenerateNameCheck(Handle<String> name, Label* miss) { |
1274 if (kind_ == Code::KEYED_CALL_IC) { | 1472 if (kind_ == Code::KEYED_CALL_IC) { |
1275 __ cmp(ecx, Immediate(Handle<String>(name))); | 1473 __ cmp(ecx, Immediate(name)); |
1276 __ j(not_equal, miss); | 1474 __ j(not_equal, miss); |
1277 } | 1475 } |
1278 } | 1476 } |
1279 | 1477 |
1280 | 1478 |
1281 void CallStubCompiler::GenerateGlobalReceiverCheck(JSObject* object, | 1479 void CallStubCompiler::GenerateGlobalReceiverCheck(JSObject* object, |
1282 JSObject* holder, | 1480 JSObject* holder, |
1283 String* name, | 1481 String* name, |
1284 Label* miss) { | 1482 Label* miss) { |
1285 ASSERT(holder->IsGlobalObject()); | 1483 ASSERT(holder->IsGlobalObject()); |
(...skipping 42 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1328 __ cmp(FieldOperand(edi, JSFunction::kSharedFunctionInfoOffset), | 1526 __ cmp(FieldOperand(edi, JSFunction::kSharedFunctionInfoOffset), |
1329 Immediate(Handle<SharedFunctionInfo>(function->shared()))); | 1527 Immediate(Handle<SharedFunctionInfo>(function->shared()))); |
1330 __ j(not_equal, miss); | 1528 __ j(not_equal, miss); |
1331 } else { | 1529 } else { |
1332 __ cmp(edi, Immediate(Handle<JSFunction>(function))); | 1530 __ cmp(edi, Immediate(Handle<JSFunction>(function))); |
1333 __ j(not_equal, miss); | 1531 __ j(not_equal, miss); |
1334 } | 1532 } |
1335 } | 1533 } |
1336 | 1534 |
1337 | 1535 |
1338 MaybeObject* CallStubCompiler::GenerateMissBranch() { | 1536 void CallStubCompiler::GenerateMissBranch() { |
1339 MaybeObject* maybe_obj = | 1537 Handle<Code> code = |
1340 isolate()->stub_cache()->ComputeCallMiss(arguments().immediate(), | 1538 isolate()->stub_cache()->ComputeCallMiss(arguments().immediate(), |
1341 kind_, | 1539 kind_, |
1342 extra_ic_state_); | 1540 extra_state_); |
| 1541 __ jmp(code, RelocInfo::CODE_TARGET); |
| 1542 } |
| 1543 |
| 1544 |
| 1545 // TODO(kmillikin): Eliminate this function when the stub cache is fully |
| 1546 // handlified. |
| 1547 MaybeObject* CallStubCompiler::TryGenerateMissBranch() { |
| 1548 MaybeObject* maybe_obj = |
| 1549 isolate()->stub_cache()->TryComputeCallMiss(arguments().immediate(), |
| 1550 kind_, |
| 1551 extra_state_); |
1343 Object* obj; | 1552 Object* obj; |
1344 if (!maybe_obj->ToObject(&obj)) return maybe_obj; | 1553 if (!maybe_obj->ToObject(&obj)) return maybe_obj; |
1345 __ jmp(Handle<Code>(Code::cast(obj)), RelocInfo::CODE_TARGET); | 1554 __ jmp(Handle<Code>(Code::cast(obj)), RelocInfo::CODE_TARGET); |
1346 return obj; | 1555 return obj; |
1347 } | 1556 } |
1348 | 1557 |
1349 | 1558 |
1350 MUST_USE_RESULT MaybeObject* CallStubCompiler::CompileCallField( | 1559 Handle<Code> CallStubCompiler::CompileCallField(Handle<JSObject> object, |
1351 JSObject* object, | 1560 Handle<JSObject> holder, |
1352 JSObject* holder, | 1561 int index, |
1353 int index, | 1562 Handle<String> name) { |
1354 String* name) { | |
1355 // ----------- S t a t e ------------- | 1563 // ----------- S t a t e ------------- |
1356 // -- ecx : name | 1564 // -- ecx : name |
1357 // -- esp[0] : return address | 1565 // -- esp[0] : return address |
1358 // -- esp[(argc - n) * 4] : arg[n] (zero-based) | 1566 // -- esp[(argc - n) * 4] : arg[n] (zero-based) |
1359 // -- ... | 1567 // -- ... |
1360 // -- esp[(argc + 1) * 4] : receiver | 1568 // -- esp[(argc + 1) * 4] : receiver |
1361 // ----------------------------------- | 1569 // ----------------------------------- |
1362 Label miss; | 1570 Label miss; |
1363 | 1571 |
1364 GenerateNameCheck(name, &miss); | 1572 GenerateNameCheck(name, &miss); |
(...skipping 17 matching lines...) Expand all Loading... |
1382 __ j(not_equal, &miss); | 1590 __ j(not_equal, &miss); |
1383 | 1591 |
1384 // Patch the receiver on the stack with the global proxy if | 1592 // Patch the receiver on the stack with the global proxy if |
1385 // necessary. | 1593 // necessary. |
1386 if (object->IsGlobalObject()) { | 1594 if (object->IsGlobalObject()) { |
1387 __ mov(edx, FieldOperand(edx, GlobalObject::kGlobalReceiverOffset)); | 1595 __ mov(edx, FieldOperand(edx, GlobalObject::kGlobalReceiverOffset)); |
1388 __ mov(Operand(esp, (argc + 1) * kPointerSize), edx); | 1596 __ mov(Operand(esp, (argc + 1) * kPointerSize), edx); |
1389 } | 1597 } |
1390 | 1598 |
1391 // Invoke the function. | 1599 // Invoke the function. |
1392 CallKind call_kind = CallICBase::Contextual::decode(extra_ic_state_) | 1600 CallKind call_kind = CallICBase::Contextual::decode(extra_state_) |
1393 ? CALL_AS_FUNCTION | 1601 ? CALL_AS_FUNCTION |
1394 : CALL_AS_METHOD; | 1602 : CALL_AS_METHOD; |
1395 __ InvokeFunction(edi, arguments(), JUMP_FUNCTION, | 1603 __ InvokeFunction(edi, arguments(), JUMP_FUNCTION, |
1396 NullCallWrapper(), call_kind); | 1604 NullCallWrapper(), call_kind); |
1397 | 1605 |
1398 // Handle call cache miss. | 1606 // Handle call cache miss. |
1399 __ bind(&miss); | 1607 __ bind(&miss); |
1400 MaybeObject* maybe_result = GenerateMissBranch(); | 1608 GenerateMissBranch(); |
1401 if (maybe_result->IsFailure()) return maybe_result; | |
1402 | 1609 |
1403 // Return the generated code. | 1610 // Return the generated code. |
1404 return GetCode(FIELD, name); | 1611 return GetCode(FIELD, name); |
1405 } | 1612 } |
1406 | 1613 |
1407 | 1614 |
1408 MaybeObject* CallStubCompiler::CompileArrayPushCall(Object* object, | 1615 MaybeObject* CallStubCompiler::CompileArrayPushCall(Object* object, |
1409 JSObject* holder, | 1616 JSObject* holder, |
1410 JSGlobalPropertyCell* cell, | 1617 JSGlobalPropertyCell* cell, |
1411 JSFunction* function, | 1618 JSFunction* function, |
1412 String* name) { | 1619 String* name) { |
1413 // ----------- S t a t e ------------- | 1620 // ----------- S t a t e ------------- |
1414 // -- ecx : name | 1621 // -- ecx : name |
1415 // -- esp[0] : return address | 1622 // -- esp[0] : return address |
1416 // -- esp[(argc - n) * 4] : arg[n] (zero-based) | 1623 // -- esp[(argc - n) * 4] : arg[n] (zero-based) |
1417 // -- ... | 1624 // -- ... |
1418 // -- esp[(argc + 1) * 4] : receiver | 1625 // -- esp[(argc + 1) * 4] : receiver |
1419 // ----------------------------------- | 1626 // ----------------------------------- |
1420 | 1627 |
1421 // If object is not an array, bail out to regular call. | 1628 // If object is not an array, bail out to regular call. |
1422 if (!object->IsJSArray() || cell != NULL) { | 1629 if (!object->IsJSArray() || cell != NULL) { |
1423 return isolate()->heap()->undefined_value(); | 1630 return isolate()->heap()->undefined_value(); |
1424 } | 1631 } |
1425 | 1632 |
1426 Label miss; | 1633 Label miss; |
1427 | 1634 |
1428 GenerateNameCheck(name, &miss); | 1635 GenerateNameCheck(Handle<String>(name), &miss); |
1429 | 1636 |
1430 // Get the receiver from the stack. | 1637 // Get the receiver from the stack. |
1431 const int argc = arguments().immediate(); | 1638 const int argc = arguments().immediate(); |
1432 __ mov(edx, Operand(esp, (argc + 1) * kPointerSize)); | 1639 __ mov(edx, Operand(esp, (argc + 1) * kPointerSize)); |
1433 | 1640 |
1434 // Check that the receiver isn't a smi. | 1641 // Check that the receiver isn't a smi. |
1435 __ JumpIfSmi(edx, &miss); | 1642 __ JumpIfSmi(edx, &miss); |
1436 | 1643 |
1437 CheckPrototypes(JSObject::cast(object), edx, | 1644 CheckPrototypes(JSObject::cast(object), edx, |
1438 holder, ebx, | 1645 holder, ebx, |
(...skipping 67 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1506 __ bind(&attempt_to_grow_elements); | 1713 __ bind(&attempt_to_grow_elements); |
1507 if (!FLAG_inline_new) { | 1714 if (!FLAG_inline_new) { |
1508 __ jmp(&call_builtin); | 1715 __ jmp(&call_builtin); |
1509 } | 1716 } |
1510 | 1717 |
1511 __ mov(edi, Operand(esp, argc * kPointerSize)); | 1718 __ mov(edi, Operand(esp, argc * kPointerSize)); |
1512 // Growing elements that are SMI-only requires special handling in case | 1719 // Growing elements that are SMI-only requires special handling in case |
1513 // the new element is non-Smi. For now, delegate to the builtin. | 1720 // the new element is non-Smi. For now, delegate to the builtin. |
1514 Label no_fast_elements_check; | 1721 Label no_fast_elements_check; |
1515 __ JumpIfSmi(edi, &no_fast_elements_check); | 1722 __ JumpIfSmi(edi, &no_fast_elements_check); |
1516 __ mov(esi, FieldOperand(edx, HeapObject::kMapOffset)); | 1723 __ mov(ecx, FieldOperand(edx, HeapObject::kMapOffset)); |
1517 __ CheckFastObjectElements(esi, &call_builtin, Label::kFar); | 1724 __ CheckFastObjectElements(ecx, &call_builtin, Label::kFar); |
1518 __ bind(&no_fast_elements_check); | 1725 __ bind(&no_fast_elements_check); |
1519 | 1726 |
1520 // We could be lucky and the elements array could be at the top of | 1727 // We could be lucky and the elements array could be at the top of |
1521 // new-space. In this case we can just grow it in place by moving the | 1728 // new-space. In this case we can just grow it in place by moving the |
1522 // allocation pointer up. | 1729 // allocation pointer up. |
1523 | 1730 |
1524 ExternalReference new_space_allocation_top = | 1731 ExternalReference new_space_allocation_top = |
1525 ExternalReference::new_space_allocation_top_address(isolate()); | 1732 ExternalReference::new_space_allocation_top_address(isolate()); |
1526 ExternalReference new_space_allocation_limit = | 1733 ExternalReference new_space_allocation_limit = |
1527 ExternalReference::new_space_allocation_limit_address(isolate()); | 1734 ExternalReference::new_space_allocation_limit_address(isolate()); |
(...skipping 47 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1575 } | 1782 } |
1576 | 1783 |
1577 __ bind(&call_builtin); | 1784 __ bind(&call_builtin); |
1578 __ TailCallExternalReference( | 1785 __ TailCallExternalReference( |
1579 ExternalReference(Builtins::c_ArrayPush, isolate()), | 1786 ExternalReference(Builtins::c_ArrayPush, isolate()), |
1580 argc + 1, | 1787 argc + 1, |
1581 1); | 1788 1); |
1582 } | 1789 } |
1583 | 1790 |
1584 __ bind(&miss); | 1791 __ bind(&miss); |
1585 MaybeObject* maybe_result = GenerateMissBranch(); | 1792 MaybeObject* maybe_result = TryGenerateMissBranch(); |
1586 if (maybe_result->IsFailure()) return maybe_result; | 1793 if (maybe_result->IsFailure()) return maybe_result; |
1587 | 1794 |
1588 // Return the generated code. | 1795 // Return the generated code. |
1589 return GetCode(function); | 1796 return TryGetCode(function); |
1590 } | 1797 } |
1591 | 1798 |
1592 | 1799 |
1593 MaybeObject* CallStubCompiler::CompileArrayPopCall(Object* object, | 1800 MaybeObject* CallStubCompiler::CompileArrayPopCall(Object* object, |
1594 JSObject* holder, | 1801 JSObject* holder, |
1595 JSGlobalPropertyCell* cell, | 1802 JSGlobalPropertyCell* cell, |
1596 JSFunction* function, | 1803 JSFunction* function, |
1597 String* name) { | 1804 String* name) { |
1598 // ----------- S t a t e ------------- | 1805 // ----------- S t a t e ------------- |
1599 // -- ecx : name | 1806 // -- ecx : name |
1600 // -- esp[0] : return address | 1807 // -- esp[0] : return address |
1601 // -- esp[(argc - n) * 4] : arg[n] (zero-based) | 1808 // -- esp[(argc - n) * 4] : arg[n] (zero-based) |
1602 // -- ... | 1809 // -- ... |
1603 // -- esp[(argc + 1) * 4] : receiver | 1810 // -- esp[(argc + 1) * 4] : receiver |
1604 // ----------------------------------- | 1811 // ----------------------------------- |
1605 | 1812 |
1606 // If object is not an array, bail out to regular call. | 1813 // If object is not an array, bail out to regular call. |
1607 if (!object->IsJSArray() || cell != NULL) { | 1814 if (!object->IsJSArray() || cell != NULL) { |
1608 return heap()->undefined_value(); | 1815 return heap()->undefined_value(); |
1609 } | 1816 } |
1610 | 1817 |
1611 Label miss, return_undefined, call_builtin; | 1818 Label miss, return_undefined, call_builtin; |
1612 | 1819 |
1613 GenerateNameCheck(name, &miss); | 1820 GenerateNameCheck(Handle<String>(name), &miss); |
1614 | 1821 |
1615 // Get the receiver from the stack. | 1822 // Get the receiver from the stack. |
1616 const int argc = arguments().immediate(); | 1823 const int argc = arguments().immediate(); |
1617 __ mov(edx, Operand(esp, (argc + 1) * kPointerSize)); | 1824 __ mov(edx, Operand(esp, (argc + 1) * kPointerSize)); |
1618 | 1825 |
1619 // Check that the receiver isn't a smi. | 1826 // Check that the receiver isn't a smi. |
1620 __ JumpIfSmi(edx, &miss); | 1827 __ JumpIfSmi(edx, &miss); |
1621 CheckPrototypes(JSObject::cast(object), edx, | 1828 CheckPrototypes(JSObject::cast(object), edx, |
1622 holder, ebx, | 1829 holder, ebx, |
1623 eax, edi, name, &miss); | 1830 eax, edi, name, &miss); |
(...skipping 34 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1658 __ mov(eax, Immediate(factory()->undefined_value())); | 1865 __ mov(eax, Immediate(factory()->undefined_value())); |
1659 __ ret((argc + 1) * kPointerSize); | 1866 __ ret((argc + 1) * kPointerSize); |
1660 | 1867 |
1661 __ bind(&call_builtin); | 1868 __ bind(&call_builtin); |
1662 __ TailCallExternalReference( | 1869 __ TailCallExternalReference( |
1663 ExternalReference(Builtins::c_ArrayPop, isolate()), | 1870 ExternalReference(Builtins::c_ArrayPop, isolate()), |
1664 argc + 1, | 1871 argc + 1, |
1665 1); | 1872 1); |
1666 | 1873 |
1667 __ bind(&miss); | 1874 __ bind(&miss); |
1668 MaybeObject* maybe_result = GenerateMissBranch(); | 1875 MaybeObject* maybe_result = TryGenerateMissBranch(); |
1669 if (maybe_result->IsFailure()) return maybe_result; | 1876 if (maybe_result->IsFailure()) return maybe_result; |
1670 | 1877 |
1671 // Return the generated code. | 1878 // Return the generated code. |
1672 return GetCode(function); | 1879 return TryGetCode(function); |
1673 } | 1880 } |
1674 | 1881 |
1675 | 1882 |
1676 MaybeObject* CallStubCompiler::CompileStringCharCodeAtCall( | 1883 MaybeObject* CallStubCompiler::CompileStringCharCodeAtCall( |
1677 Object* object, | 1884 Object* object, |
1678 JSObject* holder, | 1885 JSObject* holder, |
1679 JSGlobalPropertyCell* cell, | 1886 JSGlobalPropertyCell* cell, |
1680 JSFunction* function, | 1887 JSFunction* function, |
1681 String* name) { | 1888 String* name) { |
1682 // ----------- S t a t e ------------- | 1889 // ----------- S t a t e ------------- |
(...skipping 10 matching lines...) Expand all Loading... |
1693 } | 1900 } |
1694 | 1901 |
1695 const int argc = arguments().immediate(); | 1902 const int argc = arguments().immediate(); |
1696 | 1903 |
1697 Label miss; | 1904 Label miss; |
1698 Label name_miss; | 1905 Label name_miss; |
1699 Label index_out_of_range; | 1906 Label index_out_of_range; |
1700 Label* index_out_of_range_label = &index_out_of_range; | 1907 Label* index_out_of_range_label = &index_out_of_range; |
1701 | 1908 |
1702 if (kind_ == Code::CALL_IC && | 1909 if (kind_ == Code::CALL_IC && |
1703 (CallICBase::StringStubState::decode(extra_ic_state_) == | 1910 (CallICBase::StringStubState::decode(extra_state_) == |
1704 DEFAULT_STRING_STUB)) { | 1911 DEFAULT_STRING_STUB)) { |
1705 index_out_of_range_label = &miss; | 1912 index_out_of_range_label = &miss; |
1706 } | 1913 } |
1707 | 1914 |
1708 GenerateNameCheck(name, &name_miss); | 1915 GenerateNameCheck(Handle<String>(name), &name_miss); |
1709 | 1916 |
1710 // Check that the maps starting from the prototype haven't changed. | 1917 // Check that the maps starting from the prototype haven't changed. |
1711 GenerateDirectLoadGlobalFunctionPrototype(masm(), | 1918 GenerateDirectLoadGlobalFunctionPrototype(masm(), |
1712 Context::STRING_FUNCTION_INDEX, | 1919 Context::STRING_FUNCTION_INDEX, |
1713 eax, | 1920 eax, |
1714 &miss); | 1921 &miss); |
1715 ASSERT(object != holder); | 1922 ASSERT(object != holder); |
1716 CheckPrototypes(JSObject::cast(object->GetPrototype()), eax, holder, | 1923 CheckPrototypes(JSObject::cast(object->GetPrototype()), eax, holder, |
1717 ebx, edx, edi, name, &miss); | 1924 ebx, edx, edi, name, &miss); |
1718 | 1925 |
(...skipping 25 matching lines...) Expand all Loading... |
1744 if (index_out_of_range.is_linked()) { | 1951 if (index_out_of_range.is_linked()) { |
1745 __ bind(&index_out_of_range); | 1952 __ bind(&index_out_of_range); |
1746 __ Set(eax, Immediate(factory()->nan_value())); | 1953 __ Set(eax, Immediate(factory()->nan_value())); |
1747 __ ret((argc + 1) * kPointerSize); | 1954 __ ret((argc + 1) * kPointerSize); |
1748 } | 1955 } |
1749 | 1956 |
1750 __ bind(&miss); | 1957 __ bind(&miss); |
1751 // Restore function name in ecx. | 1958 // Restore function name in ecx. |
1752 __ Set(ecx, Immediate(Handle<String>(name))); | 1959 __ Set(ecx, Immediate(Handle<String>(name))); |
1753 __ bind(&name_miss); | 1960 __ bind(&name_miss); |
1754 MaybeObject* maybe_result = GenerateMissBranch(); | 1961 MaybeObject* maybe_result = TryGenerateMissBranch(); |
1755 if (maybe_result->IsFailure()) return maybe_result; | 1962 if (maybe_result->IsFailure()) return maybe_result; |
1756 | 1963 |
1757 // Return the generated code. | 1964 // Return the generated code. |
1758 return GetCode(function); | 1965 return TryGetCode(function); |
1759 } | 1966 } |
1760 | 1967 |
1761 | 1968 |
1762 MaybeObject* CallStubCompiler::CompileStringCharAtCall( | 1969 MaybeObject* CallStubCompiler::CompileStringCharAtCall( |
1763 Object* object, | 1970 Object* object, |
1764 JSObject* holder, | 1971 JSObject* holder, |
1765 JSGlobalPropertyCell* cell, | 1972 JSGlobalPropertyCell* cell, |
1766 JSFunction* function, | 1973 JSFunction* function, |
1767 String* name) { | 1974 String* name) { |
1768 // ----------- S t a t e ------------- | 1975 // ----------- S t a t e ------------- |
(...skipping 10 matching lines...) Expand all Loading... |
1779 } | 1986 } |
1780 | 1987 |
1781 const int argc = arguments().immediate(); | 1988 const int argc = arguments().immediate(); |
1782 | 1989 |
1783 Label miss; | 1990 Label miss; |
1784 Label name_miss; | 1991 Label name_miss; |
1785 Label index_out_of_range; | 1992 Label index_out_of_range; |
1786 Label* index_out_of_range_label = &index_out_of_range; | 1993 Label* index_out_of_range_label = &index_out_of_range; |
1787 | 1994 |
1788 if (kind_ == Code::CALL_IC && | 1995 if (kind_ == Code::CALL_IC && |
1789 (CallICBase::StringStubState::decode(extra_ic_state_) == | 1996 (CallICBase::StringStubState::decode(extra_state_) == |
1790 DEFAULT_STRING_STUB)) { | 1997 DEFAULT_STRING_STUB)) { |
1791 index_out_of_range_label = &miss; | 1998 index_out_of_range_label = &miss; |
1792 } | 1999 } |
1793 | 2000 |
1794 GenerateNameCheck(name, &name_miss); | 2001 GenerateNameCheck(Handle<String>(name), &name_miss); |
1795 | 2002 |
1796 // Check that the maps starting from the prototype haven't changed. | 2003 // Check that the maps starting from the prototype haven't changed. |
1797 GenerateDirectLoadGlobalFunctionPrototype(masm(), | 2004 GenerateDirectLoadGlobalFunctionPrototype(masm(), |
1798 Context::STRING_FUNCTION_INDEX, | 2005 Context::STRING_FUNCTION_INDEX, |
1799 eax, | 2006 eax, |
1800 &miss); | 2007 &miss); |
1801 ASSERT(object != holder); | 2008 ASSERT(object != holder); |
1802 CheckPrototypes(JSObject::cast(object->GetPrototype()), eax, holder, | 2009 CheckPrototypes(JSObject::cast(object->GetPrototype()), eax, holder, |
1803 ebx, edx, edi, name, &miss); | 2010 ebx, edx, edi, name, &miss); |
1804 | 2011 |
(...skipping 27 matching lines...) Expand all Loading... |
1832 if (index_out_of_range.is_linked()) { | 2039 if (index_out_of_range.is_linked()) { |
1833 __ bind(&index_out_of_range); | 2040 __ bind(&index_out_of_range); |
1834 __ Set(eax, Immediate(factory()->empty_string())); | 2041 __ Set(eax, Immediate(factory()->empty_string())); |
1835 __ ret((argc + 1) * kPointerSize); | 2042 __ ret((argc + 1) * kPointerSize); |
1836 } | 2043 } |
1837 | 2044 |
1838 __ bind(&miss); | 2045 __ bind(&miss); |
1839 // Restore function name in ecx. | 2046 // Restore function name in ecx. |
1840 __ Set(ecx, Immediate(Handle<String>(name))); | 2047 __ Set(ecx, Immediate(Handle<String>(name))); |
1841 __ bind(&name_miss); | 2048 __ bind(&name_miss); |
1842 MaybeObject* maybe_result = GenerateMissBranch(); | 2049 MaybeObject* maybe_result = TryGenerateMissBranch(); |
1843 if (maybe_result->IsFailure()) return maybe_result; | 2050 if (maybe_result->IsFailure()) return maybe_result; |
1844 | 2051 |
1845 // Return the generated code. | 2052 // Return the generated code. |
1846 return GetCode(function); | 2053 return TryGetCode(function); |
1847 } | 2054 } |
1848 | 2055 |
1849 | 2056 |
1850 MaybeObject* CallStubCompiler::CompileStringFromCharCodeCall( | 2057 MaybeObject* CallStubCompiler::CompileStringFromCharCodeCall( |
1851 Object* object, | 2058 Object* object, |
1852 JSObject* holder, | 2059 JSObject* holder, |
1853 JSGlobalPropertyCell* cell, | 2060 JSGlobalPropertyCell* cell, |
1854 JSFunction* function, | 2061 JSFunction* function, |
1855 String* name) { | 2062 String* name) { |
1856 // ----------- S t a t e ------------- | 2063 // ----------- S t a t e ------------- |
1857 // -- ecx : function name | 2064 // -- ecx : function name |
1858 // -- esp[0] : return address | 2065 // -- esp[0] : return address |
1859 // -- esp[(argc - n) * 4] : arg[n] (zero-based) | 2066 // -- esp[(argc - n) * 4] : arg[n] (zero-based) |
1860 // -- ... | 2067 // -- ... |
1861 // -- esp[(argc + 1) * 4] : receiver | 2068 // -- esp[(argc + 1) * 4] : receiver |
1862 // ----------------------------------- | 2069 // ----------------------------------- |
1863 | 2070 |
1864 const int argc = arguments().immediate(); | 2071 const int argc = arguments().immediate(); |
1865 | 2072 |
1866 // If the object is not a JSObject or we got an unexpected number of | 2073 // If the object is not a JSObject or we got an unexpected number of |
1867 // arguments, bail out to the regular call. | 2074 // arguments, bail out to the regular call. |
1868 if (!object->IsJSObject() || argc != 1) { | 2075 if (!object->IsJSObject() || argc != 1) { |
1869 return isolate()->heap()->undefined_value(); | 2076 return isolate()->heap()->undefined_value(); |
1870 } | 2077 } |
1871 | 2078 |
1872 Label miss; | 2079 Label miss; |
1873 GenerateNameCheck(name, &miss); | 2080 GenerateNameCheck(Handle<String>(name), &miss); |
1874 | 2081 |
1875 if (cell == NULL) { | 2082 if (cell == NULL) { |
1876 __ mov(edx, Operand(esp, 2 * kPointerSize)); | 2083 __ mov(edx, Operand(esp, 2 * kPointerSize)); |
1877 | 2084 |
1878 STATIC_ASSERT(kSmiTag == 0); | 2085 STATIC_ASSERT(kSmiTag == 0); |
1879 __ JumpIfSmi(edx, &miss); | 2086 __ JumpIfSmi(edx, &miss); |
1880 | 2087 |
1881 CheckPrototypes(JSObject::cast(object), edx, holder, ebx, eax, edi, name, | 2088 CheckPrototypes(JSObject::cast(object), edx, holder, ebx, eax, edi, name, |
1882 &miss); | 2089 &miss); |
1883 } else { | 2090 } else { |
(...skipping 17 matching lines...) Expand all Loading... |
1901 StringCharFromCodeGenerator char_from_code_generator(code, eax); | 2108 StringCharFromCodeGenerator char_from_code_generator(code, eax); |
1902 char_from_code_generator.GenerateFast(masm()); | 2109 char_from_code_generator.GenerateFast(masm()); |
1903 __ ret(2 * kPointerSize); | 2110 __ ret(2 * kPointerSize); |
1904 | 2111 |
1905 StubRuntimeCallHelper call_helper; | 2112 StubRuntimeCallHelper call_helper; |
1906 char_from_code_generator.GenerateSlow(masm(), call_helper); | 2113 char_from_code_generator.GenerateSlow(masm(), call_helper); |
1907 | 2114 |
1908 // Tail call the full function. We do not have to patch the receiver | 2115 // Tail call the full function. We do not have to patch the receiver |
1909 // because the function makes no use of it. | 2116 // because the function makes no use of it. |
1910 __ bind(&slow); | 2117 __ bind(&slow); |
1911 CallKind call_kind = CallICBase::Contextual::decode(extra_ic_state_) | 2118 CallKind call_kind = CallICBase::Contextual::decode(extra_state_) |
1912 ? CALL_AS_FUNCTION | 2119 ? CALL_AS_FUNCTION |
1913 : CALL_AS_METHOD; | 2120 : CALL_AS_METHOD; |
1914 __ InvokeFunction(function, arguments(), JUMP_FUNCTION, | 2121 __ InvokeFunction(function, arguments(), JUMP_FUNCTION, |
1915 NullCallWrapper(), call_kind); | 2122 NullCallWrapper(), call_kind); |
1916 | 2123 |
1917 __ bind(&miss); | 2124 __ bind(&miss); |
1918 // ecx: function name. | 2125 // ecx: function name. |
1919 MaybeObject* maybe_result = GenerateMissBranch(); | 2126 MaybeObject* maybe_result = TryGenerateMissBranch(); |
1920 if (maybe_result->IsFailure()) return maybe_result; | 2127 if (maybe_result->IsFailure()) return maybe_result; |
1921 | 2128 |
1922 // Return the generated code. | 2129 // Return the generated code. |
1923 return (cell == NULL) ? GetCode(function) : GetCode(NORMAL, name); | 2130 return (cell == NULL) ? TryGetCode(function) : TryGetCode(NORMAL, name); |
1924 } | 2131 } |
1925 | 2132 |
1926 | 2133 |
1927 MaybeObject* CallStubCompiler::CompileMathFloorCall(Object* object, | 2134 MaybeObject* CallStubCompiler::CompileMathFloorCall(Object* object, |
1928 JSObject* holder, | 2135 JSObject* holder, |
1929 JSGlobalPropertyCell* cell, | 2136 JSGlobalPropertyCell* cell, |
1930 JSFunction* function, | 2137 JSFunction* function, |
1931 String* name) { | 2138 String* name) { |
1932 // ----------- S t a t e ------------- | 2139 // ----------- S t a t e ------------- |
1933 // -- ecx : name | 2140 // -- ecx : name |
(...skipping 11 matching lines...) Expand all Loading... |
1945 | 2152 |
1946 const int argc = arguments().immediate(); | 2153 const int argc = arguments().immediate(); |
1947 | 2154 |
1948 // If the object is not a JSObject or we got an unexpected number of | 2155 // If the object is not a JSObject or we got an unexpected number of |
1949 // arguments, bail out to the regular call. | 2156 // arguments, bail out to the regular call. |
1950 if (!object->IsJSObject() || argc != 1) { | 2157 if (!object->IsJSObject() || argc != 1) { |
1951 return isolate()->heap()->undefined_value(); | 2158 return isolate()->heap()->undefined_value(); |
1952 } | 2159 } |
1953 | 2160 |
1954 Label miss; | 2161 Label miss; |
1955 GenerateNameCheck(name, &miss); | 2162 GenerateNameCheck(Handle<String>(name), &miss); |
1956 | 2163 |
1957 if (cell == NULL) { | 2164 if (cell == NULL) { |
1958 __ mov(edx, Operand(esp, 2 * kPointerSize)); | 2165 __ mov(edx, Operand(esp, 2 * kPointerSize)); |
1959 | 2166 |
1960 STATIC_ASSERT(kSmiTag == 0); | 2167 STATIC_ASSERT(kSmiTag == 0); |
1961 __ JumpIfSmi(edx, &miss); | 2168 __ JumpIfSmi(edx, &miss); |
1962 | 2169 |
1963 CheckPrototypes(JSObject::cast(object), edx, holder, ebx, eax, edi, name, | 2170 CheckPrototypes(JSObject::cast(object), edx, holder, ebx, eax, edi, name, |
1964 &miss); | 2171 &miss); |
1965 } else { | 2172 } else { |
(...skipping 72 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2038 __ ret(2 * kPointerSize); | 2245 __ ret(2 * kPointerSize); |
2039 | 2246 |
2040 // Tail call the full function. We do not have to patch the receiver | 2247 // Tail call the full function. We do not have to patch the receiver |
2041 // because the function makes no use of it. | 2248 // because the function makes no use of it. |
2042 __ bind(&slow); | 2249 __ bind(&slow); |
2043 __ InvokeFunction(function, arguments(), JUMP_FUNCTION, | 2250 __ InvokeFunction(function, arguments(), JUMP_FUNCTION, |
2044 NullCallWrapper(), CALL_AS_METHOD); | 2251 NullCallWrapper(), CALL_AS_METHOD); |
2045 | 2252 |
2046 __ bind(&miss); | 2253 __ bind(&miss); |
2047 // ecx: function name. | 2254 // ecx: function name. |
2048 MaybeObject* maybe_result = GenerateMissBranch(); | 2255 MaybeObject* maybe_result = TryGenerateMissBranch(); |
2049 if (maybe_result->IsFailure()) return maybe_result; | 2256 if (maybe_result->IsFailure()) return maybe_result; |
2050 | 2257 |
2051 // Return the generated code. | 2258 // Return the generated code. |
2052 return (cell == NULL) ? GetCode(function) : GetCode(NORMAL, name); | 2259 return (cell == NULL) ? TryGetCode(function) : TryGetCode(NORMAL, name); |
2053 } | 2260 } |
2054 | 2261 |
2055 | 2262 |
2056 MaybeObject* CallStubCompiler::CompileMathAbsCall(Object* object, | 2263 MaybeObject* CallStubCompiler::CompileMathAbsCall(Object* object, |
2057 JSObject* holder, | 2264 JSObject* holder, |
2058 JSGlobalPropertyCell* cell, | 2265 JSGlobalPropertyCell* cell, |
2059 JSFunction* function, | 2266 JSFunction* function, |
2060 String* name) { | 2267 String* name) { |
2061 // ----------- S t a t e ------------- | 2268 // ----------- S t a t e ------------- |
2062 // -- ecx : name | 2269 // -- ecx : name |
2063 // -- esp[0] : return address | 2270 // -- esp[0] : return address |
2064 // -- esp[(argc - n) * 4] : arg[n] (zero-based) | 2271 // -- esp[(argc - n) * 4] : arg[n] (zero-based) |
2065 // -- ... | 2272 // -- ... |
2066 // -- esp[(argc + 1) * 4] : receiver | 2273 // -- esp[(argc + 1) * 4] : receiver |
2067 // ----------------------------------- | 2274 // ----------------------------------- |
2068 | 2275 |
2069 const int argc = arguments().immediate(); | 2276 const int argc = arguments().immediate(); |
2070 | 2277 |
2071 // If the object is not a JSObject or we got an unexpected number of | 2278 // If the object is not a JSObject or we got an unexpected number of |
2072 // arguments, bail out to the regular call. | 2279 // arguments, bail out to the regular call. |
2073 if (!object->IsJSObject() || argc != 1) { | 2280 if (!object->IsJSObject() || argc != 1) { |
2074 return isolate()->heap()->undefined_value(); | 2281 return isolate()->heap()->undefined_value(); |
2075 } | 2282 } |
2076 | 2283 |
2077 Label miss; | 2284 Label miss; |
2078 GenerateNameCheck(name, &miss); | 2285 GenerateNameCheck(Handle<String>(name), &miss); |
2079 | 2286 |
2080 if (cell == NULL) { | 2287 if (cell == NULL) { |
2081 __ mov(edx, Operand(esp, 2 * kPointerSize)); | 2288 __ mov(edx, Operand(esp, 2 * kPointerSize)); |
2082 | 2289 |
2083 STATIC_ASSERT(kSmiTag == 0); | 2290 STATIC_ASSERT(kSmiTag == 0); |
2084 __ JumpIfSmi(edx, &miss); | 2291 __ JumpIfSmi(edx, &miss); |
2085 | 2292 |
2086 CheckPrototypes(JSObject::cast(object), edx, holder, ebx, eax, edi, name, | 2293 CheckPrototypes(JSObject::cast(object), edx, holder, ebx, eax, edi, name, |
2087 &miss); | 2294 &miss); |
2088 } else { | 2295 } else { |
(...skipping 53 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2142 __ ret(2 * kPointerSize); | 2349 __ ret(2 * kPointerSize); |
2143 | 2350 |
2144 // Tail call the full function. We do not have to patch the receiver | 2351 // Tail call the full function. We do not have to patch the receiver |
2145 // because the function makes no use of it. | 2352 // because the function makes no use of it. |
2146 __ bind(&slow); | 2353 __ bind(&slow); |
2147 __ InvokeFunction(function, arguments(), JUMP_FUNCTION, | 2354 __ InvokeFunction(function, arguments(), JUMP_FUNCTION, |
2148 NullCallWrapper(), CALL_AS_METHOD); | 2355 NullCallWrapper(), CALL_AS_METHOD); |
2149 | 2356 |
2150 __ bind(&miss); | 2357 __ bind(&miss); |
2151 // ecx: function name. | 2358 // ecx: function name. |
2152 MaybeObject* maybe_result = GenerateMissBranch(); | 2359 MaybeObject* maybe_result = TryGenerateMissBranch(); |
2153 if (maybe_result->IsFailure()) return maybe_result; | 2360 if (maybe_result->IsFailure()) return maybe_result; |
2154 | 2361 |
2155 // Return the generated code. | 2362 // Return the generated code. |
2156 return (cell == NULL) ? GetCode(function) : GetCode(NORMAL, name); | 2363 return (cell == NULL) ? TryGetCode(function) : TryGetCode(NORMAL, name); |
2157 } | 2364 } |
2158 | 2365 |
2159 | 2366 |
2160 MaybeObject* CallStubCompiler::CompileFastApiCall( | 2367 MaybeObject* CallStubCompiler::CompileFastApiCall( |
2161 const CallOptimization& optimization, | 2368 const CallOptimization& optimization, |
2162 Object* object, | 2369 Object* object, |
2163 JSObject* holder, | 2370 JSObject* holder, |
2164 JSGlobalPropertyCell* cell, | 2371 JSGlobalPropertyCell* cell, |
2165 JSFunction* function, | 2372 JSFunction* function, |
2166 String* name) { | 2373 String* name) { |
2167 ASSERT(optimization.is_simple_api_call()); | 2374 ASSERT(optimization.is_simple_api_call()); |
2168 // Bail out if object is a global object as we don't want to | 2375 // Bail out if object is a global object as we don't want to |
2169 // repatch it to global receiver. | 2376 // repatch it to global receiver. |
2170 if (object->IsGlobalObject()) return heap()->undefined_value(); | 2377 if (object->IsGlobalObject()) return heap()->undefined_value(); |
2171 if (cell != NULL) return heap()->undefined_value(); | 2378 if (cell != NULL) return heap()->undefined_value(); |
2172 if (!object->IsJSObject()) return heap()->undefined_value(); | 2379 if (!object->IsJSObject()) return heap()->undefined_value(); |
2173 int depth = optimization.GetPrototypeDepthOfExpectedType( | 2380 int depth = optimization.GetPrototypeDepthOfExpectedType( |
2174 JSObject::cast(object), holder); | 2381 JSObject::cast(object), holder); |
2175 if (depth == kInvalidProtoDepth) return heap()->undefined_value(); | 2382 if (depth == kInvalidProtoDepth) return heap()->undefined_value(); |
2176 | 2383 |
2177 Label miss, miss_before_stack_reserved; | 2384 Label miss, miss_before_stack_reserved; |
2178 | 2385 |
2179 GenerateNameCheck(name, &miss_before_stack_reserved); | 2386 GenerateNameCheck(Handle<String>(name), &miss_before_stack_reserved); |
2180 | 2387 |
2181 // Get the receiver from the stack. | 2388 // Get the receiver from the stack. |
2182 const int argc = arguments().immediate(); | 2389 const int argc = arguments().immediate(); |
2183 __ mov(edx, Operand(esp, (argc + 1) * kPointerSize)); | 2390 __ mov(edx, Operand(esp, (argc + 1) * kPointerSize)); |
2184 | 2391 |
2185 // Check that the receiver isn't a smi. | 2392 // Check that the receiver isn't a smi. |
2186 __ JumpIfSmi(edx, &miss_before_stack_reserved); | 2393 __ JumpIfSmi(edx, &miss_before_stack_reserved); |
2187 | 2394 |
2188 Counters* counters = isolate()->counters(); | 2395 Counters* counters = isolate()->counters(); |
2189 __ IncrementCounter(counters->call_const(), 1); | 2396 __ IncrementCounter(counters->call_const(), 1); |
(...skipping 13 matching lines...) Expand all Loading... |
2203 | 2410 |
2204 // esp[2 * kPointerSize] is uninitialized, esp[3 * kPointerSize] contains | 2411 // esp[2 * kPointerSize] is uninitialized, esp[3 * kPointerSize] contains |
2205 // duplicate of return address and will be overwritten. | 2412 // duplicate of return address and will be overwritten. |
2206 MaybeObject* result = GenerateFastApiCall(masm(), optimization, argc); | 2413 MaybeObject* result = GenerateFastApiCall(masm(), optimization, argc); |
2207 if (result->IsFailure()) return result; | 2414 if (result->IsFailure()) return result; |
2208 | 2415 |
2209 __ bind(&miss); | 2416 __ bind(&miss); |
2210 __ add(esp, Immediate(kFastApiCallArguments * kPointerSize)); | 2417 __ add(esp, Immediate(kFastApiCallArguments * kPointerSize)); |
2211 | 2418 |
2212 __ bind(&miss_before_stack_reserved); | 2419 __ bind(&miss_before_stack_reserved); |
2213 MaybeObject* maybe_result = GenerateMissBranch(); | 2420 MaybeObject* maybe_result = TryGenerateMissBranch(); |
2214 if (maybe_result->IsFailure()) return maybe_result; | 2421 if (maybe_result->IsFailure()) return maybe_result; |
2215 | 2422 |
2216 // Return the generated code. | 2423 // Return the generated code. |
2217 return GetCode(function); | 2424 return TryGetCode(function); |
2218 } | 2425 } |
2219 | 2426 |
2220 | 2427 |
2221 MaybeObject* CallStubCompiler::CompileCallConstant( | 2428 MaybeObject* CallStubCompiler::CompileCallConstant( |
2222 Object* object, | 2429 Object* object, |
2223 JSObject* holder, | 2430 JSObject* holder, |
2224 JSFunction* function, | 2431 JSFunction* function, |
2225 String* name, | 2432 String* name, |
2226 CheckType check) { | 2433 CheckType check) { |
2227 // ----------- S t a t e ------------- | 2434 // ----------- S t a t e ------------- |
2228 // -- ecx : name | 2435 // -- ecx : name |
2229 // -- esp[0] : return address | 2436 // -- esp[0] : return address |
2230 // -- esp[(argc - n) * 4] : arg[n] (zero-based) | 2437 // -- esp[(argc - n) * 4] : arg[n] (zero-based) |
2231 // -- ... | 2438 // -- ... |
2232 // -- esp[(argc + 1) * 4] : receiver | 2439 // -- esp[(argc + 1) * 4] : receiver |
2233 // ----------------------------------- | 2440 // ----------------------------------- |
2234 | 2441 |
2235 if (HasCustomCallGenerator(function)) { | 2442 if (HasCustomCallGenerator(function)) { |
2236 MaybeObject* maybe_result = CompileCustomCall( | 2443 MaybeObject* maybe_result = CompileCustomCall( |
2237 object, holder, NULL, function, name); | 2444 object, holder, NULL, function, name); |
2238 Object* result; | 2445 Object* result; |
2239 if (!maybe_result->ToObject(&result)) return maybe_result; | 2446 if (!maybe_result->ToObject(&result)) return maybe_result; |
2240 // undefined means bail out to regular compiler. | 2447 // undefined means bail out to regular compiler. |
2241 if (!result->IsUndefined()) return result; | 2448 if (!result->IsUndefined()) return result; |
2242 } | 2449 } |
2243 | 2450 |
2244 Label miss; | 2451 Label miss; |
2245 | 2452 |
2246 GenerateNameCheck(name, &miss); | 2453 GenerateNameCheck(Handle<String>(name), &miss); |
2247 | 2454 |
2248 // Get the receiver from the stack. | 2455 // Get the receiver from the stack. |
2249 const int argc = arguments().immediate(); | 2456 const int argc = arguments().immediate(); |
2250 __ mov(edx, Operand(esp, (argc + 1) * kPointerSize)); | 2457 __ mov(edx, Operand(esp, (argc + 1) * kPointerSize)); |
2251 | 2458 |
2252 // Check that the receiver isn't a smi. | 2459 // Check that the receiver isn't a smi. |
2253 if (check != NUMBER_CHECK) { | 2460 if (check != NUMBER_CHECK) { |
2254 __ JumpIfSmi(edx, &miss); | 2461 __ JumpIfSmi(edx, &miss); |
2255 } | 2462 } |
2256 | 2463 |
(...skipping 75 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2332 CheckPrototypes(JSObject::cast(object->GetPrototype()), eax, holder, | 2539 CheckPrototypes(JSObject::cast(object->GetPrototype()), eax, holder, |
2333 ebx, edx, edi, name, &miss); | 2540 ebx, edx, edi, name, &miss); |
2334 } | 2541 } |
2335 break; | 2542 break; |
2336 } | 2543 } |
2337 | 2544 |
2338 default: | 2545 default: |
2339 UNREACHABLE(); | 2546 UNREACHABLE(); |
2340 } | 2547 } |
2341 | 2548 |
2342 CallKind call_kind = CallICBase::Contextual::decode(extra_ic_state_) | 2549 CallKind call_kind = CallICBase::Contextual::decode(extra_state_) |
2343 ? CALL_AS_FUNCTION | 2550 ? CALL_AS_FUNCTION |
2344 : CALL_AS_METHOD; | 2551 : CALL_AS_METHOD; |
2345 __ InvokeFunction(function, arguments(), JUMP_FUNCTION, | 2552 __ InvokeFunction(function, arguments(), JUMP_FUNCTION, |
2346 NullCallWrapper(), call_kind); | 2553 NullCallWrapper(), call_kind); |
2347 | 2554 |
2348 // Handle call cache miss. | 2555 // Handle call cache miss. |
2349 __ bind(&miss); | 2556 __ bind(&miss); |
2350 MaybeObject* maybe_result = GenerateMissBranch(); | 2557 MaybeObject* maybe_result = TryGenerateMissBranch(); |
2351 if (maybe_result->IsFailure()) return maybe_result; | 2558 if (maybe_result->IsFailure()) return maybe_result; |
2352 | 2559 |
2353 // Return the generated code. | 2560 // Return the generated code. |
2354 return GetCode(function); | 2561 return TryGetCode(function); |
2355 } | 2562 } |
2356 | 2563 |
2357 | 2564 |
2358 MaybeObject* CallStubCompiler::CompileCallInterceptor(JSObject* object, | 2565 MaybeObject* CallStubCompiler::CompileCallInterceptor(JSObject* object, |
2359 JSObject* holder, | 2566 JSObject* holder, |
2360 String* name) { | 2567 String* name) { |
2361 // ----------- S t a t e ------------- | 2568 // ----------- S t a t e ------------- |
2362 // -- ecx : name | 2569 // -- ecx : name |
2363 // -- esp[0] : return address | 2570 // -- esp[0] : return address |
2364 // -- esp[(argc - n) * 4] : arg[n] (zero-based) | 2571 // -- esp[(argc - n) * 4] : arg[n] (zero-based) |
2365 // -- ... | 2572 // -- ... |
2366 // -- esp[(argc + 1) * 4] : receiver | 2573 // -- esp[(argc + 1) * 4] : receiver |
2367 // ----------------------------------- | 2574 // ----------------------------------- |
2368 Label miss; | 2575 Label miss; |
2369 | 2576 |
2370 GenerateNameCheck(name, &miss); | 2577 GenerateNameCheck(Handle<String>(name), &miss); |
2371 | 2578 |
2372 // Get the number of arguments. | 2579 // Get the number of arguments. |
2373 const int argc = arguments().immediate(); | 2580 const int argc = arguments().immediate(); |
2374 | 2581 |
2375 LookupResult lookup; | 2582 LookupResult lookup(isolate()); |
2376 LookupPostInterceptor(holder, name, &lookup); | 2583 LookupPostInterceptor(holder, name, &lookup); |
2377 | 2584 |
2378 // Get the receiver from the stack. | 2585 // Get the receiver from the stack. |
2379 __ mov(edx, Operand(esp, (argc + 1) * kPointerSize)); | 2586 __ mov(edx, Operand(esp, (argc + 1) * kPointerSize)); |
2380 | 2587 |
2381 CallInterceptorCompiler compiler(this, arguments(), ecx, extra_ic_state_); | 2588 CallInterceptorCompiler compiler(this, arguments(), ecx, extra_state_); |
2382 MaybeObject* result = compiler.Compile(masm(), | 2589 MaybeObject* result = compiler.Compile(masm(), |
2383 object, | 2590 object, |
2384 holder, | 2591 holder, |
2385 name, | 2592 name, |
2386 &lookup, | 2593 &lookup, |
2387 edx, | 2594 edx, |
2388 ebx, | 2595 ebx, |
2389 edi, | 2596 edi, |
2390 eax, | 2597 eax, |
2391 &miss); | 2598 &miss); |
2392 if (result->IsFailure()) return result; | 2599 if (result->IsFailure()) return result; |
2393 | 2600 |
2394 // Restore receiver. | 2601 // Restore receiver. |
2395 __ mov(edx, Operand(esp, (argc + 1) * kPointerSize)); | 2602 __ mov(edx, Operand(esp, (argc + 1) * kPointerSize)); |
2396 | 2603 |
2397 // Check that the function really is a function. | 2604 // Check that the function really is a function. |
2398 __ JumpIfSmi(eax, &miss); | 2605 __ JumpIfSmi(eax, &miss); |
2399 __ CmpObjectType(eax, JS_FUNCTION_TYPE, ebx); | 2606 __ CmpObjectType(eax, JS_FUNCTION_TYPE, ebx); |
2400 __ j(not_equal, &miss); | 2607 __ j(not_equal, &miss); |
2401 | 2608 |
2402 // Patch the receiver on the stack with the global proxy if | 2609 // Patch the receiver on the stack with the global proxy if |
2403 // necessary. | 2610 // necessary. |
2404 if (object->IsGlobalObject()) { | 2611 if (object->IsGlobalObject()) { |
2405 __ mov(edx, FieldOperand(edx, GlobalObject::kGlobalReceiverOffset)); | 2612 __ mov(edx, FieldOperand(edx, GlobalObject::kGlobalReceiverOffset)); |
2406 __ mov(Operand(esp, (argc + 1) * kPointerSize), edx); | 2613 __ mov(Operand(esp, (argc + 1) * kPointerSize), edx); |
2407 } | 2614 } |
2408 | 2615 |
2409 // Invoke the function. | 2616 // Invoke the function. |
2410 __ mov(edi, eax); | 2617 __ mov(edi, eax); |
2411 CallKind call_kind = CallICBase::Contextual::decode(extra_ic_state_) | 2618 CallKind call_kind = CallICBase::Contextual::decode(extra_state_) |
2412 ? CALL_AS_FUNCTION | 2619 ? CALL_AS_FUNCTION |
2413 : CALL_AS_METHOD; | 2620 : CALL_AS_METHOD; |
2414 __ InvokeFunction(edi, arguments(), JUMP_FUNCTION, | 2621 __ InvokeFunction(edi, arguments(), JUMP_FUNCTION, |
2415 NullCallWrapper(), call_kind); | 2622 NullCallWrapper(), call_kind); |
2416 | 2623 |
2417 // Handle load cache miss. | 2624 // Handle load cache miss. |
2418 __ bind(&miss); | 2625 __ bind(&miss); |
2419 MaybeObject* maybe_result = GenerateMissBranch(); | 2626 MaybeObject* maybe_result = TryGenerateMissBranch(); |
2420 if (maybe_result->IsFailure()) return maybe_result; | 2627 if (maybe_result->IsFailure()) return maybe_result; |
2421 | 2628 |
2422 // Return the generated code. | 2629 // Return the generated code. |
2423 return GetCode(INTERCEPTOR, name); | 2630 return TryGetCode(INTERCEPTOR, name); |
2424 } | 2631 } |
2425 | 2632 |
2426 | 2633 |
2427 MaybeObject* CallStubCompiler::CompileCallGlobal( | 2634 MaybeObject* CallStubCompiler::CompileCallGlobal( |
2428 JSObject* object, | 2635 JSObject* object, |
2429 GlobalObject* holder, | 2636 GlobalObject* holder, |
2430 JSGlobalPropertyCell* cell, | 2637 JSGlobalPropertyCell* cell, |
2431 JSFunction* function, | 2638 JSFunction* function, |
2432 String* name) { | 2639 String* name) { |
2433 // ----------- S t a t e ------------- | 2640 // ----------- S t a t e ------------- |
2434 // -- ecx : name | 2641 // -- ecx : name |
2435 // -- esp[0] : return address | 2642 // -- esp[0] : return address |
2436 // -- esp[(argc - n) * 4] : arg[n] (zero-based) | 2643 // -- esp[(argc - n) * 4] : arg[n] (zero-based) |
2437 // -- ... | 2644 // -- ... |
2438 // -- esp[(argc + 1) * 4] : receiver | 2645 // -- esp[(argc + 1) * 4] : receiver |
2439 // ----------------------------------- | 2646 // ----------------------------------- |
2440 | 2647 |
2441 if (HasCustomCallGenerator(function)) { | 2648 if (HasCustomCallGenerator(function)) { |
2442 MaybeObject* maybe_result = CompileCustomCall( | 2649 MaybeObject* maybe_result = CompileCustomCall( |
2443 object, holder, cell, function, name); | 2650 object, holder, cell, function, name); |
2444 Object* result; | 2651 Object* result; |
2445 if (!maybe_result->ToObject(&result)) return maybe_result; | 2652 if (!maybe_result->ToObject(&result)) return maybe_result; |
2446 // undefined means bail out to regular compiler. | 2653 // undefined means bail out to regular compiler. |
2447 if (!result->IsUndefined()) return result; | 2654 if (!result->IsUndefined()) return result; |
2448 } | 2655 } |
2449 | 2656 |
2450 Label miss; | 2657 Label miss; |
2451 | 2658 |
2452 GenerateNameCheck(name, &miss); | 2659 GenerateNameCheck(Handle<String>(name), &miss); |
2453 | 2660 |
2454 // Get the number of arguments. | 2661 // Get the number of arguments. |
2455 const int argc = arguments().immediate(); | 2662 const int argc = arguments().immediate(); |
2456 | 2663 |
2457 GenerateGlobalReceiverCheck(object, holder, name, &miss); | 2664 GenerateGlobalReceiverCheck(object, holder, name, &miss); |
2458 | 2665 |
2459 GenerateLoadFunctionFromCell(cell, function, &miss); | 2666 GenerateLoadFunctionFromCell(cell, function, &miss); |
2460 | 2667 |
2461 // Patch the receiver on the stack with the global proxy. | 2668 // Patch the receiver on the stack with the global proxy. |
2462 if (object->IsGlobalObject()) { | 2669 if (object->IsGlobalObject()) { |
2463 __ mov(edx, FieldOperand(edx, GlobalObject::kGlobalReceiverOffset)); | 2670 __ mov(edx, FieldOperand(edx, GlobalObject::kGlobalReceiverOffset)); |
2464 __ mov(Operand(esp, (argc + 1) * kPointerSize), edx); | 2671 __ mov(Operand(esp, (argc + 1) * kPointerSize), edx); |
2465 } | 2672 } |
2466 | 2673 |
2467 // Setup the context (function already in edi). | 2674 // Setup the context (function already in edi). |
2468 __ mov(esi, FieldOperand(edi, JSFunction::kContextOffset)); | 2675 __ mov(esi, FieldOperand(edi, JSFunction::kContextOffset)); |
2469 | 2676 |
2470 // Jump to the cached code (tail call). | 2677 // Jump to the cached code (tail call). |
2471 Counters* counters = isolate()->counters(); | 2678 Counters* counters = isolate()->counters(); |
2472 __ IncrementCounter(counters->call_global_inline(), 1); | 2679 __ IncrementCounter(counters->call_global_inline(), 1); |
2473 ASSERT(function->is_compiled()); | |
2474 ParameterCount expected(function->shared()->formal_parameter_count()); | 2680 ParameterCount expected(function->shared()->formal_parameter_count()); |
2475 CallKind call_kind = CallICBase::Contextual::decode(extra_ic_state_) | 2681 CallKind call_kind = CallICBase::Contextual::decode(extra_state_) |
2476 ? CALL_AS_FUNCTION | 2682 ? CALL_AS_FUNCTION |
2477 : CALL_AS_METHOD; | 2683 : CALL_AS_METHOD; |
2478 if (V8::UseCrankshaft()) { | 2684 // We call indirectly through the code field in the function to |
2479 // TODO(kasperl): For now, we always call indirectly through the | 2685 // allow recompilation to take effect without changing any of the |
2480 // code field in the function to allow recompilation to take effect | 2686 // call sites. |
2481 // without changing any of the call sites. | 2687 __ InvokeCode(FieldOperand(edi, JSFunction::kCodeEntryOffset), |
2482 __ InvokeCode(FieldOperand(edi, JSFunction::kCodeEntryOffset), | 2688 expected, arguments(), JUMP_FUNCTION, |
2483 expected, arguments(), JUMP_FUNCTION, | 2689 NullCallWrapper(), call_kind); |
2484 NullCallWrapper(), call_kind); | |
2485 } else { | |
2486 Handle<Code> code(function->code()); | |
2487 __ InvokeCode(code, expected, arguments(), | |
2488 RelocInfo::CODE_TARGET, JUMP_FUNCTION, | |
2489 NullCallWrapper(), call_kind); | |
2490 } | |
2491 | 2690 |
2492 // Handle call cache miss. | 2691 // Handle call cache miss. |
2493 __ bind(&miss); | 2692 __ bind(&miss); |
2494 __ IncrementCounter(counters->call_global_inline_miss(), 1); | 2693 __ IncrementCounter(counters->call_global_inline_miss(), 1); |
2495 MaybeObject* maybe_result = GenerateMissBranch(); | 2694 MaybeObject* maybe_result = TryGenerateMissBranch(); |
2496 if (maybe_result->IsFailure()) return maybe_result; | 2695 if (maybe_result->IsFailure()) return maybe_result; |
2497 | 2696 |
2498 // Return the generated code. | 2697 // Return the generated code. |
2499 return GetCode(NORMAL, name); | 2698 return TryGetCode(NORMAL, name); |
2500 } | 2699 } |
2501 | 2700 |
2502 | 2701 |
2503 MaybeObject* StoreStubCompiler::CompileStoreField(JSObject* object, | 2702 Handle<Code> StoreStubCompiler::CompileStoreField(Handle<JSObject> object, |
2504 int index, | 2703 int index, |
2505 Map* transition, | 2704 Handle<Map> transition, |
2506 String* name) { | 2705 Handle<String> name) { |
2507 // ----------- S t a t e ------------- | 2706 // ----------- S t a t e ------------- |
2508 // -- eax : value | 2707 // -- eax : value |
2509 // -- ecx : name | 2708 // -- ecx : name |
2510 // -- edx : receiver | 2709 // -- edx : receiver |
2511 // -- esp[0] : return address | 2710 // -- esp[0] : return address |
2512 // ----------------------------------- | 2711 // ----------------------------------- |
2513 Label miss; | 2712 Label miss; |
2514 | 2713 |
2515 // Generate store field code. Trashes the name register. | 2714 // Generate store field code. Trashes the name register. |
2516 GenerateStoreField(masm(), | 2715 GenerateStoreField(masm(), object, index, transition, edx, ecx, ebx, &miss); |
2517 object, | |
2518 index, | |
2519 transition, | |
2520 edx, ecx, ebx, | |
2521 &miss); | |
2522 | 2716 |
2523 // Handle store cache miss. | 2717 // Handle store cache miss. |
2524 __ bind(&miss); | 2718 __ bind(&miss); |
2525 __ mov(ecx, Immediate(Handle<String>(name))); // restore name | 2719 __ mov(ecx, Immediate(name)); // restore name |
2526 Handle<Code> ic = isolate()->builtins()->StoreIC_Miss(); | 2720 Handle<Code> ic = isolate()->builtins()->StoreIC_Miss(); |
2527 __ jmp(ic, RelocInfo::CODE_TARGET); | 2721 __ jmp(ic, RelocInfo::CODE_TARGET); |
2528 | 2722 |
2529 // Return the generated code. | 2723 // Return the generated code. |
2530 return GetCode(transition == NULL ? FIELD : MAP_TRANSITION, name); | 2724 return GetCode(transition.is_null() ? FIELD : MAP_TRANSITION, name); |
2531 } | 2725 } |
2532 | 2726 |
2533 | 2727 |
2534 MaybeObject* StoreStubCompiler::CompileStoreCallback(JSObject* object, | 2728 Handle<Code> StoreStubCompiler::CompileStoreCallback( |
2535 AccessorInfo* callback, | 2729 Handle<JSObject> object, |
2536 String* name) { | 2730 Handle<AccessorInfo> callback, |
| 2731 Handle<String> name) { |
2537 // ----------- S t a t e ------------- | 2732 // ----------- S t a t e ------------- |
2538 // -- eax : value | 2733 // -- eax : value |
2539 // -- ecx : name | 2734 // -- ecx : name |
2540 // -- edx : receiver | 2735 // -- edx : receiver |
2541 // -- esp[0] : return address | 2736 // -- esp[0] : return address |
2542 // ----------------------------------- | 2737 // ----------------------------------- |
2543 Label miss; | 2738 Label miss; |
2544 | 2739 |
2545 // Check that the object isn't a smi. | 2740 // Check that the object isn't a smi. |
2546 __ JumpIfSmi(edx, &miss); | 2741 __ JumpIfSmi(edx, &miss); |
2547 | 2742 |
2548 // Check that the map of the object hasn't changed. | 2743 // Check that the map of the object hasn't changed. |
2549 __ cmp(FieldOperand(edx, HeapObject::kMapOffset), | 2744 __ cmp(FieldOperand(edx, HeapObject::kMapOffset), |
2550 Immediate(Handle<Map>(object->map()))); | 2745 Immediate(Handle<Map>(object->map()))); |
2551 __ j(not_equal, &miss); | 2746 __ j(not_equal, &miss); |
2552 | 2747 |
2553 // Perform global security token check if needed. | 2748 // Perform global security token check if needed. |
2554 if (object->IsJSGlobalProxy()) { | 2749 if (object->IsJSGlobalProxy()) { |
2555 __ CheckAccessGlobalProxy(edx, ebx, &miss); | 2750 __ CheckAccessGlobalProxy(edx, ebx, &miss); |
2556 } | 2751 } |
2557 | 2752 |
2558 // Stub never generated for non-global objects that require access | 2753 // Stub never generated for non-global objects that require access |
2559 // checks. | 2754 // checks. |
2560 ASSERT(object->IsJSGlobalProxy() || !object->IsAccessCheckNeeded()); | 2755 ASSERT(object->IsJSGlobalProxy() || !object->IsAccessCheckNeeded()); |
2561 | 2756 |
2562 __ pop(ebx); // remove the return address | 2757 __ pop(ebx); // remove the return address |
2563 __ push(edx); // receiver | 2758 __ push(edx); // receiver |
2564 __ push(Immediate(Handle<AccessorInfo>(callback))); // callback info | 2759 __ push(Immediate(callback)); // callback info |
2565 __ push(ecx); // name | 2760 __ push(ecx); // name |
2566 __ push(eax); // value | 2761 __ push(eax); // value |
2567 __ push(ebx); // restore return address | 2762 __ push(ebx); // restore return address |
2568 | 2763 |
2569 // Do tail-call to the runtime system. | 2764 // Do tail-call to the runtime system. |
2570 ExternalReference store_callback_property = | 2765 ExternalReference store_callback_property = |
2571 ExternalReference(IC_Utility(IC::kStoreCallbackProperty), isolate()); | 2766 ExternalReference(IC_Utility(IC::kStoreCallbackProperty), isolate()); |
2572 __ TailCallExternalReference(store_callback_property, 4, 1); | 2767 __ TailCallExternalReference(store_callback_property, 4, 1); |
2573 | 2768 |
2574 // Handle store cache miss. | 2769 // Handle store cache miss. |
2575 __ bind(&miss); | 2770 __ bind(&miss); |
2576 Handle<Code> ic = isolate()->builtins()->StoreIC_Miss(); | 2771 Handle<Code> ic = isolate()->builtins()->StoreIC_Miss(); |
2577 __ jmp(ic, RelocInfo::CODE_TARGET); | 2772 __ jmp(ic, RelocInfo::CODE_TARGET); |
2578 | 2773 |
2579 // Return the generated code. | 2774 // Return the generated code. |
2580 return GetCode(CALLBACKS, name); | 2775 return GetCode(CALLBACKS, name); |
2581 } | 2776 } |
2582 | 2777 |
2583 | 2778 |
2584 MaybeObject* StoreStubCompiler::CompileStoreInterceptor(JSObject* receiver, | 2779 Handle<Code> StoreStubCompiler::CompileStoreInterceptor( |
2585 String* name) { | 2780 Handle<JSObject> receiver, |
| 2781 Handle<String> name) { |
2586 // ----------- S t a t e ------------- | 2782 // ----------- S t a t e ------------- |
2587 // -- eax : value | 2783 // -- eax : value |
2588 // -- ecx : name | 2784 // -- ecx : name |
2589 // -- edx : receiver | 2785 // -- edx : receiver |
2590 // -- esp[0] : return address | 2786 // -- esp[0] : return address |
2591 // ----------------------------------- | 2787 // ----------------------------------- |
2592 Label miss; | 2788 Label miss; |
2593 | 2789 |
2594 // Check that the object isn't a smi. | 2790 // Check that the object isn't a smi. |
2595 __ JumpIfSmi(edx, &miss); | 2791 __ JumpIfSmi(edx, &miss); |
(...skipping 27 matching lines...) Expand all Loading... |
2623 // Handle store cache miss. | 2819 // Handle store cache miss. |
2624 __ bind(&miss); | 2820 __ bind(&miss); |
2625 Handle<Code> ic = isolate()->builtins()->StoreIC_Miss(); | 2821 Handle<Code> ic = isolate()->builtins()->StoreIC_Miss(); |
2626 __ jmp(ic, RelocInfo::CODE_TARGET); | 2822 __ jmp(ic, RelocInfo::CODE_TARGET); |
2627 | 2823 |
2628 // Return the generated code. | 2824 // Return the generated code. |
2629 return GetCode(INTERCEPTOR, name); | 2825 return GetCode(INTERCEPTOR, name); |
2630 } | 2826 } |
2631 | 2827 |
2632 | 2828 |
2633 MaybeObject* StoreStubCompiler::CompileStoreGlobal(GlobalObject* object, | 2829 Handle<Code> StoreStubCompiler::CompileStoreGlobal( |
2634 JSGlobalPropertyCell* cell, | 2830 Handle<GlobalObject> object, |
2635 String* name) { | 2831 Handle<JSGlobalPropertyCell> cell, |
| 2832 Handle<String> name) { |
2636 // ----------- S t a t e ------------- | 2833 // ----------- S t a t e ------------- |
2637 // -- eax : value | 2834 // -- eax : value |
2638 // -- ecx : name | 2835 // -- ecx : name |
2639 // -- edx : receiver | 2836 // -- edx : receiver |
2640 // -- esp[0] : return address | 2837 // -- esp[0] : return address |
2641 // ----------------------------------- | 2838 // ----------------------------------- |
2642 Label miss; | 2839 Label miss; |
2643 | 2840 |
2644 // Check that the map of the global has not changed. | 2841 // Check that the map of the global has not changed. |
2645 __ cmp(FieldOperand(edx, HeapObject::kMapOffset), | 2842 __ cmp(FieldOperand(edx, HeapObject::kMapOffset), |
2646 Immediate(Handle<Map>(object->map()))); | 2843 Immediate(Handle<Map>(object->map()))); |
2647 __ j(not_equal, &miss); | 2844 __ j(not_equal, &miss); |
2648 | 2845 |
2649 // Compute the cell operand to use. | 2846 // Compute the cell operand to use. |
2650 __ mov(ebx, Immediate(Handle<JSGlobalPropertyCell>(cell))); | 2847 __ mov(ebx, Immediate(cell)); |
2651 Operand cell_operand = FieldOperand(ebx, JSGlobalPropertyCell::kValueOffset); | 2848 Operand cell_operand = FieldOperand(ebx, JSGlobalPropertyCell::kValueOffset); |
2652 | 2849 |
2653 // Check that the value in the cell is not the hole. If it is, this | 2850 // Check that the value in the cell is not the hole. If it is, this |
2654 // cell could have been deleted and reintroducing the global needs | 2851 // cell could have been deleted and reintroducing the global needs |
2655 // to update the property details in the property dictionary of the | 2852 // to update the property details in the property dictionary of the |
2656 // global object. We bail out to the runtime system to do that. | 2853 // global object. We bail out to the runtime system to do that. |
2657 __ cmp(cell_operand, factory()->the_hole_value()); | 2854 __ cmp(cell_operand, factory()->the_hole_value()); |
2658 __ j(equal, &miss); | 2855 __ j(equal, &miss); |
2659 | 2856 |
2660 // Store the value in the cell. | 2857 // Store the value in the cell. |
(...skipping 23 matching lines...) Expand all Loading... |
2684 __ bind(&miss); | 2881 __ bind(&miss); |
2685 __ IncrementCounter(counters->named_store_global_inline_miss(), 1); | 2882 __ IncrementCounter(counters->named_store_global_inline_miss(), 1); |
2686 Handle<Code> ic = isolate()->builtins()->StoreIC_Miss(); | 2883 Handle<Code> ic = isolate()->builtins()->StoreIC_Miss(); |
2687 __ jmp(ic, RelocInfo::CODE_TARGET); | 2884 __ jmp(ic, RelocInfo::CODE_TARGET); |
2688 | 2885 |
2689 // Return the generated code. | 2886 // Return the generated code. |
2690 return GetCode(NORMAL, name); | 2887 return GetCode(NORMAL, name); |
2691 } | 2888 } |
2692 | 2889 |
2693 | 2890 |
2694 MaybeObject* KeyedStoreStubCompiler::CompileStoreField(JSObject* object, | 2891 Handle<Code> KeyedStoreStubCompiler::CompileStoreField(Handle<JSObject> object, |
2695 int index, | 2892 int index, |
2696 Map* transition, | 2893 Handle<Map> transition, |
2697 String* name) { | 2894 Handle<String> name) { |
2698 // ----------- S t a t e ------------- | 2895 // ----------- S t a t e ------------- |
2699 // -- eax : value | 2896 // -- eax : value |
2700 // -- ecx : key | 2897 // -- ecx : key |
2701 // -- edx : receiver | 2898 // -- edx : receiver |
2702 // -- esp[0] : return address | 2899 // -- esp[0] : return address |
2703 // ----------------------------------- | 2900 // ----------------------------------- |
2704 Label miss; | 2901 Label miss; |
2705 | 2902 |
2706 Counters* counters = isolate()->counters(); | 2903 Counters* counters = isolate()->counters(); |
2707 __ IncrementCounter(counters->keyed_store_field(), 1); | 2904 __ IncrementCounter(counters->keyed_store_field(), 1); |
2708 | 2905 |
2709 // Check that the name has not changed. | 2906 // Check that the name has not changed. |
2710 __ cmp(ecx, Immediate(Handle<String>(name))); | 2907 __ cmp(ecx, Immediate(name)); |
2711 __ j(not_equal, &miss); | 2908 __ j(not_equal, &miss); |
2712 | 2909 |
2713 // Generate store field code. Trashes the name register. | 2910 // Generate store field code. Trashes the name register. |
2714 GenerateStoreField(masm(), | 2911 GenerateStoreField(masm(), object, index, transition, edx, ecx, ebx, &miss); |
2715 object, | |
2716 index, | |
2717 transition, | |
2718 edx, ecx, ebx, | |
2719 &miss); | |
2720 | 2912 |
2721 // Handle store cache miss. | 2913 // Handle store cache miss. |
2722 __ bind(&miss); | 2914 __ bind(&miss); |
2723 __ DecrementCounter(counters->keyed_store_field(), 1); | 2915 __ DecrementCounter(counters->keyed_store_field(), 1); |
2724 Handle<Code> ic = isolate()->builtins()->KeyedStoreIC_Miss(); | 2916 Handle<Code> ic = isolate()->builtins()->KeyedStoreIC_Miss(); |
2725 __ jmp(ic, RelocInfo::CODE_TARGET); | 2917 __ jmp(ic, RelocInfo::CODE_TARGET); |
2726 | 2918 |
2727 // Return the generated code. | 2919 // Return the generated code. |
2728 return GetCode(transition == NULL ? FIELD : MAP_TRANSITION, name); | 2920 return GetCode(transition.is_null() ? FIELD : MAP_TRANSITION, name); |
2729 } | 2921 } |
2730 | 2922 |
2731 | 2923 |
2732 MaybeObject* KeyedStoreStubCompiler::CompileStoreElement(Map* receiver_map) { | 2924 Handle<Code> KeyedStoreStubCompiler::CompileStoreElement( |
| 2925 Handle<Map> receiver_map) { |
2733 // ----------- S t a t e ------------- | 2926 // ----------- S t a t e ------------- |
2734 // -- eax : value | 2927 // -- eax : value |
2735 // -- ecx : key | 2928 // -- ecx : key |
2736 // -- edx : receiver | 2929 // -- edx : receiver |
2737 // -- esp[0] : return address | 2930 // -- esp[0] : return address |
2738 // ----------------------------------- | 2931 // ----------------------------------- |
2739 Code* stub; | |
2740 ElementsKind elements_kind = receiver_map->elements_kind(); | 2932 ElementsKind elements_kind = receiver_map->elements_kind(); |
2741 bool is_jsarray = receiver_map->instance_type() == JS_ARRAY_TYPE; | 2933 bool is_jsarray = receiver_map->instance_type() == JS_ARRAY_TYPE; |
2742 MaybeObject* maybe_stub = | 2934 Handle<Code> stub = |
2743 KeyedStoreElementStub(is_jsarray, elements_kind).TryGetCode(); | 2935 KeyedStoreElementStub(is_jsarray, elements_kind).GetCode(); |
2744 if (!maybe_stub->To(&stub)) return maybe_stub; | 2936 |
2745 __ DispatchMap(edx, | 2937 __ DispatchMap(edx, receiver_map, stub, DO_SMI_CHECK); |
2746 Handle<Map>(receiver_map), | |
2747 Handle<Code>(stub), | |
2748 DO_SMI_CHECK); | |
2749 | 2938 |
2750 Handle<Code> ic = isolate()->builtins()->KeyedStoreIC_Miss(); | 2939 Handle<Code> ic = isolate()->builtins()->KeyedStoreIC_Miss(); |
2751 __ jmp(ic, RelocInfo::CODE_TARGET); | 2940 __ jmp(ic, RelocInfo::CODE_TARGET); |
2752 | 2941 |
2753 // Return the generated code. | 2942 // Return the generated code. |
2754 return GetCode(NORMAL, NULL); | 2943 return GetCode(NORMAL, factory()->empty_string()); |
2755 } | 2944 } |
2756 | 2945 |
2757 | 2946 |
2758 MaybeObject* KeyedStoreStubCompiler::CompileStorePolymorphic( | 2947 Handle<Code> KeyedStoreStubCompiler::CompileStorePolymorphic( |
2759 MapList* receiver_maps, | 2948 MapHandleList* receiver_maps, |
2760 CodeList* handler_stubs, | 2949 CodeHandleList* handler_stubs, |
2761 MapList* transitioned_maps) { | 2950 MapHandleList* transitioned_maps) { |
2762 // ----------- S t a t e ------------- | 2951 // ----------- S t a t e ------------- |
2763 // -- eax : value | 2952 // -- eax : value |
2764 // -- ecx : key | 2953 // -- ecx : key |
2765 // -- edx : receiver | 2954 // -- edx : receiver |
2766 // -- esp[0] : return address | 2955 // -- esp[0] : return address |
2767 // ----------------------------------- | 2956 // ----------------------------------- |
2768 Label miss; | 2957 Label miss; |
2769 __ JumpIfSmi(edx, &miss, Label::kNear); | 2958 __ JumpIfSmi(edx, &miss, Label::kNear); |
2770 __ mov(edi, FieldOperand(edx, HeapObject::kMapOffset)); | 2959 __ mov(edi, FieldOperand(edx, HeapObject::kMapOffset)); |
2771 // ebx: receiver->map(). | 2960 // ebx: receiver->map(). |
2772 for (int i = 0; i < receiver_maps->length(); ++i) { | 2961 for (int i = 0; i < receiver_maps->length(); ++i) { |
2773 Handle<Map> map(receiver_maps->at(i)); | 2962 __ cmp(edi, receiver_maps->at(i)); |
2774 __ cmp(edi, map); | 2963 if (transitioned_maps->at(i).is_null()) { |
2775 if (transitioned_maps->at(i) == NULL) { | 2964 __ j(equal, handler_stubs->at(i)); |
2776 __ j(equal, Handle<Code>(handler_stubs->at(i))); | |
2777 } else { | 2965 } else { |
2778 Label next_map; | 2966 Label next_map; |
2779 __ j(not_equal, &next_map, Label::kNear); | 2967 __ j(not_equal, &next_map, Label::kNear); |
2780 __ mov(ebx, Immediate(Handle<Map>(transitioned_maps->at(i)))); | 2968 __ mov(ebx, Immediate(transitioned_maps->at(i))); |
2781 __ jmp(Handle<Code>(handler_stubs->at(i)), RelocInfo::CODE_TARGET); | 2969 __ jmp(handler_stubs->at(i), RelocInfo::CODE_TARGET); |
2782 __ bind(&next_map); | 2970 __ bind(&next_map); |
2783 } | 2971 } |
2784 } | 2972 } |
2785 __ bind(&miss); | 2973 __ bind(&miss); |
2786 Handle<Code> miss_ic = isolate()->builtins()->KeyedStoreIC_Miss(); | 2974 Handle<Code> miss_ic = isolate()->builtins()->KeyedStoreIC_Miss(); |
2787 __ jmp(miss_ic, RelocInfo::CODE_TARGET); | 2975 __ jmp(miss_ic, RelocInfo::CODE_TARGET); |
2788 | 2976 |
2789 // Return the generated code. | 2977 // Return the generated code. |
2790 return GetCode(NORMAL, NULL, MEGAMORPHIC); | 2978 return GetCode(NORMAL, factory()->empty_string(), MEGAMORPHIC); |
2791 } | 2979 } |
2792 | 2980 |
2793 | 2981 |
2794 MaybeObject* LoadStubCompiler::CompileLoadNonexistent(String* name, | 2982 Handle<Code> LoadStubCompiler::CompileLoadNonexistent(Handle<String> name, |
2795 JSObject* object, | 2983 Handle<JSObject> object, |
2796 JSObject* last) { | 2984 Handle<JSObject> last) { |
2797 // ----------- S t a t e ------------- | 2985 // ----------- S t a t e ------------- |
2798 // -- eax : receiver | 2986 // -- eax : receiver |
2799 // -- ecx : name | 2987 // -- ecx : name |
2800 // -- esp[0] : return address | 2988 // -- esp[0] : return address |
2801 // ----------------------------------- | 2989 // ----------------------------------- |
2802 Label miss; | 2990 Label miss; |
2803 | 2991 |
2804 // Check that the receiver isn't a smi. | 2992 // Check that the receiver isn't a smi. |
2805 __ JumpIfSmi(eax, &miss); | 2993 __ JumpIfSmi(eax, &miss); |
2806 | 2994 |
2807 ASSERT(last->IsGlobalObject() || last->HasFastProperties()); | 2995 ASSERT(last->IsGlobalObject() || last->HasFastProperties()); |
2808 | 2996 |
2809 // Check the maps of the full prototype chain. Also check that | 2997 // Check the maps of the full prototype chain. Also check that |
2810 // global property cells up to (but not including) the last object | 2998 // global property cells up to (but not including) the last object |
2811 // in the prototype chain are empty. | 2999 // in the prototype chain are empty. |
2812 CheckPrototypes(object, eax, last, ebx, edx, edi, name, &miss); | 3000 CheckPrototypes(object, eax, last, ebx, edx, edi, name, &miss); |
2813 | 3001 |
2814 // If the last object in the prototype chain is a global object, | 3002 // If the last object in the prototype chain is a global object, |
2815 // check that the global property cell is empty. | 3003 // check that the global property cell is empty. |
2816 if (last->IsGlobalObject()) { | 3004 if (last->IsGlobalObject()) { |
2817 MaybeObject* cell = GenerateCheckPropertyCell(masm(), | 3005 GenerateCheckPropertyCell( |
2818 GlobalObject::cast(last), | 3006 masm(), Handle<GlobalObject>::cast(last), name, edx, &miss); |
2819 name, | |
2820 edx, | |
2821 &miss); | |
2822 if (cell->IsFailure()) { | |
2823 miss.Unuse(); | |
2824 return cell; | |
2825 } | |
2826 } | 3007 } |
2827 | 3008 |
2828 // Return undefined if maps of the full prototype chain are still the | 3009 // Return undefined if maps of the full prototype chain are still the |
2829 // same and no global property with this name contains a value. | 3010 // same and no global property with this name contains a value. |
2830 __ mov(eax, isolate()->factory()->undefined_value()); | 3011 __ mov(eax, isolate()->factory()->undefined_value()); |
2831 __ ret(0); | 3012 __ ret(0); |
2832 | 3013 |
2833 __ bind(&miss); | 3014 __ bind(&miss); |
2834 GenerateLoadMiss(masm(), Code::LOAD_IC); | 3015 GenerateLoadMiss(masm(), Code::LOAD_IC); |
2835 | 3016 |
2836 // Return the generated code. | 3017 // Return the generated code. |
2837 return GetCode(NONEXISTENT, isolate()->heap()->empty_string()); | 3018 return GetCode(NONEXISTENT, factory()->empty_string()); |
2838 } | 3019 } |
2839 | 3020 |
2840 | 3021 |
2841 MaybeObject* LoadStubCompiler::CompileLoadField(JSObject* object, | 3022 Handle<Code> LoadStubCompiler::CompileLoadField(Handle<JSObject> object, |
2842 JSObject* holder, | 3023 Handle<JSObject> holder, |
2843 int index, | 3024 int index, |
2844 String* name) { | 3025 Handle<String> name) { |
2845 // ----------- S t a t e ------------- | 3026 // ----------- S t a t e ------------- |
2846 // -- eax : receiver | 3027 // -- eax : receiver |
2847 // -- ecx : name | 3028 // -- ecx : name |
2848 // -- esp[0] : return address | 3029 // -- esp[0] : return address |
2849 // ----------------------------------- | 3030 // ----------------------------------- |
2850 Label miss; | 3031 Label miss; |
2851 | 3032 |
2852 GenerateLoadField(object, holder, eax, ebx, edx, edi, index, name, &miss); | 3033 GenerateLoadField(object, holder, eax, ebx, edx, edi, index, name, &miss); |
2853 __ bind(&miss); | 3034 __ bind(&miss); |
2854 GenerateLoadMiss(masm(), Code::LOAD_IC); | 3035 GenerateLoadMiss(masm(), Code::LOAD_IC); |
(...skipping 18 matching lines...) Expand all Loading... |
2873 edi, callback, name, &miss); | 3054 edi, callback, name, &miss); |
2874 if (result->IsFailure()) { | 3055 if (result->IsFailure()) { |
2875 miss.Unuse(); | 3056 miss.Unuse(); |
2876 return result; | 3057 return result; |
2877 } | 3058 } |
2878 | 3059 |
2879 __ bind(&miss); | 3060 __ bind(&miss); |
2880 GenerateLoadMiss(masm(), Code::LOAD_IC); | 3061 GenerateLoadMiss(masm(), Code::LOAD_IC); |
2881 | 3062 |
2882 // Return the generated code. | 3063 // Return the generated code. |
2883 return GetCode(CALLBACKS, name); | 3064 return TryGetCode(CALLBACKS, name); |
2884 } | 3065 } |
2885 | 3066 |
2886 | 3067 |
2887 MaybeObject* LoadStubCompiler::CompileLoadConstant(JSObject* object, | 3068 Handle<Code> LoadStubCompiler::CompileLoadConstant(Handle<JSObject> object, |
2888 JSObject* holder, | 3069 Handle<JSObject> holder, |
2889 Object* value, | 3070 Handle<Object> value, |
2890 String* name) { | 3071 Handle<String> name) { |
2891 // ----------- S t a t e ------------- | 3072 // ----------- S t a t e ------------- |
2892 // -- eax : receiver | 3073 // -- eax : receiver |
2893 // -- ecx : name | 3074 // -- ecx : name |
2894 // -- esp[0] : return address | 3075 // -- esp[0] : return address |
2895 // ----------------------------------- | 3076 // ----------------------------------- |
2896 Label miss; | 3077 Label miss; |
2897 | 3078 |
2898 GenerateLoadConstant(object, holder, eax, ebx, edx, edi, value, name, &miss); | 3079 GenerateLoadConstant(object, holder, eax, ebx, edx, edi, value, name, &miss); |
2899 __ bind(&miss); | 3080 __ bind(&miss); |
2900 GenerateLoadMiss(masm(), Code::LOAD_IC); | 3081 GenerateLoadMiss(masm(), Code::LOAD_IC); |
2901 | 3082 |
2902 // Return the generated code. | 3083 // Return the generated code. |
2903 return GetCode(CONSTANT_FUNCTION, name); | 3084 return GetCode(CONSTANT_FUNCTION, name); |
2904 } | 3085 } |
2905 | 3086 |
2906 | 3087 |
2907 MaybeObject* LoadStubCompiler::CompileLoadInterceptor(JSObject* receiver, | 3088 MaybeObject* LoadStubCompiler::CompileLoadInterceptor(JSObject* receiver, |
2908 JSObject* holder, | 3089 JSObject* holder, |
2909 String* name) { | 3090 String* name) { |
2910 // ----------- S t a t e ------------- | 3091 // ----------- S t a t e ------------- |
2911 // -- eax : receiver | 3092 // -- eax : receiver |
2912 // -- ecx : name | 3093 // -- ecx : name |
2913 // -- esp[0] : return address | 3094 // -- esp[0] : return address |
2914 // ----------------------------------- | 3095 // ----------------------------------- |
2915 Label miss; | 3096 Label miss; |
2916 | 3097 |
2917 LookupResult lookup; | 3098 LookupResult lookup(isolate()); |
2918 LookupPostInterceptor(holder, name, &lookup); | 3099 LookupPostInterceptor(holder, name, &lookup); |
2919 | 3100 |
2920 // TODO(368): Compile in the whole chain: all the interceptors in | 3101 // TODO(368): Compile in the whole chain: all the interceptors in |
2921 // prototypes and ultimate answer. | 3102 // prototypes and ultimate answer. |
2922 GenerateLoadInterceptor(receiver, | 3103 GenerateLoadInterceptor(receiver, |
2923 holder, | 3104 holder, |
2924 &lookup, | 3105 &lookup, |
2925 eax, | 3106 eax, |
2926 ecx, | 3107 ecx, |
2927 edx, | 3108 edx, |
2928 ebx, | 3109 ebx, |
2929 edi, | 3110 edi, |
2930 name, | 3111 name, |
2931 &miss); | 3112 &miss); |
2932 | 3113 |
2933 __ bind(&miss); | 3114 __ bind(&miss); |
2934 GenerateLoadMiss(masm(), Code::LOAD_IC); | 3115 GenerateLoadMiss(masm(), Code::LOAD_IC); |
2935 | 3116 |
2936 // Return the generated code. | 3117 // Return the generated code. |
2937 return GetCode(INTERCEPTOR, name); | 3118 return TryGetCode(INTERCEPTOR, name); |
2938 } | 3119 } |
2939 | 3120 |
2940 | 3121 |
2941 MaybeObject* LoadStubCompiler::CompileLoadGlobal(JSObject* object, | 3122 Handle<Code> LoadStubCompiler::CompileLoadGlobal( |
2942 GlobalObject* holder, | 3123 Handle<JSObject> object, |
2943 JSGlobalPropertyCell* cell, | 3124 Handle<GlobalObject> holder, |
2944 String* name, | 3125 Handle<JSGlobalPropertyCell> cell, |
2945 bool is_dont_delete) { | 3126 Handle<String> name, |
| 3127 bool is_dont_delete) { |
2946 // ----------- S t a t e ------------- | 3128 // ----------- S t a t e ------------- |
2947 // -- eax : receiver | 3129 // -- eax : receiver |
2948 // -- ecx : name | 3130 // -- ecx : name |
2949 // -- esp[0] : return address | 3131 // -- esp[0] : return address |
2950 // ----------------------------------- | 3132 // ----------------------------------- |
2951 Label miss; | 3133 Label miss; |
2952 | 3134 |
2953 // If the object is the holder then we know that it's a global | 3135 // If the object is the holder then we know that it's a global |
2954 // object which can only happen for contextual loads. In this case, | 3136 // object which can only happen for contextual loads. In this case, |
2955 // the receiver cannot be a smi. | 3137 // the receiver cannot be a smi. |
2956 if (object != holder) { | 3138 if (!object.is_identical_to(holder)) { |
2957 __ JumpIfSmi(eax, &miss); | 3139 __ JumpIfSmi(eax, &miss); |
2958 } | 3140 } |
2959 | 3141 |
2960 // Check that the maps haven't changed. | 3142 // Check that the maps haven't changed. |
2961 CheckPrototypes(object, eax, holder, ebx, edx, edi, name, &miss); | 3143 CheckPrototypes(object, eax, holder, ebx, edx, edi, name, &miss); |
2962 | 3144 |
2963 // Get the value from the cell. | 3145 // Get the value from the cell. |
2964 if (Serializer::enabled()) { | 3146 if (Serializer::enabled()) { |
2965 __ mov(ebx, Immediate(Handle<JSGlobalPropertyCell>(cell))); | 3147 __ mov(ebx, Immediate(cell)); |
2966 __ mov(ebx, FieldOperand(ebx, JSGlobalPropertyCell::kValueOffset)); | 3148 __ mov(ebx, FieldOperand(ebx, JSGlobalPropertyCell::kValueOffset)); |
2967 } else { | 3149 } else { |
2968 __ mov(ebx, Operand::Cell(Handle<JSGlobalPropertyCell>(cell))); | 3150 __ mov(ebx, Operand::Cell(cell)); |
2969 } | 3151 } |
2970 | 3152 |
2971 // Check for deleted property if property can actually be deleted. | 3153 // Check for deleted property if property can actually be deleted. |
2972 if (!is_dont_delete) { | 3154 if (!is_dont_delete) { |
2973 __ cmp(ebx, factory()->the_hole_value()); | 3155 __ cmp(ebx, factory()->the_hole_value()); |
2974 __ j(equal, &miss); | 3156 __ j(equal, &miss); |
2975 } else if (FLAG_debug_code) { | 3157 } else if (FLAG_debug_code) { |
2976 __ cmp(ebx, factory()->the_hole_value()); | 3158 __ cmp(ebx, factory()->the_hole_value()); |
2977 __ Check(not_equal, "DontDelete cells can't contain the hole"); | 3159 __ Check(not_equal, "DontDelete cells can't contain the hole"); |
2978 } | 3160 } |
2979 | 3161 |
2980 Counters* counters = isolate()->counters(); | 3162 Counters* counters = isolate()->counters(); |
2981 __ IncrementCounter(counters->named_load_global_stub(), 1); | 3163 __ IncrementCounter(counters->named_load_global_stub(), 1); |
2982 __ mov(eax, ebx); | 3164 __ mov(eax, ebx); |
2983 __ ret(0); | 3165 __ ret(0); |
2984 | 3166 |
2985 __ bind(&miss); | 3167 __ bind(&miss); |
2986 __ IncrementCounter(counters->named_load_global_stub_miss(), 1); | 3168 __ IncrementCounter(counters->named_load_global_stub_miss(), 1); |
2987 GenerateLoadMiss(masm(), Code::LOAD_IC); | 3169 GenerateLoadMiss(masm(), Code::LOAD_IC); |
2988 | 3170 |
2989 // Return the generated code. | 3171 // Return the generated code. |
2990 return GetCode(NORMAL, name); | 3172 return GetCode(NORMAL, name); |
2991 } | 3173 } |
2992 | 3174 |
2993 | 3175 |
2994 MaybeObject* KeyedLoadStubCompiler::CompileLoadField(String* name, | 3176 Handle<Code> KeyedLoadStubCompiler::CompileLoadField(Handle<String> name, |
2995 JSObject* receiver, | 3177 Handle<JSObject> receiver, |
2996 JSObject* holder, | 3178 Handle<JSObject> holder, |
2997 int index) { | 3179 int index) { |
2998 // ----------- S t a t e ------------- | 3180 // ----------- S t a t e ------------- |
2999 // -- eax : key | 3181 // -- eax : key |
3000 // -- edx : receiver | 3182 // -- edx : receiver |
3001 // -- esp[0] : return address | 3183 // -- esp[0] : return address |
3002 // ----------------------------------- | 3184 // ----------------------------------- |
3003 Label miss; | 3185 Label miss; |
3004 | 3186 |
3005 Counters* counters = isolate()->counters(); | 3187 Counters* counters = isolate()->counters(); |
3006 __ IncrementCounter(counters->keyed_load_field(), 1); | 3188 __ IncrementCounter(counters->keyed_load_field(), 1); |
3007 | 3189 |
3008 // Check that the name has not changed. | 3190 // Check that the name has not changed. |
3009 __ cmp(eax, Immediate(Handle<String>(name))); | 3191 __ cmp(eax, Immediate(name)); |
3010 __ j(not_equal, &miss); | 3192 __ j(not_equal, &miss); |
3011 | 3193 |
3012 GenerateLoadField(receiver, holder, edx, ebx, ecx, edi, index, name, &miss); | 3194 GenerateLoadField(receiver, holder, edx, ebx, ecx, edi, index, name, &miss); |
3013 | 3195 |
3014 __ bind(&miss); | 3196 __ bind(&miss); |
3015 __ DecrementCounter(counters->keyed_load_field(), 1); | 3197 __ DecrementCounter(counters->keyed_load_field(), 1); |
3016 GenerateLoadMiss(masm(), Code::KEYED_LOAD_IC); | 3198 GenerateLoadMiss(masm(), Code::KEYED_LOAD_IC); |
3017 | 3199 |
3018 // Return the generated code. | 3200 // Return the generated code. |
3019 return GetCode(FIELD, name); | 3201 return GetCode(FIELD, name); |
(...skipping 25 matching lines...) Expand all Loading... |
3045 miss.Unuse(); | 3227 miss.Unuse(); |
3046 return result; | 3228 return result; |
3047 } | 3229 } |
3048 | 3230 |
3049 __ bind(&miss); | 3231 __ bind(&miss); |
3050 | 3232 |
3051 __ DecrementCounter(counters->keyed_load_callback(), 1); | 3233 __ DecrementCounter(counters->keyed_load_callback(), 1); |
3052 GenerateLoadMiss(masm(), Code::KEYED_LOAD_IC); | 3234 GenerateLoadMiss(masm(), Code::KEYED_LOAD_IC); |
3053 | 3235 |
3054 // Return the generated code. | 3236 // Return the generated code. |
3055 return GetCode(CALLBACKS, name); | 3237 return TryGetCode(CALLBACKS, name); |
3056 } | 3238 } |
3057 | 3239 |
3058 | 3240 |
3059 MaybeObject* KeyedLoadStubCompiler::CompileLoadConstant(String* name, | 3241 Handle<Code> KeyedLoadStubCompiler::CompileLoadConstant( |
3060 JSObject* receiver, | 3242 Handle<String> name, |
3061 JSObject* holder, | 3243 Handle<JSObject> receiver, |
3062 Object* value) { | 3244 Handle<JSObject> holder, |
| 3245 Handle<Object> value) { |
3063 // ----------- S t a t e ------------- | 3246 // ----------- S t a t e ------------- |
3064 // -- eax : key | 3247 // -- eax : key |
3065 // -- edx : receiver | 3248 // -- edx : receiver |
3066 // -- esp[0] : return address | 3249 // -- esp[0] : return address |
3067 // ----------------------------------- | 3250 // ----------------------------------- |
3068 Label miss; | 3251 Label miss; |
3069 | 3252 |
3070 Counters* counters = isolate()->counters(); | 3253 Counters* counters = isolate()->counters(); |
3071 __ IncrementCounter(counters->keyed_load_constant_function(), 1); | 3254 __ IncrementCounter(counters->keyed_load_constant_function(), 1); |
3072 | 3255 |
3073 // Check that the name has not changed. | 3256 // Check that the name has not changed. |
3074 __ cmp(eax, Immediate(Handle<String>(name))); | 3257 __ cmp(eax, Immediate(name)); |
3075 __ j(not_equal, &miss); | 3258 __ j(not_equal, &miss); |
3076 | 3259 |
3077 GenerateLoadConstant(receiver, holder, edx, ebx, ecx, edi, | 3260 GenerateLoadConstant( |
3078 value, name, &miss); | 3261 receiver, holder, edx, ebx, ecx, edi, value, name, &miss); |
3079 __ bind(&miss); | 3262 __ bind(&miss); |
3080 __ DecrementCounter(counters->keyed_load_constant_function(), 1); | 3263 __ DecrementCounter(counters->keyed_load_constant_function(), 1); |
3081 GenerateLoadMiss(masm(), Code::KEYED_LOAD_IC); | 3264 GenerateLoadMiss(masm(), Code::KEYED_LOAD_IC); |
3082 | 3265 |
3083 // Return the generated code. | 3266 // Return the generated code. |
3084 return GetCode(CONSTANT_FUNCTION, name); | 3267 return GetCode(CONSTANT_FUNCTION, name); |
3085 } | 3268 } |
3086 | 3269 |
3087 | 3270 |
3088 MaybeObject* KeyedLoadStubCompiler::CompileLoadInterceptor(JSObject* receiver, | 3271 MaybeObject* KeyedLoadStubCompiler::CompileLoadInterceptor(JSObject* receiver, |
3089 JSObject* holder, | 3272 JSObject* holder, |
3090 String* name) { | 3273 String* name) { |
3091 // ----------- S t a t e ------------- | 3274 // ----------- S t a t e ------------- |
3092 // -- eax : key | 3275 // -- eax : key |
3093 // -- edx : receiver | 3276 // -- edx : receiver |
3094 // -- esp[0] : return address | 3277 // -- esp[0] : return address |
3095 // ----------------------------------- | 3278 // ----------------------------------- |
3096 Label miss; | 3279 Label miss; |
3097 | 3280 |
3098 Counters* counters = isolate()->counters(); | 3281 Counters* counters = isolate()->counters(); |
3099 __ IncrementCounter(counters->keyed_load_interceptor(), 1); | 3282 __ IncrementCounter(counters->keyed_load_interceptor(), 1); |
3100 | 3283 |
3101 // Check that the name has not changed. | 3284 // Check that the name has not changed. |
3102 __ cmp(eax, Immediate(Handle<String>(name))); | 3285 __ cmp(eax, Immediate(Handle<String>(name))); |
3103 __ j(not_equal, &miss); | 3286 __ j(not_equal, &miss); |
3104 | 3287 |
3105 LookupResult lookup; | 3288 LookupResult lookup(isolate()); |
3106 LookupPostInterceptor(holder, name, &lookup); | 3289 LookupPostInterceptor(holder, name, &lookup); |
3107 GenerateLoadInterceptor(receiver, | 3290 GenerateLoadInterceptor(receiver, |
3108 holder, | 3291 holder, |
3109 &lookup, | 3292 &lookup, |
3110 edx, | 3293 edx, |
3111 eax, | 3294 eax, |
3112 ecx, | 3295 ecx, |
3113 ebx, | 3296 ebx, |
3114 edi, | 3297 edi, |
3115 name, | 3298 name, |
3116 &miss); | 3299 &miss); |
3117 __ bind(&miss); | 3300 __ bind(&miss); |
3118 __ DecrementCounter(counters->keyed_load_interceptor(), 1); | 3301 __ DecrementCounter(counters->keyed_load_interceptor(), 1); |
3119 GenerateLoadMiss(masm(), Code::KEYED_LOAD_IC); | 3302 GenerateLoadMiss(masm(), Code::KEYED_LOAD_IC); |
3120 | 3303 |
3121 // Return the generated code. | 3304 // Return the generated code. |
3122 return GetCode(INTERCEPTOR, name); | 3305 return TryGetCode(INTERCEPTOR, name); |
3123 } | 3306 } |
3124 | 3307 |
3125 | 3308 |
3126 MaybeObject* KeyedLoadStubCompiler::CompileLoadArrayLength(String* name) { | 3309 Handle<Code> KeyedLoadStubCompiler::CompileLoadArrayLength( |
| 3310 Handle<String> name) { |
3127 // ----------- S t a t e ------------- | 3311 // ----------- S t a t e ------------- |
3128 // -- eax : key | 3312 // -- eax : key |
3129 // -- edx : receiver | 3313 // -- edx : receiver |
3130 // -- esp[0] : return address | 3314 // -- esp[0] : return address |
3131 // ----------------------------------- | 3315 // ----------------------------------- |
3132 Label miss; | 3316 Label miss; |
3133 | 3317 |
3134 Counters* counters = isolate()->counters(); | 3318 Counters* counters = isolate()->counters(); |
3135 __ IncrementCounter(counters->keyed_load_array_length(), 1); | 3319 __ IncrementCounter(counters->keyed_load_array_length(), 1); |
3136 | 3320 |
3137 // Check that the name has not changed. | 3321 // Check that the name has not changed. |
3138 __ cmp(eax, Immediate(Handle<String>(name))); | 3322 __ cmp(eax, Immediate(name)); |
3139 __ j(not_equal, &miss); | 3323 __ j(not_equal, &miss); |
3140 | 3324 |
3141 GenerateLoadArrayLength(masm(), edx, ecx, &miss); | 3325 GenerateLoadArrayLength(masm(), edx, ecx, &miss); |
3142 __ bind(&miss); | 3326 __ bind(&miss); |
3143 __ DecrementCounter(counters->keyed_load_array_length(), 1); | 3327 __ DecrementCounter(counters->keyed_load_array_length(), 1); |
3144 GenerateLoadMiss(masm(), Code::KEYED_LOAD_IC); | 3328 GenerateLoadMiss(masm(), Code::KEYED_LOAD_IC); |
3145 | 3329 |
3146 // Return the generated code. | 3330 // Return the generated code. |
3147 return GetCode(CALLBACKS, name); | 3331 return GetCode(CALLBACKS, name); |
3148 } | 3332 } |
3149 | 3333 |
3150 | 3334 |
3151 MaybeObject* KeyedLoadStubCompiler::CompileLoadStringLength(String* name) { | 3335 Handle<Code> KeyedLoadStubCompiler::CompileLoadStringLength( |
| 3336 Handle<String> name) { |
3152 // ----------- S t a t e ------------- | 3337 // ----------- S t a t e ------------- |
3153 // -- eax : key | 3338 // -- eax : key |
3154 // -- edx : receiver | 3339 // -- edx : receiver |
3155 // -- esp[0] : return address | 3340 // -- esp[0] : return address |
3156 // ----------------------------------- | 3341 // ----------------------------------- |
3157 Label miss; | 3342 Label miss; |
3158 | 3343 |
3159 Counters* counters = isolate()->counters(); | 3344 Counters* counters = isolate()->counters(); |
3160 __ IncrementCounter(counters->keyed_load_string_length(), 1); | 3345 __ IncrementCounter(counters->keyed_load_string_length(), 1); |
3161 | 3346 |
3162 // Check that the name has not changed. | 3347 // Check that the name has not changed. |
3163 __ cmp(eax, Immediate(Handle<String>(name))); | 3348 __ cmp(eax, Immediate(name)); |
3164 __ j(not_equal, &miss); | 3349 __ j(not_equal, &miss); |
3165 | 3350 |
3166 GenerateLoadStringLength(masm(), edx, ecx, ebx, &miss, true); | 3351 GenerateLoadStringLength(masm(), edx, ecx, ebx, &miss, true); |
3167 __ bind(&miss); | 3352 __ bind(&miss); |
3168 __ DecrementCounter(counters->keyed_load_string_length(), 1); | 3353 __ DecrementCounter(counters->keyed_load_string_length(), 1); |
3169 GenerateLoadMiss(masm(), Code::KEYED_LOAD_IC); | 3354 GenerateLoadMiss(masm(), Code::KEYED_LOAD_IC); |
3170 | 3355 |
3171 // Return the generated code. | 3356 // Return the generated code. |
3172 return GetCode(CALLBACKS, name); | 3357 return GetCode(CALLBACKS, name); |
3173 } | 3358 } |
3174 | 3359 |
3175 | 3360 |
3176 MaybeObject* KeyedLoadStubCompiler::CompileLoadFunctionPrototype(String* name) { | 3361 Handle<Code> KeyedLoadStubCompiler::CompileLoadFunctionPrototype( |
| 3362 Handle<String> name) { |
3177 // ----------- S t a t e ------------- | 3363 // ----------- S t a t e ------------- |
3178 // -- eax : key | 3364 // -- eax : key |
3179 // -- edx : receiver | 3365 // -- edx : receiver |
3180 // -- esp[0] : return address | 3366 // -- esp[0] : return address |
3181 // ----------------------------------- | 3367 // ----------------------------------- |
3182 Label miss; | 3368 Label miss; |
3183 | 3369 |
3184 Counters* counters = isolate()->counters(); | 3370 Counters* counters = isolate()->counters(); |
3185 __ IncrementCounter(counters->keyed_load_function_prototype(), 1); | 3371 __ IncrementCounter(counters->keyed_load_function_prototype(), 1); |
3186 | 3372 |
3187 // Check that the name has not changed. | 3373 // Check that the name has not changed. |
3188 __ cmp(eax, Immediate(Handle<String>(name))); | 3374 __ cmp(eax, Immediate(name)); |
3189 __ j(not_equal, &miss); | 3375 __ j(not_equal, &miss); |
3190 | 3376 |
3191 GenerateLoadFunctionPrototype(masm(), edx, ecx, ebx, &miss); | 3377 GenerateLoadFunctionPrototype(masm(), edx, ecx, ebx, &miss); |
3192 __ bind(&miss); | 3378 __ bind(&miss); |
3193 __ DecrementCounter(counters->keyed_load_function_prototype(), 1); | 3379 __ DecrementCounter(counters->keyed_load_function_prototype(), 1); |
3194 GenerateLoadMiss(masm(), Code::KEYED_LOAD_IC); | 3380 GenerateLoadMiss(masm(), Code::KEYED_LOAD_IC); |
3195 | 3381 |
3196 // Return the generated code. | 3382 // Return the generated code. |
3197 return GetCode(CALLBACKS, name); | 3383 return GetCode(CALLBACKS, name); |
3198 } | 3384 } |
3199 | 3385 |
3200 | 3386 |
3201 MaybeObject* KeyedLoadStubCompiler::CompileLoadElement(Map* receiver_map) { | 3387 Handle<Code> KeyedLoadStubCompiler::CompileLoadElement( |
| 3388 Handle<Map> receiver_map) { |
3202 // ----------- S t a t e ------------- | 3389 // ----------- S t a t e ------------- |
3203 // -- eax : key | 3390 // -- eax : key |
3204 // -- edx : receiver | 3391 // -- edx : receiver |
3205 // -- esp[0] : return address | 3392 // -- esp[0] : return address |
3206 // ----------------------------------- | 3393 // ----------------------------------- |
3207 Code* stub; | 3394 |
3208 ElementsKind elements_kind = receiver_map->elements_kind(); | 3395 ElementsKind elements_kind = receiver_map->elements_kind(); |
3209 MaybeObject* maybe_stub = KeyedLoadElementStub(elements_kind).TryGetCode(); | 3396 Handle<Code> stub = KeyedLoadElementStub(elements_kind).GetCode(); |
3210 if (!maybe_stub->To(&stub)) return maybe_stub; | 3397 |
3211 __ DispatchMap(edx, | 3398 __ DispatchMap(edx, receiver_map, stub, DO_SMI_CHECK); |
3212 Handle<Map>(receiver_map), | |
3213 Handle<Code>(stub), | |
3214 DO_SMI_CHECK); | |
3215 | 3399 |
3216 GenerateLoadMiss(masm(), Code::KEYED_LOAD_IC); | 3400 GenerateLoadMiss(masm(), Code::KEYED_LOAD_IC); |
3217 | 3401 |
3218 // Return the generated code. | 3402 // Return the generated code. |
3219 return GetCode(NORMAL, NULL); | 3403 return GetCode(NORMAL, factory()->empty_string()); |
3220 } | 3404 } |
3221 | 3405 |
3222 | 3406 |
3223 MaybeObject* KeyedLoadStubCompiler::CompileLoadPolymorphic( | 3407 Handle<Code> KeyedLoadStubCompiler::CompileLoadPolymorphic( |
3224 MapList* receiver_maps, | 3408 MapHandleList* receiver_maps, |
3225 CodeList* handler_ics) { | 3409 CodeHandleList* handler_ics) { |
3226 // ----------- S t a t e ------------- | 3410 // ----------- S t a t e ------------- |
3227 // -- eax : key | 3411 // -- eax : key |
3228 // -- edx : receiver | 3412 // -- edx : receiver |
3229 // -- esp[0] : return address | 3413 // -- esp[0] : return address |
3230 // ----------------------------------- | 3414 // ----------------------------------- |
3231 Label miss; | 3415 Label miss; |
3232 __ JumpIfSmi(edx, &miss); | 3416 __ JumpIfSmi(edx, &miss); |
3233 | 3417 |
3234 Register map_reg = ebx; | 3418 Register map_reg = ebx; |
3235 __ mov(map_reg, FieldOperand(edx, HeapObject::kMapOffset)); | 3419 __ mov(map_reg, FieldOperand(edx, HeapObject::kMapOffset)); |
3236 int receiver_count = receiver_maps->length(); | 3420 int receiver_count = receiver_maps->length(); |
3237 for (int current = 0; current < receiver_count; ++current) { | 3421 for (int current = 0; current < receiver_count; ++current) { |
3238 Handle<Map> map(receiver_maps->at(current)); | 3422 __ cmp(map_reg, receiver_maps->at(current)); |
3239 __ cmp(map_reg, map); | 3423 __ j(equal, handler_ics->at(current)); |
3240 __ j(equal, Handle<Code>(handler_ics->at(current))); | |
3241 } | 3424 } |
3242 | 3425 |
3243 __ bind(&miss); | 3426 __ bind(&miss); |
3244 GenerateLoadMiss(masm(), Code::KEYED_LOAD_IC); | 3427 GenerateLoadMiss(masm(), Code::KEYED_LOAD_IC); |
3245 | 3428 |
3246 // Return the generated code. | 3429 // Return the generated code. |
3247 return GetCode(NORMAL, NULL, MEGAMORPHIC); | 3430 return GetCode(NORMAL, factory()->empty_string(), MEGAMORPHIC); |
3248 } | 3431 } |
3249 | 3432 |
3250 | 3433 |
3251 // Specialized stub for constructing objects from functions which only have only | 3434 // Specialized stub for constructing objects from functions which only have only |
3252 // simple assignments of the form this.x = ...; in their body. | 3435 // simple assignments of the form this.x = ...; in their body. |
3253 MaybeObject* ConstructStubCompiler::CompileConstructStub(JSFunction* function) { | 3436 MaybeObject* ConstructStubCompiler::CompileConstructStub(JSFunction* function) { |
3254 // ----------- S t a t e ------------- | 3437 // ----------- S t a t e ------------- |
3255 // -- eax : argc | 3438 // -- eax : argc |
3256 // -- edi : constructor | 3439 // -- edi : constructor |
3257 // -- esp[0] : return address | 3440 // -- esp[0] : return address |
(...skipping 768 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
4026 Handle<Code> ic_miss = masm->isolate()->builtins()->KeyedStoreIC_Miss(); | 4209 Handle<Code> ic_miss = masm->isolate()->builtins()->KeyedStoreIC_Miss(); |
4027 __ jmp(ic_miss, RelocInfo::CODE_TARGET); | 4210 __ jmp(ic_miss, RelocInfo::CODE_TARGET); |
4028 } | 4211 } |
4029 | 4212 |
4030 | 4213 |
4031 #undef __ | 4214 #undef __ |
4032 | 4215 |
4033 } } // namespace v8::internal | 4216 } } // namespace v8::internal |
4034 | 4217 |
4035 #endif // V8_TARGET_ARCH_IA32 | 4218 #endif // V8_TARGET_ARCH_IA32 |
OLD | NEW |