OLD | NEW |
1 // Copyright 2013 the V8 project authors. All rights reserved. | 1 // Copyright 2013 the V8 project authors. All rights reserved. |
2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 #include "src/v8.h" | 5 #include "src/v8.h" |
6 | 6 |
7 #if V8_TARGET_ARCH_ARM64 | 7 #if V8_TARGET_ARCH_ARM64 |
8 | 8 |
9 #include "src/codegen.h" | 9 #include "src/codegen.h" |
10 #include "src/ic-inl.h" | 10 #include "src/ic-inl.h" |
11 #include "src/stub-cache.h" | 11 #include "src/stub-cache.h" |
12 | 12 |
13 namespace v8 { | 13 namespace v8 { |
14 namespace internal { | 14 namespace internal { |
15 | 15 |
16 | 16 |
17 #define __ ACCESS_MASM(masm) | 17 #define __ ACCESS_MASM(masm) |
18 | 18 |
19 | 19 |
20 void StubCompiler::GenerateDictionaryNegativeLookup(MacroAssembler* masm, | 20 void PropertyHandlerCompiler::GenerateDictionaryNegativeLookup( |
21 Label* miss_label, | 21 MacroAssembler* masm, Label* miss_label, Register receiver, |
22 Register receiver, | 22 Handle<Name> name, Register scratch0, Register scratch1) { |
23 Handle<Name> name, | |
24 Register scratch0, | |
25 Register scratch1) { | |
26 ASSERT(!AreAliased(receiver, scratch0, scratch1)); | 23 ASSERT(!AreAliased(receiver, scratch0, scratch1)); |
27 ASSERT(name->IsUniqueName()); | 24 ASSERT(name->IsUniqueName()); |
28 Counters* counters = masm->isolate()->counters(); | 25 Counters* counters = masm->isolate()->counters(); |
29 __ IncrementCounter(counters->negative_lookups(), 1, scratch0, scratch1); | 26 __ IncrementCounter(counters->negative_lookups(), 1, scratch0, scratch1); |
30 __ IncrementCounter(counters->negative_lookups_miss(), 1, scratch0, scratch1); | 27 __ IncrementCounter(counters->negative_lookups_miss(), 1, scratch0, scratch1); |
31 | 28 |
32 Label done; | 29 Label done; |
33 | 30 |
34 const int kInterceptorOrAccessCheckNeededMask = | 31 const int kInterceptorOrAccessCheckNeededMask = |
35 (1 << Map::kHasNamedInterceptor) | (1 << Map::kIsAccessCheckNeeded); | 32 (1 << Map::kHasNamedInterceptor) | (1 << Map::kIsAccessCheckNeeded); |
(...skipping 158 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
194 scratch, extra, extra2, extra3); | 191 scratch, extra, extra2, extra3); |
195 | 192 |
196 // Cache miss: Fall-through and let caller handle the miss by | 193 // Cache miss: Fall-through and let caller handle the miss by |
197 // entering the runtime system. | 194 // entering the runtime system. |
198 __ Bind(&miss); | 195 __ Bind(&miss); |
199 __ IncrementCounter(counters->megamorphic_stub_cache_misses(), 1, | 196 __ IncrementCounter(counters->megamorphic_stub_cache_misses(), 1, |
200 extra2, extra3); | 197 extra2, extra3); |
201 } | 198 } |
202 | 199 |
203 | 200 |
204 void StubCompiler::GenerateLoadGlobalFunctionPrototype(MacroAssembler* masm, | 201 void NamedLoadHandlerCompiler::GenerateDirectLoadGlobalFunctionPrototype( |
205 int index, | 202 MacroAssembler* masm, int index, Register prototype, Label* miss) { |
206 Register prototype) { | |
207 // Load the global or builtins object from the current context. | |
208 __ Ldr(prototype, GlobalObjectMemOperand()); | |
209 // Load the native context from the global or builtins object. | |
210 __ Ldr(prototype, | |
211 FieldMemOperand(prototype, GlobalObject::kNativeContextOffset)); | |
212 // Load the function from the native context. | |
213 __ Ldr(prototype, ContextMemOperand(prototype, index)); | |
214 // Load the initial map. The global functions all have initial maps. | |
215 __ Ldr(prototype, | |
216 FieldMemOperand(prototype, JSFunction::kPrototypeOrInitialMapOffset)); | |
217 // Load the prototype from the initial map. | |
218 __ Ldr(prototype, FieldMemOperand(prototype, Map::kPrototypeOffset)); | |
219 } | |
220 | |
221 | |
222 void StubCompiler::GenerateDirectLoadGlobalFunctionPrototype( | |
223 MacroAssembler* masm, | |
224 int index, | |
225 Register prototype, | |
226 Label* miss) { | |
227 Isolate* isolate = masm->isolate(); | 203 Isolate* isolate = masm->isolate(); |
228 // Get the global function with the given index. | 204 // Get the global function with the given index. |
229 Handle<JSFunction> function( | 205 Handle<JSFunction> function( |
230 JSFunction::cast(isolate->native_context()->get(index))); | 206 JSFunction::cast(isolate->native_context()->get(index))); |
231 | 207 |
232 // Check we're still in the same context. | 208 // Check we're still in the same context. |
233 Register scratch = prototype; | 209 Register scratch = prototype; |
234 __ Ldr(scratch, GlobalObjectMemOperand()); | 210 __ Ldr(scratch, GlobalObjectMemOperand()); |
235 __ Ldr(scratch, FieldMemOperand(scratch, GlobalObject::kNativeContextOffset)); | 211 __ Ldr(scratch, FieldMemOperand(scratch, GlobalObject::kNativeContextOffset)); |
236 __ Ldr(scratch, ContextMemOperand(scratch, index)); | 212 __ Ldr(scratch, ContextMemOperand(scratch, index)); |
237 __ Cmp(scratch, Operand(function)); | 213 __ Cmp(scratch, Operand(function)); |
238 __ B(ne, miss); | 214 __ B(ne, miss); |
239 | 215 |
240 // Load its initial map. The global functions all have initial maps. | 216 // Load its initial map. The global functions all have initial maps. |
241 __ Mov(prototype, Operand(Handle<Map>(function->initial_map()))); | 217 __ Mov(prototype, Operand(Handle<Map>(function->initial_map()))); |
242 // Load the prototype from the initial map. | 218 // Load the prototype from the initial map. |
243 __ Ldr(prototype, FieldMemOperand(prototype, Map::kPrototypeOffset)); | 219 __ Ldr(prototype, FieldMemOperand(prototype, Map::kPrototypeOffset)); |
244 } | 220 } |
245 | 221 |
246 | 222 |
247 void StubCompiler::GenerateFastPropertyLoad(MacroAssembler* masm, | 223 void NamedLoadHandlerCompiler::GenerateLoadFunctionPrototype( |
248 Register dst, | 224 MacroAssembler* masm, Register receiver, Register scratch1, |
249 Register src, | 225 Register scratch2, Label* miss_label) { |
250 bool inobject, | |
251 int index, | |
252 Representation representation) { | |
253 ASSERT(!representation.IsDouble()); | |
254 USE(representation); | |
255 if (inobject) { | |
256 int offset = index * kPointerSize; | |
257 __ Ldr(dst, FieldMemOperand(src, offset)); | |
258 } else { | |
259 // Calculate the offset into the properties array. | |
260 int offset = index * kPointerSize + FixedArray::kHeaderSize; | |
261 __ Ldr(dst, FieldMemOperand(src, JSObject::kPropertiesOffset)); | |
262 __ Ldr(dst, FieldMemOperand(dst, offset)); | |
263 } | |
264 } | |
265 | |
266 | |
267 void StubCompiler::GenerateLoadArrayLength(MacroAssembler* masm, | |
268 Register receiver, | |
269 Register scratch, | |
270 Label* miss_label) { | |
271 ASSERT(!AreAliased(receiver, scratch)); | |
272 | |
273 // Check that the receiver isn't a smi. | |
274 __ JumpIfSmi(receiver, miss_label); | |
275 | |
276 // Check that the object is a JS array. | |
277 __ JumpIfNotObjectType(receiver, scratch, scratch, JS_ARRAY_TYPE, | |
278 miss_label); | |
279 | |
280 // Load length directly from the JS array. | |
281 __ Ldr(x0, FieldMemOperand(receiver, JSArray::kLengthOffset)); | |
282 __ Ret(); | |
283 } | |
284 | |
285 | |
286 void StubCompiler::GenerateLoadFunctionPrototype(MacroAssembler* masm, | |
287 Register receiver, | |
288 Register scratch1, | |
289 Register scratch2, | |
290 Label* miss_label) { | |
291 __ TryGetFunctionPrototype(receiver, scratch1, scratch2, miss_label); | 226 __ TryGetFunctionPrototype(receiver, scratch1, scratch2, miss_label); |
292 // TryGetFunctionPrototype can't put the result directly in x0 because the | 227 // TryGetFunctionPrototype can't put the result directly in x0 because the |
293 // 3 inputs registers can't alias and we call this function from | 228 // 3 inputs registers can't alias and we call this function from |
294 // LoadIC::GenerateFunctionPrototype, where receiver is x0. So we explicitly | 229 // LoadIC::GenerateFunctionPrototype, where receiver is x0. So we explicitly |
295 // move the result in x0. | 230 // move the result in x0. |
296 __ Mov(x0, scratch1); | 231 __ Mov(x0, scratch1); |
297 __ Ret(); | 232 __ Ret(); |
298 } | 233 } |
299 | 234 |
300 | 235 |
301 // Generate code to check that a global property cell is empty. Create | 236 // Generate code to check that a global property cell is empty. Create |
302 // the property cell at compilation time if no cell exists for the | 237 // the property cell at compilation time if no cell exists for the |
303 // property. | 238 // property. |
304 void StubCompiler::GenerateCheckPropertyCell(MacroAssembler* masm, | 239 void PropertyHandlerCompiler::GenerateCheckPropertyCell( |
305 Handle<JSGlobalObject> global, | 240 MacroAssembler* masm, Handle<JSGlobalObject> global, Handle<Name> name, |
306 Handle<Name> name, | 241 Register scratch, Label* miss) { |
307 Register scratch, | |
308 Label* miss) { | |
309 Handle<Cell> cell = JSGlobalObject::EnsurePropertyCell(global, name); | 242 Handle<Cell> cell = JSGlobalObject::EnsurePropertyCell(global, name); |
310 ASSERT(cell->value()->IsTheHole()); | 243 ASSERT(cell->value()->IsTheHole()); |
311 __ Mov(scratch, Operand(cell)); | 244 __ Mov(scratch, Operand(cell)); |
312 __ Ldr(scratch, FieldMemOperand(scratch, Cell::kValueOffset)); | 245 __ Ldr(scratch, FieldMemOperand(scratch, Cell::kValueOffset)); |
313 __ JumpIfNotRoot(scratch, Heap::kTheHoleValueRootIndex, miss); | 246 __ JumpIfNotRoot(scratch, Heap::kTheHoleValueRootIndex, miss); |
314 } | 247 } |
315 | 248 |
316 | 249 |
317 void StoreStubCompiler::GenerateNegativeHolderLookup( | 250 void NamedStoreHandlerCompiler::GenerateNegativeHolderLookup( |
318 MacroAssembler* masm, | 251 MacroAssembler* masm, Handle<JSObject> holder, Register holder_reg, |
319 Handle<JSObject> holder, | 252 Handle<Name> name, Label* miss) { |
320 Register holder_reg, | |
321 Handle<Name> name, | |
322 Label* miss) { | |
323 if (holder->IsJSGlobalObject()) { | 253 if (holder->IsJSGlobalObject()) { |
324 GenerateCheckPropertyCell( | 254 GenerateCheckPropertyCell( |
325 masm, Handle<JSGlobalObject>::cast(holder), name, scratch1(), miss); | 255 masm, Handle<JSGlobalObject>::cast(holder), name, scratch1(), miss); |
326 } else if (!holder->HasFastProperties() && !holder->IsJSGlobalProxy()) { | 256 } else if (!holder->HasFastProperties() && !holder->IsJSGlobalProxy()) { |
327 GenerateDictionaryNegativeLookup( | 257 GenerateDictionaryNegativeLookup( |
328 masm, miss, holder_reg, name, scratch1(), scratch2()); | 258 masm, miss, holder_reg, name, scratch1(), scratch2()); |
329 } | 259 } |
330 } | 260 } |
331 | 261 |
332 | 262 |
333 // Generate StoreTransition code, value is passed in x0 register. | 263 // Generate StoreTransition code, value is passed in x0 register. |
334 // When leaving generated code after success, the receiver_reg and storage_reg | 264 // When leaving generated code after success, the receiver_reg and storage_reg |
335 // may be clobbered. Upon branch to miss_label, the receiver and name registers | 265 // may be clobbered. Upon branch to miss_label, the receiver and name registers |
336 // have their original values. | 266 // have their original values. |
337 void StoreStubCompiler::GenerateStoreTransition(MacroAssembler* masm, | 267 void NamedStoreHandlerCompiler::GenerateStoreTransition( |
338 Handle<JSObject> object, | 268 MacroAssembler* masm, Handle<JSObject> object, LookupResult* lookup, |
339 LookupResult* lookup, | 269 Handle<Map> transition, Handle<Name> name, Register receiver_reg, |
340 Handle<Map> transition, | 270 Register storage_reg, Register value_reg, Register scratch1, |
341 Handle<Name> name, | 271 Register scratch2, Register scratch3, Label* miss_label, Label* slow) { |
342 Register receiver_reg, | |
343 Register storage_reg, | |
344 Register value_reg, | |
345 Register scratch1, | |
346 Register scratch2, | |
347 Register scratch3, | |
348 Label* miss_label, | |
349 Label* slow) { | |
350 Label exit; | 272 Label exit; |
351 | 273 |
352 ASSERT(!AreAliased(receiver_reg, storage_reg, value_reg, | 274 ASSERT(!AreAliased(receiver_reg, storage_reg, value_reg, |
353 scratch1, scratch2, scratch3)); | 275 scratch1, scratch2, scratch3)); |
354 | 276 |
355 // We don't need scratch3. | 277 // We don't need scratch3. |
356 scratch3 = NoReg; | 278 scratch3 = NoReg; |
357 | 279 |
358 int descriptor = transition->LastAdded(); | 280 int descriptor = transition->LastAdded(); |
359 DescriptorArray* descriptors = transition->instance_descriptors(); | 281 DescriptorArray* descriptors = transition->instance_descriptors(); |
(...skipping 140 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
500 // Return the value (register x0). | 422 // Return the value (register x0). |
501 ASSERT(value_reg.is(x0)); | 423 ASSERT(value_reg.is(x0)); |
502 __ Ret(); | 424 __ Ret(); |
503 } | 425 } |
504 | 426 |
505 | 427 |
506 // Generate StoreField code, value is passed in x0 register. | 428 // Generate StoreField code, value is passed in x0 register. |
507 // When leaving generated code after success, the receiver_reg and name_reg may | 429 // When leaving generated code after success, the receiver_reg and name_reg may |
508 // be clobbered. Upon branch to miss_label, the receiver and name registers have | 430 // be clobbered. Upon branch to miss_label, the receiver and name registers have |
509 // their original values. | 431 // their original values. |
510 void StoreStubCompiler::GenerateStoreField(MacroAssembler* masm, | 432 void NamedStoreHandlerCompiler::GenerateStoreField( |
511 Handle<JSObject> object, | 433 MacroAssembler* masm, Handle<JSObject> object, LookupResult* lookup, |
512 LookupResult* lookup, | 434 Register receiver_reg, Register name_reg, Register value_reg, |
513 Register receiver_reg, | 435 Register scratch1, Register scratch2, Label* miss_label) { |
514 Register name_reg, | |
515 Register value_reg, | |
516 Register scratch1, | |
517 Register scratch2, | |
518 Label* miss_label) { | |
519 // x0 : value | 436 // x0 : value |
520 Label exit; | 437 Label exit; |
521 | 438 |
522 // Stub never generated for non-global objects that require access | 439 // Stub never generated for non-global objects that require access |
523 // checks. | 440 // checks. |
524 ASSERT(object->IsJSGlobalProxy() || !object->IsAccessCheckNeeded()); | 441 ASSERT(object->IsJSGlobalProxy() || !object->IsAccessCheckNeeded()); |
525 | 442 |
526 FieldIndex index = lookup->GetFieldIndex(); | 443 FieldIndex index = lookup->GetFieldIndex(); |
527 | 444 |
528 Representation representation = lookup->representation(); | 445 Representation representation = lookup->representation(); |
(...skipping 99 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
628 } | 545 } |
629 } | 546 } |
630 | 547 |
631 __ Bind(&exit); | 548 __ Bind(&exit); |
632 // Return the value (register x0). | 549 // Return the value (register x0). |
633 ASSERT(value_reg.is(x0)); | 550 ASSERT(value_reg.is(x0)); |
634 __ Ret(); | 551 __ Ret(); |
635 } | 552 } |
636 | 553 |
637 | 554 |
638 void StoreStubCompiler::GenerateRestoreName(MacroAssembler* masm, | 555 void NamedStoreHandlerCompiler::GenerateRestoreName(MacroAssembler* masm, |
639 Label* label, | 556 Label* label, |
640 Handle<Name> name) { | 557 Handle<Name> name) { |
641 if (!label->is_unused()) { | 558 if (!label->is_unused()) { |
642 __ Bind(label); | 559 __ Bind(label); |
643 __ Mov(this->name(), Operand(name)); | 560 __ Mov(this->name(), Operand(name)); |
644 } | 561 } |
645 } | 562 } |
646 | 563 |
647 | 564 |
648 static void PushInterceptorArguments(MacroAssembler* masm, | 565 static void PushInterceptorArguments(MacroAssembler* masm, |
649 Register receiver, | 566 Register receiver, |
650 Register holder, | 567 Register holder, |
(...skipping 23 matching lines...) Expand all Loading... |
674 IC::UtilityId id) { | 591 IC::UtilityId id) { |
675 PushInterceptorArguments(masm, receiver, holder, name, holder_obj); | 592 PushInterceptorArguments(masm, receiver, holder, name, holder_obj); |
676 | 593 |
677 __ CallExternalReference( | 594 __ CallExternalReference( |
678 ExternalReference(IC_Utility(id), masm->isolate()), | 595 ExternalReference(IC_Utility(id), masm->isolate()), |
679 StubCache::kInterceptorArgsLength); | 596 StubCache::kInterceptorArgsLength); |
680 } | 597 } |
681 | 598 |
682 | 599 |
683 // Generate call to api function. | 600 // Generate call to api function. |
684 void StubCompiler::GenerateFastApiCall(MacroAssembler* masm, | 601 void PropertyHandlerCompiler::GenerateFastApiCall( |
685 const CallOptimization& optimization, | 602 MacroAssembler* masm, const CallOptimization& optimization, |
686 Handle<Map> receiver_map, | 603 Handle<Map> receiver_map, Register receiver, Register scratch, |
687 Register receiver, | 604 bool is_store, int argc, Register* values) { |
688 Register scratch, | |
689 bool is_store, | |
690 int argc, | |
691 Register* values) { | |
692 ASSERT(!AreAliased(receiver, scratch)); | 605 ASSERT(!AreAliased(receiver, scratch)); |
693 | 606 |
694 MacroAssembler::PushPopQueue queue(masm); | 607 MacroAssembler::PushPopQueue queue(masm); |
695 queue.Queue(receiver); | 608 queue.Queue(receiver); |
696 // Write the arguments to the stack frame. | 609 // Write the arguments to the stack frame. |
697 for (int i = 0; i < argc; i++) { | 610 for (int i = 0; i < argc; i++) { |
698 Register arg = values[argc-1-i]; | 611 Register arg = values[argc-1-i]; |
699 ASSERT(!AreAliased(receiver, scratch, arg)); | 612 ASSERT(!AreAliased(receiver, scratch, arg)); |
700 queue.Queue(arg); | 613 queue.Queue(arg); |
701 } | 614 } |
(...skipping 50 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
752 ExternalReference::DIRECT_API_CALL, | 665 ExternalReference::DIRECT_API_CALL, |
753 masm->isolate()); | 666 masm->isolate()); |
754 __ Mov(api_function_address, ref); | 667 __ Mov(api_function_address, ref); |
755 | 668 |
756 // Jump to stub. | 669 // Jump to stub. |
757 CallApiFunctionStub stub(isolate, is_store, call_data_undefined, argc); | 670 CallApiFunctionStub stub(isolate, is_store, call_data_undefined, argc); |
758 __ TailCallStub(&stub); | 671 __ TailCallStub(&stub); |
759 } | 672 } |
760 | 673 |
761 | 674 |
762 void StubCompiler::GenerateTailCall(MacroAssembler* masm, Handle<Code> code) { | 675 void PropertyAccessCompiler::GenerateTailCall(MacroAssembler* masm, |
| 676 Handle<Code> code) { |
763 __ Jump(code, RelocInfo::CODE_TARGET); | 677 __ Jump(code, RelocInfo::CODE_TARGET); |
764 } | 678 } |
765 | 679 |
766 | 680 |
767 #undef __ | 681 #undef __ |
768 #define __ ACCESS_MASM(masm()) | 682 #define __ ACCESS_MASM(masm()) |
769 | 683 |
770 | 684 |
771 Register StubCompiler::CheckPrototypes(Handle<HeapType> type, | 685 Register PropertyHandlerCompiler::CheckPrototypes( |
772 Register object_reg, | 686 Handle<HeapType> type, Register object_reg, Handle<JSObject> holder, |
773 Handle<JSObject> holder, | 687 Register holder_reg, Register scratch1, Register scratch2, |
774 Register holder_reg, | 688 Handle<Name> name, Label* miss, PrototypeCheckType check) { |
775 Register scratch1, | |
776 Register scratch2, | |
777 Handle<Name> name, | |
778 Label* miss, | |
779 PrototypeCheckType check) { | |
780 Handle<Map> receiver_map(IC::TypeToMap(*type, isolate())); | 689 Handle<Map> receiver_map(IC::TypeToMap(*type, isolate())); |
781 | 690 |
782 // object_reg and holder_reg registers can alias. | 691 // object_reg and holder_reg registers can alias. |
783 ASSERT(!AreAliased(object_reg, scratch1, scratch2)); | 692 ASSERT(!AreAliased(object_reg, scratch1, scratch2)); |
784 ASSERT(!AreAliased(holder_reg, scratch1, scratch2)); | 693 ASSERT(!AreAliased(holder_reg, scratch1, scratch2)); |
785 | 694 |
786 // Keep track of the current object in register reg. | 695 // Keep track of the current object in register reg. |
787 Register reg = object_reg; | 696 Register reg = object_reg; |
788 int depth = 0; | 697 int depth = 0; |
789 | 698 |
(...skipping 86 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
876 !current_map->is_access_check_needed()); | 785 !current_map->is_access_check_needed()); |
877 if (current_map->IsJSGlobalProxyMap()) { | 786 if (current_map->IsJSGlobalProxyMap()) { |
878 __ CheckAccessGlobalProxy(reg, scratch1, scratch2, miss); | 787 __ CheckAccessGlobalProxy(reg, scratch1, scratch2, miss); |
879 } | 788 } |
880 | 789 |
881 // Return the register containing the holder. | 790 // Return the register containing the holder. |
882 return reg; | 791 return reg; |
883 } | 792 } |
884 | 793 |
885 | 794 |
886 void LoadStubCompiler::HandlerFrontendFooter(Handle<Name> name, Label* miss) { | 795 void NamedLoadHandlerCompiler::FrontendFooter(Handle<Name> name, Label* miss) { |
887 if (!miss->is_unused()) { | 796 if (!miss->is_unused()) { |
888 Label success; | 797 Label success; |
889 __ B(&success); | 798 __ B(&success); |
890 | 799 |
891 __ Bind(miss); | 800 __ Bind(miss); |
892 TailCallBuiltin(masm(), MissBuiltin(kind())); | 801 TailCallBuiltin(masm(), MissBuiltin(kind())); |
893 | 802 |
894 __ Bind(&success); | 803 __ Bind(&success); |
895 } | 804 } |
896 } | 805 } |
897 | 806 |
898 | 807 |
899 void StoreStubCompiler::HandlerFrontendFooter(Handle<Name> name, Label* miss) { | 808 void NamedStoreHandlerCompiler::FrontendFooter(Handle<Name> name, Label* miss) { |
900 if (!miss->is_unused()) { | 809 if (!miss->is_unused()) { |
901 Label success; | 810 Label success; |
902 __ B(&success); | 811 __ B(&success); |
903 | 812 |
904 GenerateRestoreName(masm(), miss, name); | 813 GenerateRestoreName(masm(), miss, name); |
905 TailCallBuiltin(masm(), MissBuiltin(kind())); | 814 TailCallBuiltin(masm(), MissBuiltin(kind())); |
906 | 815 |
907 __ Bind(&success); | 816 __ Bind(&success); |
908 } | 817 } |
909 } | 818 } |
910 | 819 |
911 | 820 |
912 Register LoadStubCompiler::CallbackHandlerFrontend(Handle<HeapType> type, | 821 Register NamedLoadHandlerCompiler::CallbackFrontend(Handle<HeapType> type, |
913 Register object_reg, | 822 Register object_reg, |
914 Handle<JSObject> holder, | 823 Handle<JSObject> holder, |
915 Handle<Name> name, | 824 Handle<Name> name, |
916 Handle<Object> callback) { | 825 Handle<Object> callback) { |
917 Label miss; | 826 Label miss; |
918 | 827 |
919 Register reg = HandlerFrontendHeader(type, object_reg, holder, name, &miss); | 828 Register reg = FrontendHeader(type, object_reg, holder, name, &miss); |
920 // HandlerFrontendHeader can return its result into scratch1() so do not | 829 // FrontendHeader can return its result into scratch1() so do not |
921 // use it. | 830 // use it. |
922 Register scratch2 = this->scratch2(); | 831 Register scratch2 = this->scratch2(); |
923 Register scratch3 = this->scratch3(); | 832 Register scratch3 = this->scratch3(); |
924 Register dictionary = this->scratch4(); | 833 Register dictionary = this->scratch4(); |
925 ASSERT(!AreAliased(reg, scratch2, scratch3, dictionary)); | 834 ASSERT(!AreAliased(reg, scratch2, scratch3, dictionary)); |
926 | 835 |
927 if (!holder->HasFastProperties() && !holder->IsJSGlobalObject()) { | 836 if (!holder->HasFastProperties() && !holder->IsJSGlobalObject()) { |
928 // Load the properties dictionary. | 837 // Load the properties dictionary. |
929 __ Ldr(dictionary, FieldMemOperand(reg, JSObject::kPropertiesOffset)); | 838 __ Ldr(dictionary, FieldMemOperand(reg, JSObject::kPropertiesOffset)); |
930 | 839 |
(...skipping 12 matching lines...) Expand all Loading... |
943 // pointer into the dictionary. Check that the value is the callback. | 852 // pointer into the dictionary. Check that the value is the callback. |
944 Register pointer = scratch3; | 853 Register pointer = scratch3; |
945 const int kElementsStartOffset = NameDictionary::kHeaderSize + | 854 const int kElementsStartOffset = NameDictionary::kHeaderSize + |
946 NameDictionary::kElementsStartIndex * kPointerSize; | 855 NameDictionary::kElementsStartIndex * kPointerSize; |
947 const int kValueOffset = kElementsStartOffset + kPointerSize; | 856 const int kValueOffset = kElementsStartOffset + kPointerSize; |
948 __ Ldr(scratch2, FieldMemOperand(pointer, kValueOffset)); | 857 __ Ldr(scratch2, FieldMemOperand(pointer, kValueOffset)); |
949 __ Cmp(scratch2, Operand(callback)); | 858 __ Cmp(scratch2, Operand(callback)); |
950 __ B(ne, &miss); | 859 __ B(ne, &miss); |
951 } | 860 } |
952 | 861 |
953 HandlerFrontendFooter(name, &miss); | 862 FrontendFooter(name, &miss); |
954 return reg; | 863 return reg; |
955 } | 864 } |
956 | 865 |
957 | 866 |
958 void LoadStubCompiler::GenerateLoadField(Register reg, | 867 void NamedLoadHandlerCompiler::GenerateLoadField( |
959 Handle<JSObject> holder, | 868 Register reg, Handle<JSObject> holder, FieldIndex field, |
960 FieldIndex field, | 869 Representation representation) { |
961 Representation representation) { | |
962 __ Mov(receiver(), reg); | 870 __ Mov(receiver(), reg); |
963 LoadFieldStub stub(isolate(), field); | 871 LoadFieldStub stub(isolate(), field); |
964 GenerateTailCall(masm(), stub.GetCode()); | 872 GenerateTailCall(masm(), stub.GetCode()); |
965 } | 873 } |
966 | 874 |
967 | 875 |
968 void LoadStubCompiler::GenerateLoadConstant(Handle<Object> value) { | 876 void NamedLoadHandlerCompiler::GenerateLoadConstant(Handle<Object> value) { |
969 // Return the constant value. | 877 // Return the constant value. |
970 __ LoadObject(x0, value); | 878 __ LoadObject(x0, value); |
971 __ Ret(); | 879 __ Ret(); |
972 } | 880 } |
973 | 881 |
974 | 882 |
975 void LoadStubCompiler::GenerateLoadCallback( | 883 void NamedLoadHandlerCompiler::GenerateLoadCallback( |
976 Register reg, | 884 Register reg, Handle<ExecutableAccessorInfo> callback) { |
977 Handle<ExecutableAccessorInfo> callback) { | |
978 ASSERT(!AreAliased(scratch2(), scratch3(), scratch4(), reg)); | 885 ASSERT(!AreAliased(scratch2(), scratch3(), scratch4(), reg)); |
979 | 886 |
980 // Build ExecutableAccessorInfo::args_ list on the stack and push property | 887 // Build ExecutableAccessorInfo::args_ list on the stack and push property |
981 // name below the exit frame to make GC aware of them and store pointers to | 888 // name below the exit frame to make GC aware of them and store pointers to |
982 // them. | 889 // them. |
983 STATIC_ASSERT(PropertyCallbackArguments::kHolderIndex == 0); | 890 STATIC_ASSERT(PropertyCallbackArguments::kHolderIndex == 0); |
984 STATIC_ASSERT(PropertyCallbackArguments::kIsolateIndex == 1); | 891 STATIC_ASSERT(PropertyCallbackArguments::kIsolateIndex == 1); |
985 STATIC_ASSERT(PropertyCallbackArguments::kReturnValueDefaultValueIndex == 2); | 892 STATIC_ASSERT(PropertyCallbackArguments::kReturnValueDefaultValueIndex == 2); |
986 STATIC_ASSERT(PropertyCallbackArguments::kReturnValueOffset == 3); | 893 STATIC_ASSERT(PropertyCallbackArguments::kReturnValueOffset == 3); |
987 STATIC_ASSERT(PropertyCallbackArguments::kDataIndex == 4); | 894 STATIC_ASSERT(PropertyCallbackArguments::kDataIndex == 4); |
(...skipping 32 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1020 ApiFunction fun(getter_address); | 927 ApiFunction fun(getter_address); |
1021 ExternalReference::Type type = ExternalReference::DIRECT_GETTER_CALL; | 928 ExternalReference::Type type = ExternalReference::DIRECT_GETTER_CALL; |
1022 ExternalReference ref = ExternalReference(&fun, type, isolate()); | 929 ExternalReference ref = ExternalReference(&fun, type, isolate()); |
1023 __ Mov(getter_address_reg, ref); | 930 __ Mov(getter_address_reg, ref); |
1024 | 931 |
1025 CallApiGetterStub stub(isolate()); | 932 CallApiGetterStub stub(isolate()); |
1026 __ TailCallStub(&stub); | 933 __ TailCallStub(&stub); |
1027 } | 934 } |
1028 | 935 |
1029 | 936 |
1030 void LoadStubCompiler::GenerateLoadInterceptor( | 937 void NamedLoadHandlerCompiler::GenerateLoadInterceptor( |
1031 Register holder_reg, | 938 Register holder_reg, Handle<Object> object, |
1032 Handle<Object> object, | 939 Handle<JSObject> interceptor_holder, LookupResult* lookup, |
1033 Handle<JSObject> interceptor_holder, | |
1034 LookupResult* lookup, | |
1035 Handle<Name> name) { | 940 Handle<Name> name) { |
1036 ASSERT(!AreAliased(receiver(), this->name(), | 941 ASSERT(!AreAliased(receiver(), this->name(), |
1037 scratch1(), scratch2(), scratch3())); | 942 scratch1(), scratch2(), scratch3())); |
1038 ASSERT(interceptor_holder->HasNamedInterceptor()); | 943 ASSERT(interceptor_holder->HasNamedInterceptor()); |
1039 ASSERT(!interceptor_holder->GetNamedInterceptor()->getter()->IsUndefined()); | 944 ASSERT(!interceptor_holder->GetNamedInterceptor()->getter()->IsUndefined()); |
1040 | 945 |
1041 // So far the most popular follow ups for interceptor loads are FIELD | 946 // So far the most popular follow ups for interceptor loads are FIELD |
1042 // and CALLBACKS, so inline only them, other cases may be added later. | 947 // and CALLBACKS, so inline only them, other cases may be added later. |
1043 bool compile_followup_inline = false; | 948 bool compile_followup_inline = false; |
1044 if (lookup->IsFound() && lookup->IsCacheable()) { | 949 if (lookup->IsFound() && lookup->IsCacheable()) { |
(...skipping 63 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1108 masm(), receiver(), holder_reg, this->name(), interceptor_holder); | 1013 masm(), receiver(), holder_reg, this->name(), interceptor_holder); |
1109 | 1014 |
1110 ExternalReference ref = | 1015 ExternalReference ref = |
1111 ExternalReference(IC_Utility(IC::kLoadPropertyWithInterceptor), | 1016 ExternalReference(IC_Utility(IC::kLoadPropertyWithInterceptor), |
1112 isolate()); | 1017 isolate()); |
1113 __ TailCallExternalReference(ref, StubCache::kInterceptorArgsLength, 1); | 1018 __ TailCallExternalReference(ref, StubCache::kInterceptorArgsLength, 1); |
1114 } | 1019 } |
1115 } | 1020 } |
1116 | 1021 |
1117 | 1022 |
1118 Handle<Code> StoreStubCompiler::CompileStoreCallback( | 1023 Handle<Code> NamedStoreHandlerCompiler::CompileStoreCallback( |
1119 Handle<JSObject> object, | 1024 Handle<JSObject> object, Handle<JSObject> holder, Handle<Name> name, |
1120 Handle<JSObject> holder, | |
1121 Handle<Name> name, | |
1122 Handle<ExecutableAccessorInfo> callback) { | 1025 Handle<ExecutableAccessorInfo> callback) { |
1123 ASM_LOCATION("StoreStubCompiler::CompileStoreCallback"); | 1026 ASM_LOCATION("NamedStoreHandlerCompiler::CompileStoreCallback"); |
1124 Register holder_reg = HandlerFrontend( | 1027 Register holder_reg = |
1125 IC::CurrentTypeOf(object, isolate()), receiver(), holder, name); | 1028 Frontend(IC::CurrentTypeOf(object, isolate()), receiver(), holder, name); |
1126 | 1029 |
1127 // Stub never generated for non-global objects that require access checks. | 1030 // Stub never generated for non-global objects that require access checks. |
1128 ASSERT(holder->IsJSGlobalProxy() || !holder->IsAccessCheckNeeded()); | 1031 ASSERT(holder->IsJSGlobalProxy() || !holder->IsAccessCheckNeeded()); |
1129 | 1032 |
1130 // receiver() and holder_reg can alias. | 1033 // receiver() and holder_reg can alias. |
1131 ASSERT(!AreAliased(receiver(), scratch1(), scratch2(), value())); | 1034 ASSERT(!AreAliased(receiver(), scratch1(), scratch2(), value())); |
1132 ASSERT(!AreAliased(holder_reg, scratch1(), scratch2(), value())); | 1035 ASSERT(!AreAliased(holder_reg, scratch1(), scratch2(), value())); |
1133 __ Mov(scratch1(), Operand(callback)); | 1036 __ Mov(scratch1(), Operand(callback)); |
1134 __ Mov(scratch2(), Operand(name)); | 1037 __ Mov(scratch2(), Operand(name)); |
1135 __ Push(receiver(), holder_reg, scratch1(), scratch2(), value()); | 1038 __ Push(receiver(), holder_reg, scratch1(), scratch2(), value()); |
1136 | 1039 |
1137 // Do tail-call to the runtime system. | 1040 // Do tail-call to the runtime system. |
1138 ExternalReference store_callback_property = | 1041 ExternalReference store_callback_property = |
1139 ExternalReference(IC_Utility(IC::kStoreCallbackProperty), isolate()); | 1042 ExternalReference(IC_Utility(IC::kStoreCallbackProperty), isolate()); |
1140 __ TailCallExternalReference(store_callback_property, 5, 1); | 1043 __ TailCallExternalReference(store_callback_property, 5, 1); |
1141 | 1044 |
1142 // Return the generated code. | 1045 // Return the generated code. |
1143 return GetCode(kind(), Code::FAST, name); | 1046 return GetCode(kind(), Code::FAST, name); |
1144 } | 1047 } |
1145 | 1048 |
1146 | 1049 |
1147 #undef __ | 1050 #undef __ |
1148 #define __ ACCESS_MASM(masm) | 1051 #define __ ACCESS_MASM(masm) |
1149 | 1052 |
1150 | 1053 |
1151 void StoreStubCompiler::GenerateStoreViaSetter( | 1054 void NamedStoreHandlerCompiler::GenerateStoreViaSetter( |
1152 MacroAssembler* masm, | 1055 MacroAssembler* masm, Handle<HeapType> type, Register receiver, |
1153 Handle<HeapType> type, | |
1154 Register receiver, | |
1155 Handle<JSFunction> setter) { | 1056 Handle<JSFunction> setter) { |
1156 // ----------- S t a t e ------------- | 1057 // ----------- S t a t e ------------- |
1157 // -- lr : return address | 1058 // -- lr : return address |
1158 // ----------------------------------- | 1059 // ----------------------------------- |
1159 Label miss; | 1060 Label miss; |
1160 | 1061 |
1161 { | 1062 { |
1162 FrameScope scope(masm, StackFrame::INTERNAL); | 1063 FrameScope scope(masm, StackFrame::INTERNAL); |
1163 | 1064 |
1164 // Save value register, so we can restore it later. | 1065 // Save value register, so we can restore it later. |
(...skipping 24 matching lines...) Expand all Loading... |
1189 __ Ldr(cp, MemOperand(fp, StandardFrameConstants::kContextOffset)); | 1090 __ Ldr(cp, MemOperand(fp, StandardFrameConstants::kContextOffset)); |
1190 } | 1091 } |
1191 __ Ret(); | 1092 __ Ret(); |
1192 } | 1093 } |
1193 | 1094 |
1194 | 1095 |
1195 #undef __ | 1096 #undef __ |
1196 #define __ ACCESS_MASM(masm()) | 1097 #define __ ACCESS_MASM(masm()) |
1197 | 1098 |
1198 | 1099 |
1199 Handle<Code> StoreStubCompiler::CompileStoreInterceptor( | 1100 Handle<Code> NamedStoreHandlerCompiler::CompileStoreInterceptor( |
1200 Handle<JSObject> object, | 1101 Handle<JSObject> object, Handle<Name> name) { |
1201 Handle<Name> name) { | |
1202 Label miss; | 1102 Label miss; |
1203 | 1103 |
1204 ASM_LOCATION("StoreStubCompiler::CompileStoreInterceptor"); | 1104 ASM_LOCATION("NamedStoreHandlerCompiler::CompileStoreInterceptor"); |
1205 | 1105 |
1206 __ Push(receiver(), this->name(), value()); | 1106 __ Push(receiver(), this->name(), value()); |
1207 | 1107 |
1208 // Do tail-call to the runtime system. | 1108 // Do tail-call to the runtime system. |
1209 ExternalReference store_ic_property = | 1109 ExternalReference store_ic_property = |
1210 ExternalReference(IC_Utility(IC::kStoreInterceptorProperty), isolate()); | 1110 ExternalReference(IC_Utility(IC::kStoreInterceptorProperty), isolate()); |
1211 __ TailCallExternalReference(store_ic_property, 3, 1); | 1111 __ TailCallExternalReference(store_ic_property, 3, 1); |
1212 | 1112 |
1213 // Return the generated code. | 1113 // Return the generated code. |
1214 return GetCode(kind(), Code::FAST, name); | 1114 return GetCode(kind(), Code::FAST, name); |
1215 } | 1115 } |
1216 | 1116 |
1217 | 1117 |
1218 Handle<Code> LoadStubCompiler::CompileLoadNonexistent(Handle<HeapType> type, | 1118 Handle<Code> NamedLoadHandlerCompiler::CompileLoadNonexistent( |
1219 Handle<JSObject> last, | 1119 Handle<HeapType> type, Handle<JSObject> last, Handle<Name> name) { |
1220 Handle<Name> name) { | 1120 NonexistentFrontend(type, last, name); |
1221 NonexistentHandlerFrontend(type, last, name); | |
1222 | 1121 |
1223 // Return undefined if maps of the full prototype chain are still the | 1122 // Return undefined if maps of the full prototype chain are still the |
1224 // same and no global property with this name contains a value. | 1123 // same and no global property with this name contains a value. |
1225 __ LoadRoot(x0, Heap::kUndefinedValueRootIndex); | 1124 __ LoadRoot(x0, Heap::kUndefinedValueRootIndex); |
1226 __ Ret(); | 1125 __ Ret(); |
1227 | 1126 |
1228 // Return the generated code. | 1127 // Return the generated code. |
1229 return GetCode(kind(), Code::FAST, name); | 1128 return GetCode(kind(), Code::FAST, name); |
1230 } | 1129 } |
1231 | 1130 |
1232 | 1131 |
1233 // TODO(all): The so-called scratch registers are significant in some cases. For | 1132 // TODO(all): The so-called scratch registers are significant in some cases. For |
1234 // example, KeyedStoreStubCompiler::registers()[3] (x3) is actually used for | 1133 // example, PropertyAccessCompiler::keyed_store_calling_convention()[3] (x3) is |
1235 // KeyedStoreCompiler::transition_map(). We should verify which registers are | 1134 // actually |
1236 // actually scratch registers, and which are important. For now, we use the same | 1135 // used for KeyedStoreCompiler::transition_map(). We should verify which |
1237 // assignments as ARM to remain on the safe side. | 1136 // registers are actually scratch registers, and which are important. For now, |
| 1137 // we use the same assignments as ARM to remain on the safe side. |
1238 | 1138 |
1239 Register* LoadStubCompiler::registers() { | 1139 Register* PropertyAccessCompiler::load_calling_convention() { |
1240 // receiver, name, scratch1, scratch2, scratch3, scratch4. | 1140 // receiver, name, scratch1, scratch2, scratch3, scratch4. |
1241 Register receiver = LoadIC::ReceiverRegister(); | 1141 Register receiver = LoadIC::ReceiverRegister(); |
1242 Register name = LoadIC::NameRegister(); | 1142 Register name = LoadIC::NameRegister(); |
1243 static Register registers[] = { receiver, name, x3, x0, x4, x5 }; | 1143 static Register registers[] = { receiver, name, x3, x0, x4, x5 }; |
1244 return registers; | 1144 return registers; |
1245 } | 1145 } |
1246 | 1146 |
1247 | 1147 |
1248 Register* KeyedLoadStubCompiler::registers() { | 1148 Register* PropertyAccessCompiler::store_calling_convention() { |
1249 // receiver, name, scratch1, scratch2, scratch3, scratch4. | |
1250 Register receiver = LoadIC::ReceiverRegister(); | |
1251 Register name = LoadIC::NameRegister(); | |
1252 static Register registers[] = { receiver, name, x3, x0, x4, x5 }; | |
1253 return registers; | |
1254 } | |
1255 | |
1256 | |
1257 Register StoreStubCompiler::value() { | |
1258 return StoreIC::ValueRegister(); | |
1259 } | |
1260 | |
1261 | |
1262 Register* StoreStubCompiler::registers() { | |
1263 // receiver, value, scratch1, scratch2, scratch3. | 1149 // receiver, value, scratch1, scratch2, scratch3. |
1264 Register receiver = StoreIC::ReceiverRegister(); | 1150 Register receiver = StoreIC::ReceiverRegister(); |
1265 Register name = StoreIC::NameRegister(); | 1151 Register name = StoreIC::NameRegister(); |
1266 static Register registers[] = { receiver, name, x3, x4, x5 }; | 1152 static Register registers[] = { receiver, name, x3, x4, x5 }; |
1267 return registers; | 1153 return registers; |
1268 } | 1154 } |
1269 | 1155 |
1270 | 1156 |
1271 Register* KeyedStoreStubCompiler::registers() { | 1157 Register* PropertyAccessCompiler::keyed_store_calling_convention() { |
1272 // receiver, name, scratch1/map, scratch2, scratch3. | 1158 // receiver, name, scratch1/map, scratch2, scratch3. |
1273 Register receiver = KeyedStoreIC::ReceiverRegister(); | 1159 Register receiver = KeyedStoreIC::ReceiverRegister(); |
1274 Register name = KeyedStoreIC::NameRegister(); | 1160 Register name = KeyedStoreIC::NameRegister(); |
1275 Register map = KeyedStoreIC::MapRegister(); | 1161 Register map = KeyedStoreIC::MapRegister(); |
1276 static Register registers[] = { receiver, name, map, x4, x5 }; | 1162 static Register registers[] = { receiver, name, map, x4, x5 }; |
1277 return registers; | 1163 return registers; |
1278 } | 1164 } |
1279 | 1165 |
1280 | 1166 |
| 1167 Register NamedStoreHandlerCompiler::value() { return StoreIC::ValueRegister(); } |
| 1168 |
| 1169 |
1281 #undef __ | 1170 #undef __ |
1282 #define __ ACCESS_MASM(masm) | 1171 #define __ ACCESS_MASM(masm) |
1283 | 1172 |
1284 void LoadStubCompiler::GenerateLoadViaGetter(MacroAssembler* masm, | 1173 void NamedLoadHandlerCompiler::GenerateLoadViaGetter( |
1285 Handle<HeapType> type, | 1174 MacroAssembler* masm, Handle<HeapType> type, Register receiver, |
1286 Register receiver, | 1175 Handle<JSFunction> getter) { |
1287 Handle<JSFunction> getter) { | |
1288 { | 1176 { |
1289 FrameScope scope(masm, StackFrame::INTERNAL); | 1177 FrameScope scope(masm, StackFrame::INTERNAL); |
1290 | 1178 |
1291 if (!getter.is_null()) { | 1179 if (!getter.is_null()) { |
1292 // Call the JavaScript getter with the receiver on the stack. | 1180 // Call the JavaScript getter with the receiver on the stack. |
1293 if (IC::TypeToMap(*type, masm->isolate())->IsJSGlobalObjectMap()) { | 1181 if (IC::TypeToMap(*type, masm->isolate())->IsJSGlobalObjectMap()) { |
1294 // Swap in the global receiver. | 1182 // Swap in the global receiver. |
1295 __ Ldr(receiver, | 1183 __ Ldr(receiver, |
1296 FieldMemOperand(receiver, JSGlobalObject::kGlobalProxyOffset)); | 1184 FieldMemOperand(receiver, JSGlobalObject::kGlobalProxyOffset)); |
1297 } | 1185 } |
(...skipping 12 matching lines...) Expand all Loading... |
1310 __ Ldr(cp, MemOperand(fp, StandardFrameConstants::kContextOffset)); | 1198 __ Ldr(cp, MemOperand(fp, StandardFrameConstants::kContextOffset)); |
1311 } | 1199 } |
1312 __ Ret(); | 1200 __ Ret(); |
1313 } | 1201 } |
1314 | 1202 |
1315 | 1203 |
1316 #undef __ | 1204 #undef __ |
1317 #define __ ACCESS_MASM(masm()) | 1205 #define __ ACCESS_MASM(masm()) |
1318 | 1206 |
1319 | 1207 |
1320 Handle<Code> LoadStubCompiler::CompileLoadGlobal( | 1208 Handle<Code> NamedLoadHandlerCompiler::CompileLoadGlobal( |
1321 Handle<HeapType> type, | 1209 Handle<HeapType> type, Handle<GlobalObject> global, |
1322 Handle<GlobalObject> global, | 1210 Handle<PropertyCell> cell, Handle<Name> name, bool is_dont_delete) { |
1323 Handle<PropertyCell> cell, | |
1324 Handle<Name> name, | |
1325 bool is_dont_delete) { | |
1326 Label miss; | 1211 Label miss; |
1327 HandlerFrontendHeader(type, receiver(), global, name, &miss); | 1212 FrontendHeader(type, receiver(), global, name, &miss); |
1328 | 1213 |
1329 // Get the value from the cell. | 1214 // Get the value from the cell. |
1330 __ Mov(x3, Operand(cell)); | 1215 __ Mov(x3, Operand(cell)); |
1331 __ Ldr(x4, FieldMemOperand(x3, Cell::kValueOffset)); | 1216 __ Ldr(x4, FieldMemOperand(x3, Cell::kValueOffset)); |
1332 | 1217 |
1333 // Check for deleted property if property can actually be deleted. | 1218 // Check for deleted property if property can actually be deleted. |
1334 if (!is_dont_delete) { | 1219 if (!is_dont_delete) { |
1335 __ JumpIfRoot(x4, Heap::kTheHoleValueRootIndex, &miss); | 1220 __ JumpIfRoot(x4, Heap::kTheHoleValueRootIndex, &miss); |
1336 } | 1221 } |
1337 | 1222 |
1338 Counters* counters = isolate()->counters(); | 1223 Counters* counters = isolate()->counters(); |
1339 __ IncrementCounter(counters->named_load_global_stub(), 1, x1, x3); | 1224 __ IncrementCounter(counters->named_load_global_stub(), 1, x1, x3); |
1340 __ Mov(x0, x4); | 1225 __ Mov(x0, x4); |
1341 __ Ret(); | 1226 __ Ret(); |
1342 | 1227 |
1343 HandlerFrontendFooter(name, &miss); | 1228 FrontendFooter(name, &miss); |
1344 | 1229 |
1345 // Return the generated code. | 1230 // Return the generated code. |
1346 return GetCode(kind(), Code::NORMAL, name); | 1231 return GetCode(kind(), Code::NORMAL, name); |
1347 } | 1232 } |
1348 | 1233 |
1349 | 1234 |
1350 Handle<Code> BaseLoadStoreStubCompiler::CompilePolymorphicIC( | 1235 Handle<Code> PropertyICCompiler::CompilePolymorphic(TypeHandleList* types, |
1351 TypeHandleList* types, | 1236 CodeHandleList* handlers, |
1352 CodeHandleList* handlers, | 1237 Handle<Name> name, |
1353 Handle<Name> name, | 1238 Code::StubType type, |
1354 Code::StubType type, | 1239 IcCheckType check) { |
1355 IcCheckType check) { | |
1356 Label miss; | 1240 Label miss; |
1357 | 1241 |
1358 if (check == PROPERTY && | 1242 if (check == PROPERTY && |
1359 (kind() == Code::KEYED_LOAD_IC || kind() == Code::KEYED_STORE_IC)) { | 1243 (kind() == Code::KEYED_LOAD_IC || kind() == Code::KEYED_STORE_IC)) { |
1360 __ CompareAndBranch(this->name(), Operand(name), ne, &miss); | 1244 __ CompareAndBranch(this->name(), Operand(name), ne, &miss); |
1361 } | 1245 } |
1362 | 1246 |
1363 Label number_case; | 1247 Label number_case; |
1364 Label* smi_target = IncludesNumberType(types) ? &number_case : &miss; | 1248 Label* smi_target = IncludesNumberType(types) ? &number_case : &miss; |
1365 __ JumpIfSmi(receiver(), smi_target); | 1249 __ JumpIfSmi(receiver(), smi_target); |
(...skipping 22 matching lines...) Expand all Loading... |
1388 } | 1272 } |
1389 } | 1273 } |
1390 ASSERT(number_of_handled_maps != 0); | 1274 ASSERT(number_of_handled_maps != 0); |
1391 | 1275 |
1392 __ Bind(&miss); | 1276 __ Bind(&miss); |
1393 TailCallBuiltin(masm(), MissBuiltin(kind())); | 1277 TailCallBuiltin(masm(), MissBuiltin(kind())); |
1394 | 1278 |
1395 // Return the generated code. | 1279 // Return the generated code. |
1396 InlineCacheState state = | 1280 InlineCacheState state = |
1397 (number_of_handled_maps > 1) ? POLYMORPHIC : MONOMORPHIC; | 1281 (number_of_handled_maps > 1) ? POLYMORPHIC : MONOMORPHIC; |
1398 return GetICCode(kind(), type, name, state); | 1282 return GetCode(kind(), type, name, state); |
1399 } | 1283 } |
1400 | 1284 |
1401 | 1285 |
1402 void StoreStubCompiler::GenerateStoreArrayLength() { | 1286 void NamedStoreHandlerCompiler::GenerateStoreArrayLength() { |
1403 // Prepare tail call to StoreIC_ArrayLength. | 1287 // Prepare tail call to StoreIC_ArrayLength. |
1404 __ Push(receiver(), value()); | 1288 __ Push(receiver(), value()); |
1405 | 1289 |
1406 ExternalReference ref = | 1290 ExternalReference ref = |
1407 ExternalReference(IC_Utility(IC::kStoreIC_ArrayLength), | 1291 ExternalReference(IC_Utility(IC::kStoreIC_ArrayLength), |
1408 masm()->isolate()); | 1292 masm()->isolate()); |
1409 __ TailCallExternalReference(ref, 2, 1); | 1293 __ TailCallExternalReference(ref, 2, 1); |
1410 } | 1294 } |
1411 | 1295 |
1412 | 1296 |
1413 Handle<Code> KeyedStoreStubCompiler::CompileStorePolymorphic( | 1297 Handle<Code> PropertyICCompiler::CompileIndexedStorePolymorphic( |
1414 MapHandleList* receiver_maps, | 1298 MapHandleList* receiver_maps, CodeHandleList* handler_stubs, |
1415 CodeHandleList* handler_stubs, | |
1416 MapHandleList* transitioned_maps) { | 1299 MapHandleList* transitioned_maps) { |
1417 Label miss; | 1300 Label miss; |
1418 | 1301 |
1419 ASM_LOCATION("KeyedStoreStubCompiler::CompileStorePolymorphic"); | 1302 ASM_LOCATION("PropertyICCompiler::CompileStorePolymorphic"); |
1420 | 1303 |
1421 __ JumpIfSmi(receiver(), &miss); | 1304 __ JumpIfSmi(receiver(), &miss); |
1422 | 1305 |
1423 int receiver_count = receiver_maps->length(); | 1306 int receiver_count = receiver_maps->length(); |
1424 __ Ldr(scratch1(), FieldMemOperand(receiver(), HeapObject::kMapOffset)); | 1307 __ Ldr(scratch1(), FieldMemOperand(receiver(), HeapObject::kMapOffset)); |
1425 for (int i = 0; i < receiver_count; i++) { | 1308 for (int i = 0; i < receiver_count; i++) { |
1426 __ Cmp(scratch1(), Operand(receiver_maps->at(i))); | 1309 __ Cmp(scratch1(), Operand(receiver_maps->at(i))); |
1427 | 1310 |
1428 Label skip; | 1311 Label skip; |
1429 __ B(&skip, ne); | 1312 __ B(&skip, ne); |
1430 if (!transitioned_maps->at(i).is_null()) { | 1313 if (!transitioned_maps->at(i).is_null()) { |
1431 // This argument is used by the handler stub. For example, see | 1314 // This argument is used by the handler stub. For example, see |
1432 // ElementsTransitionGenerator::GenerateMapChangeElementsTransition. | 1315 // ElementsTransitionGenerator::GenerateMapChangeElementsTransition. |
1433 __ Mov(transition_map(), Operand(transitioned_maps->at(i))); | 1316 __ Mov(transition_map(), Operand(transitioned_maps->at(i))); |
1434 } | 1317 } |
1435 __ Jump(handler_stubs->at(i), RelocInfo::CODE_TARGET); | 1318 __ Jump(handler_stubs->at(i), RelocInfo::CODE_TARGET); |
1436 __ Bind(&skip); | 1319 __ Bind(&skip); |
1437 } | 1320 } |
1438 | 1321 |
1439 __ Bind(&miss); | 1322 __ Bind(&miss); |
1440 TailCallBuiltin(masm(), MissBuiltin(kind())); | 1323 TailCallBuiltin(masm(), MissBuiltin(kind())); |
1441 | 1324 |
1442 return GetICCode( | 1325 return GetCode(kind(), Code::NORMAL, factory()->empty_string(), POLYMORPHIC); |
1443 kind(), Code::NORMAL, factory()->empty_string(), POLYMORPHIC); | |
1444 } | 1326 } |
1445 | 1327 |
1446 | 1328 |
1447 #undef __ | 1329 #undef __ |
1448 #define __ ACCESS_MASM(masm) | 1330 #define __ ACCESS_MASM(masm) |
1449 | 1331 |
1450 void KeyedLoadStubCompiler::GenerateLoadDictionaryElement( | 1332 void IndexedHandlerCompiler::GenerateLoadDictionaryElement( |
1451 MacroAssembler* masm) { | 1333 MacroAssembler* masm) { |
1452 // The return address is in lr. | 1334 // The return address is in lr. |
1453 Label slow, miss; | 1335 Label slow, miss; |
1454 | 1336 |
1455 Register result = x0; | 1337 Register result = x0; |
1456 Register key = LoadIC::NameRegister(); | 1338 Register key = LoadIC::NameRegister(); |
1457 Register receiver = LoadIC::ReceiverRegister(); | 1339 Register receiver = LoadIC::ReceiverRegister(); |
1458 ASSERT(receiver.is(x1)); | 1340 ASSERT(receiver.is(x1)); |
1459 ASSERT(key.is(x2)); | 1341 ASSERT(key.is(x2)); |
1460 | 1342 |
1461 __ JumpIfNotSmi(key, &miss); | 1343 __ JumpIfNotSmi(key, &miss); |
1462 __ Ldr(x4, FieldMemOperand(receiver, JSObject::kElementsOffset)); | 1344 __ Ldr(x4, FieldMemOperand(receiver, JSObject::kElementsOffset)); |
1463 __ LoadFromNumberDictionary(&slow, x4, key, result, x7, x3, x5, x6); | 1345 __ LoadFromNumberDictionary(&slow, x4, key, result, x7, x3, x5, x6); |
1464 __ Ret(); | 1346 __ Ret(); |
1465 | 1347 |
1466 __ Bind(&slow); | 1348 __ Bind(&slow); |
1467 __ IncrementCounter( | 1349 __ IncrementCounter( |
1468 masm->isolate()->counters()->keyed_load_external_array_slow(), 1, x4, x3); | 1350 masm->isolate()->counters()->keyed_load_external_array_slow(), 1, x4, x3); |
1469 TailCallBuiltin(masm, Builtins::kKeyedLoadIC_Slow); | 1351 TailCallBuiltin(masm, Builtins::kKeyedLoadIC_Slow); |
1470 | 1352 |
1471 // Miss case, call the runtime. | 1353 // Miss case, call the runtime. |
1472 __ Bind(&miss); | 1354 __ Bind(&miss); |
1473 TailCallBuiltin(masm, Builtins::kKeyedLoadIC_Miss); | 1355 TailCallBuiltin(masm, Builtins::kKeyedLoadIC_Miss); |
1474 } | 1356 } |
1475 | 1357 |
1476 | 1358 |
1477 } } // namespace v8::internal | 1359 } } // namespace v8::internal |
1478 | 1360 |
1479 #endif // V8_TARGET_ARCH_ARM64 | 1361 #endif // V8_TARGET_ARCH_ARM64 |
OLD | NEW |