OLD | NEW |
1 // Copyright 2012 the V8 project authors. All rights reserved. | 1 // Copyright 2012 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_X87 | 7 #if V8_TARGET_ARCH_X87 |
8 | 8 |
9 #include "src/codegen.h" | 9 #include "src/codegen.h" |
10 #include "src/ic-inl.h" | 10 #include "src/ic-inl.h" |
(...skipping 96 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
107 __ add(offset, Immediate(Code::kHeaderSize - kHeapObjectTag)); | 107 __ add(offset, Immediate(Code::kHeaderSize - kHeapObjectTag)); |
108 __ jmp(offset); | 108 __ jmp(offset); |
109 | 109 |
110 // Pop at miss. | 110 // Pop at miss. |
111 __ bind(&miss); | 111 __ bind(&miss); |
112 __ pop(offset); | 112 __ pop(offset); |
113 } | 113 } |
114 } | 114 } |
115 | 115 |
116 | 116 |
117 void StubCompiler::GenerateDictionaryNegativeLookup(MacroAssembler* masm, | 117 void PropertyHandlerCompiler::GenerateDictionaryNegativeLookup( |
118 Label* miss_label, | 118 MacroAssembler* masm, Label* miss_label, Register receiver, |
119 Register receiver, | 119 Handle<Name> name, Register scratch0, Register scratch1) { |
120 Handle<Name> name, | |
121 Register scratch0, | |
122 Register scratch1) { | |
123 ASSERT(name->IsUniqueName()); | 120 ASSERT(name->IsUniqueName()); |
124 ASSERT(!receiver.is(scratch0)); | 121 ASSERT(!receiver.is(scratch0)); |
125 Counters* counters = masm->isolate()->counters(); | 122 Counters* counters = masm->isolate()->counters(); |
126 __ IncrementCounter(counters->negative_lookups(), 1); | 123 __ IncrementCounter(counters->negative_lookups(), 1); |
127 __ IncrementCounter(counters->negative_lookups_miss(), 1); | 124 __ IncrementCounter(counters->negative_lookups_miss(), 1); |
128 | 125 |
129 __ mov(scratch0, FieldOperand(receiver, HeapObject::kMapOffset)); | 126 __ mov(scratch0, FieldOperand(receiver, HeapObject::kMapOffset)); |
130 | 127 |
131 const int kInterceptorOrAccessCheckNeededMask = | 128 const int kInterceptorOrAccessCheckNeededMask = |
132 (1 << Map::kHasNamedInterceptor) | (1 << Map::kIsAccessCheckNeeded); | 129 (1 << Map::kHasNamedInterceptor) | (1 << Map::kIsAccessCheckNeeded); |
(...skipping 93 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
226 ProbeTable( | 223 ProbeTable( |
227 isolate(), masm, flags, kSecondary, name, receiver, offset, extra); | 224 isolate(), masm, flags, kSecondary, name, receiver, offset, extra); |
228 | 225 |
229 // Cache miss: Fall-through and let caller handle the miss by | 226 // Cache miss: Fall-through and let caller handle the miss by |
230 // entering the runtime system. | 227 // entering the runtime system. |
231 __ bind(&miss); | 228 __ bind(&miss); |
232 __ IncrementCounter(counters->megamorphic_stub_cache_misses(), 1); | 229 __ IncrementCounter(counters->megamorphic_stub_cache_misses(), 1); |
233 } | 230 } |
234 | 231 |
235 | 232 |
236 void StubCompiler::GenerateLoadGlobalFunctionPrototype(MacroAssembler* masm, | 233 void NamedLoadHandlerCompiler::GenerateDirectLoadGlobalFunctionPrototype( |
237 int index, | 234 MacroAssembler* masm, int index, Register prototype, Label* miss) { |
238 Register prototype) { | |
239 __ LoadGlobalFunction(index, prototype); | |
240 __ LoadGlobalFunctionInitialMap(prototype, prototype); | |
241 // Load the prototype from the initial map. | |
242 __ mov(prototype, FieldOperand(prototype, Map::kPrototypeOffset)); | |
243 } | |
244 | |
245 | |
246 void StubCompiler::GenerateDirectLoadGlobalFunctionPrototype( | |
247 MacroAssembler* masm, | |
248 int index, | |
249 Register prototype, | |
250 Label* miss) { | |
251 // Get the global function with the given index. | 235 // Get the global function with the given index. |
252 Handle<JSFunction> function( | 236 Handle<JSFunction> function( |
253 JSFunction::cast(masm->isolate()->native_context()->get(index))); | 237 JSFunction::cast(masm->isolate()->native_context()->get(index))); |
254 // Check we're still in the same context. | 238 // Check we're still in the same context. |
255 Register scratch = prototype; | 239 Register scratch = prototype; |
256 const int offset = Context::SlotOffset(Context::GLOBAL_OBJECT_INDEX); | 240 const int offset = Context::SlotOffset(Context::GLOBAL_OBJECT_INDEX); |
257 __ mov(scratch, Operand(esi, offset)); | 241 __ mov(scratch, Operand(esi, offset)); |
258 __ mov(scratch, FieldOperand(scratch, GlobalObject::kNativeContextOffset)); | 242 __ mov(scratch, FieldOperand(scratch, GlobalObject::kNativeContextOffset)); |
259 __ cmp(Operand(scratch, Context::SlotOffset(index)), function); | 243 __ cmp(Operand(scratch, Context::SlotOffset(index)), function); |
260 __ j(not_equal, miss); | 244 __ j(not_equal, miss); |
261 | 245 |
262 // Load its initial map. The global functions all have initial maps. | 246 // Load its initial map. The global functions all have initial maps. |
263 __ Move(prototype, Immediate(Handle<Map>(function->initial_map()))); | 247 __ Move(prototype, Immediate(Handle<Map>(function->initial_map()))); |
264 // Load the prototype from the initial map. | 248 // Load the prototype from the initial map. |
265 __ mov(prototype, FieldOperand(prototype, Map::kPrototypeOffset)); | 249 __ mov(prototype, FieldOperand(prototype, Map::kPrototypeOffset)); |
266 } | 250 } |
267 | 251 |
268 | 252 |
269 void StubCompiler::GenerateLoadArrayLength(MacroAssembler* masm, | 253 void NamedLoadHandlerCompiler::GenerateLoadFunctionPrototype( |
270 Register receiver, | 254 MacroAssembler* masm, Register receiver, Register scratch1, |
271 Register scratch, | 255 Register scratch2, Label* miss_label) { |
272 Label* miss_label) { | |
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 __ CmpObjectType(receiver, JS_ARRAY_TYPE, scratch); | |
278 __ j(not_equal, miss_label); | |
279 | |
280 // Load length directly from the JS array. | |
281 __ mov(eax, FieldOperand(receiver, JSArray::kLengthOffset)); | |
282 __ ret(0); | |
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); | 256 __ TryGetFunctionPrototype(receiver, scratch1, scratch2, miss_label); |
292 __ mov(eax, scratch1); | 257 __ mov(eax, scratch1); |
293 __ ret(0); | 258 __ ret(0); |
294 } | 259 } |
295 | 260 |
296 | 261 |
297 void StubCompiler::GenerateFastPropertyLoad(MacroAssembler* masm, | |
298 Register dst, | |
299 Register src, | |
300 bool inobject, | |
301 int index, | |
302 Representation representation) { | |
303 ASSERT(!representation.IsDouble()); | |
304 int offset = index * kPointerSize; | |
305 if (!inobject) { | |
306 // Calculate the offset into the properties array. | |
307 offset = offset + FixedArray::kHeaderSize; | |
308 __ mov(dst, FieldOperand(src, JSObject::kPropertiesOffset)); | |
309 src = dst; | |
310 } | |
311 __ mov(dst, FieldOperand(src, offset)); | |
312 } | |
313 | |
314 | |
315 static void PushInterceptorArguments(MacroAssembler* masm, | 262 static void PushInterceptorArguments(MacroAssembler* masm, |
316 Register receiver, | 263 Register receiver, |
317 Register holder, | 264 Register holder, |
318 Register name, | 265 Register name, |
319 Handle<JSObject> holder_obj) { | 266 Handle<JSObject> holder_obj) { |
320 STATIC_ASSERT(StubCache::kInterceptorArgsNameIndex == 0); | 267 STATIC_ASSERT(StubCache::kInterceptorArgsNameIndex == 0); |
321 STATIC_ASSERT(StubCache::kInterceptorArgsInfoIndex == 1); | 268 STATIC_ASSERT(StubCache::kInterceptorArgsInfoIndex == 1); |
322 STATIC_ASSERT(StubCache::kInterceptorArgsThisIndex == 2); | 269 STATIC_ASSERT(StubCache::kInterceptorArgsThisIndex == 2); |
323 STATIC_ASSERT(StubCache::kInterceptorArgsHolderIndex == 3); | 270 STATIC_ASSERT(StubCache::kInterceptorArgsHolderIndex == 3); |
324 STATIC_ASSERT(StubCache::kInterceptorArgsLength == 4); | 271 STATIC_ASSERT(StubCache::kInterceptorArgsLength == 4); |
(...skipping 19 matching lines...) Expand all Loading... |
344 __ CallExternalReference( | 291 __ CallExternalReference( |
345 ExternalReference(IC_Utility(id), masm->isolate()), | 292 ExternalReference(IC_Utility(id), masm->isolate()), |
346 StubCache::kInterceptorArgsLength); | 293 StubCache::kInterceptorArgsLength); |
347 } | 294 } |
348 | 295 |
349 | 296 |
350 // Generate call to api function. | 297 // Generate call to api function. |
351 // This function uses push() to generate smaller, faster code than | 298 // This function uses push() to generate smaller, faster code than |
352 // the version above. It is an optimization that should will be removed | 299 // the version above. It is an optimization that should will be removed |
353 // when api call ICs are generated in hydrogen. | 300 // when api call ICs are generated in hydrogen. |
354 void StubCompiler::GenerateFastApiCall(MacroAssembler* masm, | 301 void PropertyHandlerCompiler::GenerateFastApiCall( |
355 const CallOptimization& optimization, | 302 MacroAssembler* masm, const CallOptimization& optimization, |
356 Handle<Map> receiver_map, | 303 Handle<Map> receiver_map, Register receiver, Register scratch_in, |
357 Register receiver, | 304 bool is_store, int argc, Register* values) { |
358 Register scratch_in, | |
359 bool is_store, | |
360 int argc, | |
361 Register* values) { | |
362 // Copy return value. | 305 // Copy return value. |
363 __ pop(scratch_in); | 306 __ pop(scratch_in); |
364 // receiver | 307 // receiver |
365 __ push(receiver); | 308 __ push(receiver); |
366 // Write the arguments to stack frame. | 309 // Write the arguments to stack frame. |
367 for (int i = 0; i < argc; i++) { | 310 for (int i = 0; i < argc; i++) { |
368 Register arg = values[argc-1-i]; | 311 Register arg = values[argc-1-i]; |
369 ASSERT(!receiver.is(arg)); | 312 ASSERT(!receiver.is(arg)); |
370 ASSERT(!scratch_in.is(arg)); | 313 ASSERT(!scratch_in.is(arg)); |
371 __ push(arg); | 314 __ push(arg); |
(...skipping 49 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
421 // Put api_function_address in place. | 364 // Put api_function_address in place. |
422 Address function_address = v8::ToCData<Address>(api_call_info->callback()); | 365 Address function_address = v8::ToCData<Address>(api_call_info->callback()); |
423 __ mov(api_function_address, Immediate(function_address)); | 366 __ mov(api_function_address, Immediate(function_address)); |
424 | 367 |
425 // Jump to stub. | 368 // Jump to stub. |
426 CallApiFunctionStub stub(isolate, is_store, call_data_undefined, argc); | 369 CallApiFunctionStub stub(isolate, is_store, call_data_undefined, argc); |
427 __ TailCallStub(&stub); | 370 __ TailCallStub(&stub); |
428 } | 371 } |
429 | 372 |
430 | 373 |
431 void StoreStubCompiler::GenerateRestoreName(MacroAssembler* masm, | 374 void NamedStoreHandlerCompiler::GenerateRestoreName(MacroAssembler* masm, |
432 Label* label, | 375 Label* label, |
433 Handle<Name> name) { | 376 Handle<Name> name) { |
434 if (!label->is_unused()) { | 377 if (!label->is_unused()) { |
435 __ bind(label); | 378 __ bind(label); |
436 __ mov(this->name(), Immediate(name)); | 379 __ mov(this->name(), Immediate(name)); |
437 } | 380 } |
438 } | 381 } |
439 | 382 |
440 | 383 |
441 // Generate code to check that a global property cell is empty. Create | 384 // Generate code to check that a global property cell is empty. Create |
442 // the property cell at compilation time if no cell exists for the | 385 // the property cell at compilation time if no cell exists for the |
443 // property. | 386 // property. |
444 void StubCompiler::GenerateCheckPropertyCell(MacroAssembler* masm, | 387 void PropertyHandlerCompiler::GenerateCheckPropertyCell( |
445 Handle<JSGlobalObject> global, | 388 MacroAssembler* masm, Handle<JSGlobalObject> global, Handle<Name> name, |
446 Handle<Name> name, | 389 Register scratch, Label* miss) { |
447 Register scratch, | |
448 Label* miss) { | |
449 Handle<PropertyCell> cell = | 390 Handle<PropertyCell> cell = |
450 JSGlobalObject::EnsurePropertyCell(global, name); | 391 JSGlobalObject::EnsurePropertyCell(global, name); |
451 ASSERT(cell->value()->IsTheHole()); | 392 ASSERT(cell->value()->IsTheHole()); |
452 Handle<Oddball> the_hole = masm->isolate()->factory()->the_hole_value(); | 393 Handle<Oddball> the_hole = masm->isolate()->factory()->the_hole_value(); |
453 if (masm->serializer_enabled()) { | 394 if (masm->serializer_enabled()) { |
454 __ mov(scratch, Immediate(cell)); | 395 __ mov(scratch, Immediate(cell)); |
455 __ cmp(FieldOperand(scratch, PropertyCell::kValueOffset), | 396 __ cmp(FieldOperand(scratch, PropertyCell::kValueOffset), |
456 Immediate(the_hole)); | 397 Immediate(the_hole)); |
457 } else { | 398 } else { |
458 __ cmp(Operand::ForCell(cell), Immediate(the_hole)); | 399 __ cmp(Operand::ForCell(cell), Immediate(the_hole)); |
459 } | 400 } |
460 __ j(not_equal, miss); | 401 __ j(not_equal, miss); |
461 } | 402 } |
462 | 403 |
463 | 404 |
464 void StoreStubCompiler::GenerateNegativeHolderLookup( | 405 void NamedStoreHandlerCompiler::GenerateNegativeHolderLookup( |
465 MacroAssembler* masm, | 406 MacroAssembler* masm, Handle<JSObject> holder, Register holder_reg, |
466 Handle<JSObject> holder, | 407 Handle<Name> name, Label* miss) { |
467 Register holder_reg, | |
468 Handle<Name> name, | |
469 Label* miss) { | |
470 if (holder->IsJSGlobalObject()) { | 408 if (holder->IsJSGlobalObject()) { |
471 GenerateCheckPropertyCell( | 409 GenerateCheckPropertyCell( |
472 masm, Handle<JSGlobalObject>::cast(holder), name, scratch1(), miss); | 410 masm, Handle<JSGlobalObject>::cast(holder), name, scratch1(), miss); |
473 } else if (!holder->HasFastProperties() && !holder->IsJSGlobalProxy()) { | 411 } else if (!holder->HasFastProperties() && !holder->IsJSGlobalProxy()) { |
474 GenerateDictionaryNegativeLookup( | 412 GenerateDictionaryNegativeLookup( |
475 masm, miss, holder_reg, name, scratch1(), scratch2()); | 413 masm, miss, holder_reg, name, scratch1(), scratch2()); |
476 } | 414 } |
477 } | 415 } |
478 | 416 |
479 | 417 |
480 // Receiver_reg is preserved on jumps to miss_label, but may be destroyed if | 418 // Receiver_reg is preserved on jumps to miss_label, but may be destroyed if |
481 // store is successful. | 419 // store is successful. |
482 void StoreStubCompiler::GenerateStoreTransition(MacroAssembler* masm, | 420 void NamedStoreHandlerCompiler::GenerateStoreTransition( |
483 Handle<JSObject> object, | 421 MacroAssembler* masm, Handle<JSObject> object, LookupResult* lookup, |
484 LookupResult* lookup, | 422 Handle<Map> transition, Handle<Name> name, Register receiver_reg, |
485 Handle<Map> transition, | 423 Register storage_reg, Register value_reg, Register scratch1, |
486 Handle<Name> name, | 424 Register scratch2, Register unused, Label* miss_label, Label* slow) { |
487 Register receiver_reg, | |
488 Register storage_reg, | |
489 Register value_reg, | |
490 Register scratch1, | |
491 Register scratch2, | |
492 Register unused, | |
493 Label* miss_label, | |
494 Label* slow) { | |
495 int descriptor = transition->LastAdded(); | 425 int descriptor = transition->LastAdded(); |
496 DescriptorArray* descriptors = transition->instance_descriptors(); | 426 DescriptorArray* descriptors = transition->instance_descriptors(); |
497 PropertyDetails details = descriptors->GetDetails(descriptor); | 427 PropertyDetails details = descriptors->GetDetails(descriptor); |
498 Representation representation = details.representation(); | 428 Representation representation = details.representation(); |
499 ASSERT(!representation.IsNone()); | 429 ASSERT(!representation.IsNone()); |
500 | 430 |
501 if (details.type() == CONSTANT) { | 431 if (details.type() == CONSTANT) { |
502 Handle<Object> constant(descriptors->GetValue(descriptor), masm->isolate()); | 432 Handle<Object> constant(descriptors->GetValue(descriptor), masm->isolate()); |
503 __ CmpObject(value_reg, constant); | 433 __ CmpObject(value_reg, constant); |
504 __ j(not_equal, miss_label); | 434 __ j(not_equal, miss_label); |
(...skipping 135 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
640 } | 570 } |
641 | 571 |
642 // Return the value (register eax). | 572 // Return the value (register eax). |
643 ASSERT(value_reg.is(eax)); | 573 ASSERT(value_reg.is(eax)); |
644 __ ret(0); | 574 __ ret(0); |
645 } | 575 } |
646 | 576 |
647 | 577 |
648 // Both name_reg and receiver_reg are preserved on jumps to miss_label, | 578 // Both name_reg and receiver_reg are preserved on jumps to miss_label, |
649 // but may be destroyed if store is successful. | 579 // but may be destroyed if store is successful. |
650 void StoreStubCompiler::GenerateStoreField(MacroAssembler* masm, | 580 void NamedStoreHandlerCompiler::GenerateStoreField( |
651 Handle<JSObject> object, | 581 MacroAssembler* masm, Handle<JSObject> object, LookupResult* lookup, |
652 LookupResult* lookup, | 582 Register receiver_reg, Register name_reg, Register value_reg, |
653 Register receiver_reg, | 583 Register scratch1, Register scratch2, Label* miss_label) { |
654 Register name_reg, | |
655 Register value_reg, | |
656 Register scratch1, | |
657 Register scratch2, | |
658 Label* miss_label) { | |
659 // Stub never generated for non-global objects that require access | 584 // Stub never generated for non-global objects that require access |
660 // checks. | 585 // checks. |
661 ASSERT(object->IsJSGlobalProxy() || !object->IsAccessCheckNeeded()); | 586 ASSERT(object->IsJSGlobalProxy() || !object->IsAccessCheckNeeded()); |
662 | 587 |
663 FieldIndex index = lookup->GetFieldIndex(); | 588 FieldIndex index = lookup->GetFieldIndex(); |
664 | 589 |
665 Representation representation = lookup->representation(); | 590 Representation representation = lookup->representation(); |
666 ASSERT(!representation.IsNone()); | 591 ASSERT(!representation.IsNone()); |
667 if (representation.IsSmi()) { | 592 if (representation.IsSmi()) { |
668 __ JumpIfNotSmi(value_reg, miss_label); | 593 __ JumpIfNotSmi(value_reg, miss_label); |
(...skipping 81 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
750 smi_check); | 675 smi_check); |
751 } | 676 } |
752 } | 677 } |
753 | 678 |
754 // Return the value (register eax). | 679 // Return the value (register eax). |
755 ASSERT(value_reg.is(eax)); | 680 ASSERT(value_reg.is(eax)); |
756 __ ret(0); | 681 __ ret(0); |
757 } | 682 } |
758 | 683 |
759 | 684 |
760 void StubCompiler::GenerateTailCall(MacroAssembler* masm, Handle<Code> code) { | 685 void PropertyAccessCompiler::GenerateTailCall(MacroAssembler* masm, |
| 686 Handle<Code> code) { |
761 __ jmp(code, RelocInfo::CODE_TARGET); | 687 __ jmp(code, RelocInfo::CODE_TARGET); |
762 } | 688 } |
763 | 689 |
764 | 690 |
765 #undef __ | 691 #undef __ |
766 #define __ ACCESS_MASM(masm()) | 692 #define __ ACCESS_MASM(masm()) |
767 | 693 |
768 | 694 |
769 Register StubCompiler::CheckPrototypes(Handle<HeapType> type, | 695 Register PropertyHandlerCompiler::CheckPrototypes( |
770 Register object_reg, | 696 Handle<HeapType> type, Register object_reg, Handle<JSObject> holder, |
771 Handle<JSObject> holder, | 697 Register holder_reg, Register scratch1, Register scratch2, |
772 Register holder_reg, | 698 Handle<Name> name, Label* miss, PrototypeCheckType check) { |
773 Register scratch1, | |
774 Register scratch2, | |
775 Handle<Name> name, | |
776 Label* miss, | |
777 PrototypeCheckType check) { | |
778 Handle<Map> receiver_map(IC::TypeToMap(*type, isolate())); | 699 Handle<Map> receiver_map(IC::TypeToMap(*type, isolate())); |
779 | 700 |
780 // Make sure there's no overlap between holder and object registers. | 701 // Make sure there's no overlap between holder and object registers. |
781 ASSERT(!scratch1.is(object_reg) && !scratch1.is(holder_reg)); | 702 ASSERT(!scratch1.is(object_reg) && !scratch1.is(holder_reg)); |
782 ASSERT(!scratch2.is(object_reg) && !scratch2.is(holder_reg) | 703 ASSERT(!scratch2.is(object_reg) && !scratch2.is(holder_reg) |
783 && !scratch2.is(scratch1)); | 704 && !scratch2.is(scratch1)); |
784 | 705 |
785 // Keep track of the current object in register reg. | 706 // Keep track of the current object in register reg. |
786 Register reg = object_reg; | 707 Register reg = object_reg; |
787 int depth = 0; | 708 int depth = 0; |
(...skipping 86 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
874 !current_map->is_access_check_needed()); | 795 !current_map->is_access_check_needed()); |
875 if (current_map->IsJSGlobalProxyMap()) { | 796 if (current_map->IsJSGlobalProxyMap()) { |
876 __ CheckAccessGlobalProxy(reg, scratch1, scratch2, miss); | 797 __ CheckAccessGlobalProxy(reg, scratch1, scratch2, miss); |
877 } | 798 } |
878 | 799 |
879 // Return the register containing the holder. | 800 // Return the register containing the holder. |
880 return reg; | 801 return reg; |
881 } | 802 } |
882 | 803 |
883 | 804 |
884 void LoadStubCompiler::HandlerFrontendFooter(Handle<Name> name, Label* miss) { | 805 void NamedLoadHandlerCompiler::FrontendFooter(Handle<Name> name, Label* miss) { |
885 if (!miss->is_unused()) { | 806 if (!miss->is_unused()) { |
886 Label success; | 807 Label success; |
887 __ jmp(&success); | 808 __ jmp(&success); |
888 __ bind(miss); | 809 __ bind(miss); |
889 TailCallBuiltin(masm(), MissBuiltin(kind())); | 810 TailCallBuiltin(masm(), MissBuiltin(kind())); |
890 __ bind(&success); | 811 __ bind(&success); |
891 } | 812 } |
892 } | 813 } |
893 | 814 |
894 | 815 |
895 void StoreStubCompiler::HandlerFrontendFooter(Handle<Name> name, Label* miss) { | 816 void NamedStoreHandlerCompiler::FrontendFooter(Handle<Name> name, Label* miss) { |
896 if (!miss->is_unused()) { | 817 if (!miss->is_unused()) { |
897 Label success; | 818 Label success; |
898 __ jmp(&success); | 819 __ jmp(&success); |
899 GenerateRestoreName(masm(), miss, name); | 820 GenerateRestoreName(masm(), miss, name); |
900 TailCallBuiltin(masm(), MissBuiltin(kind())); | 821 TailCallBuiltin(masm(), MissBuiltin(kind())); |
901 __ bind(&success); | 822 __ bind(&success); |
902 } | 823 } |
903 } | 824 } |
904 | 825 |
905 | 826 |
906 Register LoadStubCompiler::CallbackHandlerFrontend( | 827 Register NamedLoadHandlerCompiler::CallbackFrontend(Handle<HeapType> type, |
907 Handle<HeapType> type, | 828 Register object_reg, |
908 Register object_reg, | 829 Handle<JSObject> holder, |
909 Handle<JSObject> holder, | 830 Handle<Name> name, |
910 Handle<Name> name, | 831 Handle<Object> callback) { |
911 Handle<Object> callback) { | |
912 Label miss; | 832 Label miss; |
913 | 833 |
914 Register reg = HandlerFrontendHeader(type, object_reg, holder, name, &miss); | 834 Register reg = FrontendHeader(type, object_reg, holder, name, &miss); |
915 | 835 |
916 if (!holder->HasFastProperties() && !holder->IsJSGlobalObject()) { | 836 if (!holder->HasFastProperties() && !holder->IsJSGlobalObject()) { |
917 ASSERT(!reg.is(scratch2())); | 837 ASSERT(!reg.is(scratch2())); |
918 ASSERT(!reg.is(scratch3())); | 838 ASSERT(!reg.is(scratch3())); |
919 Register dictionary = scratch1(); | 839 Register dictionary = scratch1(); |
920 bool must_preserve_dictionary_reg = reg.is(dictionary); | 840 bool must_preserve_dictionary_reg = reg.is(dictionary); |
921 | 841 |
922 // Load the properties dictionary. | 842 // Load the properties dictionary. |
923 if (must_preserve_dictionary_reg) { | 843 if (must_preserve_dictionary_reg) { |
924 __ push(dictionary); | 844 __ push(dictionary); |
(...skipping 25 matching lines...) Expand all Loading... |
950 const int kValueOffset = kElementsStartOffset + kPointerSize; | 870 const int kValueOffset = kElementsStartOffset + kPointerSize; |
951 __ mov(scratch3(), | 871 __ mov(scratch3(), |
952 Operand(dictionary, index, times_4, kValueOffset - kHeapObjectTag)); | 872 Operand(dictionary, index, times_4, kValueOffset - kHeapObjectTag)); |
953 if (must_preserve_dictionary_reg) { | 873 if (must_preserve_dictionary_reg) { |
954 __ pop(dictionary); | 874 __ pop(dictionary); |
955 } | 875 } |
956 __ cmp(scratch3(), callback); | 876 __ cmp(scratch3(), callback); |
957 __ j(not_equal, &miss); | 877 __ j(not_equal, &miss); |
958 } | 878 } |
959 | 879 |
960 HandlerFrontendFooter(name, &miss); | 880 FrontendFooter(name, &miss); |
961 return reg; | 881 return reg; |
962 } | 882 } |
963 | 883 |
964 | 884 |
965 void LoadStubCompiler::GenerateLoadField(Register reg, | 885 void NamedLoadHandlerCompiler::GenerateLoadField( |
966 Handle<JSObject> holder, | 886 Register reg, Handle<JSObject> holder, FieldIndex field, |
967 FieldIndex field, | 887 Representation representation) { |
968 Representation representation) { | |
969 if (!reg.is(receiver())) __ mov(receiver(), reg); | 888 if (!reg.is(receiver())) __ mov(receiver(), reg); |
970 LoadFieldStub stub(isolate(), field); | 889 LoadFieldStub stub(isolate(), field); |
971 GenerateTailCall(masm(), stub.GetCode()); | 890 GenerateTailCall(masm(), stub.GetCode()); |
972 } | 891 } |
973 | 892 |
974 | 893 |
975 void LoadStubCompiler::GenerateLoadCallback( | 894 void NamedLoadHandlerCompiler::GenerateLoadCallback( |
976 Register reg, | 895 Register reg, Handle<ExecutableAccessorInfo> callback) { |
977 Handle<ExecutableAccessorInfo> callback) { | |
978 // Insert additional parameters into the stack frame above return address. | 896 // Insert additional parameters into the stack frame above return address. |
979 ASSERT(!scratch3().is(reg)); | 897 ASSERT(!scratch3().is(reg)); |
980 __ pop(scratch3()); // Get return address to place it below. | 898 __ pop(scratch3()); // Get return address to place it below. |
981 | 899 |
982 STATIC_ASSERT(PropertyCallbackArguments::kHolderIndex == 0); | 900 STATIC_ASSERT(PropertyCallbackArguments::kHolderIndex == 0); |
983 STATIC_ASSERT(PropertyCallbackArguments::kIsolateIndex == 1); | 901 STATIC_ASSERT(PropertyCallbackArguments::kIsolateIndex == 1); |
984 STATIC_ASSERT(PropertyCallbackArguments::kReturnValueDefaultValueIndex == 2); | 902 STATIC_ASSERT(PropertyCallbackArguments::kReturnValueDefaultValueIndex == 2); |
985 STATIC_ASSERT(PropertyCallbackArguments::kReturnValueOffset == 3); | 903 STATIC_ASSERT(PropertyCallbackArguments::kReturnValueOffset == 3); |
986 STATIC_ASSERT(PropertyCallbackArguments::kDataIndex == 4); | 904 STATIC_ASSERT(PropertyCallbackArguments::kDataIndex == 4); |
987 STATIC_ASSERT(PropertyCallbackArguments::kThisIndex == 5); | 905 STATIC_ASSERT(PropertyCallbackArguments::kThisIndex == 5); |
(...skipping 23 matching lines...) Expand all Loading... |
1011 // Abi for CallApiGetter | 929 // Abi for CallApiGetter |
1012 Register getter_address = edx; | 930 Register getter_address = edx; |
1013 Address function_address = v8::ToCData<Address>(callback->getter()); | 931 Address function_address = v8::ToCData<Address>(callback->getter()); |
1014 __ mov(getter_address, Immediate(function_address)); | 932 __ mov(getter_address, Immediate(function_address)); |
1015 | 933 |
1016 CallApiGetterStub stub(isolate()); | 934 CallApiGetterStub stub(isolate()); |
1017 __ TailCallStub(&stub); | 935 __ TailCallStub(&stub); |
1018 } | 936 } |
1019 | 937 |
1020 | 938 |
1021 void LoadStubCompiler::GenerateLoadConstant(Handle<Object> value) { | 939 void NamedLoadHandlerCompiler::GenerateLoadConstant(Handle<Object> value) { |
1022 // Return the constant value. | 940 // Return the constant value. |
1023 __ LoadObject(eax, value); | 941 __ LoadObject(eax, value); |
1024 __ ret(0); | 942 __ ret(0); |
1025 } | 943 } |
1026 | 944 |
1027 | 945 |
1028 void LoadStubCompiler::GenerateLoadInterceptor( | 946 void NamedLoadHandlerCompiler::GenerateLoadInterceptor( |
1029 Register holder_reg, | 947 Register holder_reg, Handle<Object> object, |
1030 Handle<Object> object, | 948 Handle<JSObject> interceptor_holder, LookupResult* lookup, |
1031 Handle<JSObject> interceptor_holder, | |
1032 LookupResult* lookup, | |
1033 Handle<Name> name) { | 949 Handle<Name> name) { |
1034 ASSERT(interceptor_holder->HasNamedInterceptor()); | 950 ASSERT(interceptor_holder->HasNamedInterceptor()); |
1035 ASSERT(!interceptor_holder->GetNamedInterceptor()->getter()->IsUndefined()); | 951 ASSERT(!interceptor_holder->GetNamedInterceptor()->getter()->IsUndefined()); |
1036 | 952 |
1037 // So far the most popular follow ups for interceptor loads are FIELD | 953 // So far the most popular follow ups for interceptor loads are FIELD |
1038 // and CALLBACKS, so inline only them, other cases may be added | 954 // and CALLBACKS, so inline only them, other cases may be added |
1039 // later. | 955 // later. |
1040 bool compile_followup_inline = false; | 956 bool compile_followup_inline = false; |
1041 if (lookup->IsFound() && lookup->IsCacheable()) { | 957 if (lookup->IsFound() && lookup->IsCacheable()) { |
1042 if (lookup->IsField()) { | 958 if (lookup->IsField()) { |
(...skipping 74 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1117 __ push(scratch2()); // restore old return address | 1033 __ push(scratch2()); // restore old return address |
1118 | 1034 |
1119 ExternalReference ref = | 1035 ExternalReference ref = |
1120 ExternalReference(IC_Utility(IC::kLoadPropertyWithInterceptor), | 1036 ExternalReference(IC_Utility(IC::kLoadPropertyWithInterceptor), |
1121 isolate()); | 1037 isolate()); |
1122 __ TailCallExternalReference(ref, StubCache::kInterceptorArgsLength, 1); | 1038 __ TailCallExternalReference(ref, StubCache::kInterceptorArgsLength, 1); |
1123 } | 1039 } |
1124 } | 1040 } |
1125 | 1041 |
1126 | 1042 |
1127 Handle<Code> StoreStubCompiler::CompileStoreCallback( | 1043 Handle<Code> NamedStoreHandlerCompiler::CompileStoreCallback( |
1128 Handle<JSObject> object, | 1044 Handle<JSObject> object, Handle<JSObject> holder, Handle<Name> name, |
1129 Handle<JSObject> holder, | |
1130 Handle<Name> name, | |
1131 Handle<ExecutableAccessorInfo> callback) { | 1045 Handle<ExecutableAccessorInfo> callback) { |
1132 Register holder_reg = HandlerFrontend( | 1046 Register holder_reg = |
1133 IC::CurrentTypeOf(object, isolate()), receiver(), holder, name); | 1047 Frontend(IC::CurrentTypeOf(object, isolate()), receiver(), holder, name); |
1134 | 1048 |
1135 __ pop(scratch1()); // remove the return address | 1049 __ pop(scratch1()); // remove the return address |
1136 __ push(receiver()); | 1050 __ push(receiver()); |
1137 __ push(holder_reg); | 1051 __ push(holder_reg); |
1138 __ Push(callback); | 1052 __ Push(callback); |
1139 __ Push(name); | 1053 __ Push(name); |
1140 __ push(value()); | 1054 __ push(value()); |
1141 __ push(scratch1()); // restore return address | 1055 __ push(scratch1()); // restore return address |
1142 | 1056 |
1143 // Do tail-call to the runtime system. | 1057 // Do tail-call to the runtime system. |
1144 ExternalReference store_callback_property = | 1058 ExternalReference store_callback_property = |
1145 ExternalReference(IC_Utility(IC::kStoreCallbackProperty), isolate()); | 1059 ExternalReference(IC_Utility(IC::kStoreCallbackProperty), isolate()); |
1146 __ TailCallExternalReference(store_callback_property, 5, 1); | 1060 __ TailCallExternalReference(store_callback_property, 5, 1); |
1147 | 1061 |
1148 // Return the generated code. | 1062 // Return the generated code. |
1149 return GetCode(kind(), Code::FAST, name); | 1063 return GetCode(kind(), Code::FAST, name); |
1150 } | 1064 } |
1151 | 1065 |
1152 | 1066 |
1153 #undef __ | 1067 #undef __ |
1154 #define __ ACCESS_MASM(masm) | 1068 #define __ ACCESS_MASM(masm) |
1155 | 1069 |
1156 | 1070 |
1157 void StoreStubCompiler::GenerateStoreViaSetter( | 1071 void NamedStoreHandlerCompiler::GenerateStoreViaSetter( |
1158 MacroAssembler* masm, | 1072 MacroAssembler* masm, Handle<HeapType> type, Register receiver, |
1159 Handle<HeapType> type, | |
1160 Register receiver, | |
1161 Handle<JSFunction> setter) { | 1073 Handle<JSFunction> setter) { |
1162 // ----------- S t a t e ------------- | 1074 // ----------- S t a t e ------------- |
1163 // -- esp[0] : return address | 1075 // -- esp[0] : return address |
1164 // ----------------------------------- | 1076 // ----------------------------------- |
1165 { | 1077 { |
1166 FrameScope scope(masm, StackFrame::INTERNAL); | 1078 FrameScope scope(masm, StackFrame::INTERNAL); |
1167 | 1079 |
1168 // Save value register, so we can restore it later. | 1080 // Save value register, so we can restore it later. |
1169 __ push(value()); | 1081 __ push(value()); |
1170 | 1082 |
(...skipping 23 matching lines...) Expand all Loading... |
1194 __ mov(esi, Operand(ebp, StandardFrameConstants::kContextOffset)); | 1106 __ mov(esi, Operand(ebp, StandardFrameConstants::kContextOffset)); |
1195 } | 1107 } |
1196 __ ret(0); | 1108 __ ret(0); |
1197 } | 1109 } |
1198 | 1110 |
1199 | 1111 |
1200 #undef __ | 1112 #undef __ |
1201 #define __ ACCESS_MASM(masm()) | 1113 #define __ ACCESS_MASM(masm()) |
1202 | 1114 |
1203 | 1115 |
1204 Handle<Code> StoreStubCompiler::CompileStoreInterceptor( | 1116 Handle<Code> NamedStoreHandlerCompiler::CompileStoreInterceptor( |
1205 Handle<JSObject> object, | 1117 Handle<JSObject> object, Handle<Name> name) { |
1206 Handle<Name> name) { | |
1207 __ pop(scratch1()); // remove the return address | 1118 __ pop(scratch1()); // remove the return address |
1208 __ push(receiver()); | 1119 __ push(receiver()); |
1209 __ push(this->name()); | 1120 __ push(this->name()); |
1210 __ push(value()); | 1121 __ push(value()); |
1211 __ push(scratch1()); // restore return address | 1122 __ push(scratch1()); // restore return address |
1212 | 1123 |
1213 // Do tail-call to the runtime system. | 1124 // Do tail-call to the runtime system. |
1214 ExternalReference store_ic_property = | 1125 ExternalReference store_ic_property = |
1215 ExternalReference(IC_Utility(IC::kStoreInterceptorProperty), isolate()); | 1126 ExternalReference(IC_Utility(IC::kStoreInterceptorProperty), isolate()); |
1216 __ TailCallExternalReference(store_ic_property, 3, 1); | 1127 __ TailCallExternalReference(store_ic_property, 3, 1); |
1217 | 1128 |
1218 // Return the generated code. | 1129 // Return the generated code. |
1219 return GetCode(kind(), Code::FAST, name); | 1130 return GetCode(kind(), Code::FAST, name); |
1220 } | 1131 } |
1221 | 1132 |
1222 | 1133 |
1223 void StoreStubCompiler::GenerateStoreArrayLength() { | 1134 void NamedStoreHandlerCompiler::GenerateStoreArrayLength() { |
1224 // Prepare tail call to StoreIC_ArrayLength. | 1135 // Prepare tail call to StoreIC_ArrayLength. |
1225 __ pop(scratch1()); // remove the return address | 1136 __ pop(scratch1()); // remove the return address |
1226 __ push(receiver()); | 1137 __ push(receiver()); |
1227 __ push(value()); | 1138 __ push(value()); |
1228 __ push(scratch1()); // restore return address | 1139 __ push(scratch1()); // restore return address |
1229 | 1140 |
1230 ExternalReference ref = | 1141 ExternalReference ref = |
1231 ExternalReference(IC_Utility(IC::kStoreIC_ArrayLength), | 1142 ExternalReference(IC_Utility(IC::kStoreIC_ArrayLength), |
1232 masm()->isolate()); | 1143 masm()->isolate()); |
1233 __ TailCallExternalReference(ref, 2, 1); | 1144 __ TailCallExternalReference(ref, 2, 1); |
1234 } | 1145 } |
1235 | 1146 |
1236 | 1147 |
1237 Handle<Code> KeyedStoreStubCompiler::CompileStorePolymorphic( | 1148 Handle<Code> PropertyICCompiler::CompileIndexedStorePolymorphic( |
1238 MapHandleList* receiver_maps, | 1149 MapHandleList* receiver_maps, CodeHandleList* handler_stubs, |
1239 CodeHandleList* handler_stubs, | |
1240 MapHandleList* transitioned_maps) { | 1150 MapHandleList* transitioned_maps) { |
1241 Label miss; | 1151 Label miss; |
1242 __ JumpIfSmi(receiver(), &miss, Label::kNear); | 1152 __ JumpIfSmi(receiver(), &miss, Label::kNear); |
1243 __ mov(scratch1(), FieldOperand(receiver(), HeapObject::kMapOffset)); | 1153 __ mov(scratch1(), FieldOperand(receiver(), HeapObject::kMapOffset)); |
1244 for (int i = 0; i < receiver_maps->length(); ++i) { | 1154 for (int i = 0; i < receiver_maps->length(); ++i) { |
1245 __ cmp(scratch1(), receiver_maps->at(i)); | 1155 __ cmp(scratch1(), receiver_maps->at(i)); |
1246 if (transitioned_maps->at(i).is_null()) { | 1156 if (transitioned_maps->at(i).is_null()) { |
1247 __ j(equal, handler_stubs->at(i)); | 1157 __ j(equal, handler_stubs->at(i)); |
1248 } else { | 1158 } else { |
1249 Label next_map; | 1159 Label next_map; |
1250 __ j(not_equal, &next_map, Label::kNear); | 1160 __ j(not_equal, &next_map, Label::kNear); |
1251 __ mov(transition_map(), Immediate(transitioned_maps->at(i))); | 1161 __ mov(transition_map(), Immediate(transitioned_maps->at(i))); |
1252 __ jmp(handler_stubs->at(i), RelocInfo::CODE_TARGET); | 1162 __ jmp(handler_stubs->at(i), RelocInfo::CODE_TARGET); |
1253 __ bind(&next_map); | 1163 __ bind(&next_map); |
1254 } | 1164 } |
1255 } | 1165 } |
1256 __ bind(&miss); | 1166 __ bind(&miss); |
1257 TailCallBuiltin(masm(), MissBuiltin(kind())); | 1167 TailCallBuiltin(masm(), MissBuiltin(kind())); |
1258 | 1168 |
1259 // Return the generated code. | 1169 // Return the generated code. |
1260 return GetICCode( | 1170 return GetCode(kind(), Code::NORMAL, factory()->empty_string(), POLYMORPHIC); |
1261 kind(), Code::NORMAL, factory()->empty_string(), POLYMORPHIC); | |
1262 } | 1171 } |
1263 | 1172 |
1264 | 1173 |
1265 Handle<Code> LoadStubCompiler::CompileLoadNonexistent(Handle<HeapType> type, | 1174 Handle<Code> NamedLoadHandlerCompiler::CompileLoadNonexistent( |
1266 Handle<JSObject> last, | 1175 Handle<HeapType> type, Handle<JSObject> last, Handle<Name> name) { |
1267 Handle<Name> name) { | 1176 NonexistentFrontend(type, last, name); |
1268 NonexistentHandlerFrontend(type, last, name); | |
1269 | 1177 |
1270 // Return undefined if maps of the full prototype chain are still the | 1178 // Return undefined if maps of the full prototype chain are still the |
1271 // same and no global property with this name contains a value. | 1179 // same and no global property with this name contains a value. |
1272 __ mov(eax, isolate()->factory()->undefined_value()); | 1180 __ mov(eax, isolate()->factory()->undefined_value()); |
1273 __ ret(0); | 1181 __ ret(0); |
1274 | 1182 |
1275 // Return the generated code. | 1183 // Return the generated code. |
1276 return GetCode(kind(), Code::FAST, name); | 1184 return GetCode(kind(), Code::FAST, name); |
1277 } | 1185 } |
1278 | 1186 |
1279 | 1187 |
1280 Register* LoadStubCompiler::registers() { | 1188 Register* PropertyAccessCompiler::load_calling_convention() { |
1281 // receiver, name, scratch1, scratch2, scratch3, scratch4. | 1189 // receiver, name, scratch1, scratch2, scratch3, scratch4. |
1282 Register receiver = LoadIC::ReceiverRegister(); | 1190 Register receiver = LoadIC::ReceiverRegister(); |
1283 Register name = LoadIC::NameRegister(); | 1191 Register name = LoadIC::NameRegister(); |
1284 static Register registers[] = { receiver, name, ebx, eax, edi, no_reg }; | |
1285 return registers; | |
1286 } | |
1287 | |
1288 | |
1289 Register* KeyedLoadStubCompiler::registers() { | |
1290 // receiver, name, scratch1, scratch2, scratch3, scratch4. | |
1291 Register receiver = LoadIC::ReceiverRegister(); | |
1292 Register name = LoadIC::NameRegister(); | |
1293 static Register registers[] = { receiver, name, ebx, eax, edi, no_reg }; | 1192 static Register registers[] = { receiver, name, ebx, eax, edi, no_reg }; |
1294 return registers; | 1193 return registers; |
1295 } | 1194 } |
1296 | 1195 |
1297 | 1196 |
1298 Register StoreStubCompiler::value() { | 1197 Register* PropertyAccessCompiler::store_calling_convention() { |
1299 return StoreIC::ValueRegister(); | |
1300 } | |
1301 | |
1302 | |
1303 Register* StoreStubCompiler::registers() { | |
1304 // receiver, name, scratch1, scratch2, scratch3. | 1198 // receiver, name, scratch1, scratch2, scratch3. |
1305 Register receiver = StoreIC::ReceiverRegister(); | 1199 Register receiver = StoreIC::ReceiverRegister(); |
1306 Register name = StoreIC::NameRegister(); | 1200 Register name = StoreIC::NameRegister(); |
1307 static Register registers[] = { receiver, name, ebx, edi, no_reg }; | 1201 static Register registers[] = { receiver, name, ebx, edi, no_reg }; |
1308 return registers; | 1202 return registers; |
1309 } | 1203 } |
1310 | 1204 |
1311 | 1205 |
1312 Register* KeyedStoreStubCompiler::registers() { | 1206 Register* PropertyAccessCompiler::keyed_store_calling_convention() { |
1313 // receiver, name, scratch1/map, scratch2, scratch3. | 1207 // receiver, name, scratch1/map, scratch2, scratch3. |
1314 Register receiver = KeyedStoreIC::ReceiverRegister(); | 1208 Register receiver = KeyedStoreIC::ReceiverRegister(); |
1315 Register name = KeyedStoreIC::NameRegister(); | 1209 Register name = KeyedStoreIC::NameRegister(); |
1316 Register map = KeyedStoreIC::MapRegister(); | 1210 Register map = KeyedStoreIC::MapRegister(); |
1317 static Register registers[] = { receiver, name, map, edi, no_reg }; | 1211 static Register registers[] = { receiver, name, map, edi, no_reg }; |
1318 return registers; | 1212 return registers; |
1319 } | 1213 } |
1320 | 1214 |
1321 | 1215 |
| 1216 Register NamedStoreHandlerCompiler::value() { return StoreIC::ValueRegister(); } |
| 1217 |
| 1218 |
1322 #undef __ | 1219 #undef __ |
1323 #define __ ACCESS_MASM(masm) | 1220 #define __ ACCESS_MASM(masm) |
1324 | 1221 |
1325 | 1222 |
1326 void LoadStubCompiler::GenerateLoadViaGetter(MacroAssembler* masm, | 1223 void NamedLoadHandlerCompiler::GenerateLoadViaGetter( |
1327 Handle<HeapType> type, | 1224 MacroAssembler* masm, Handle<HeapType> type, Register receiver, |
1328 Register receiver, | 1225 Handle<JSFunction> getter) { |
1329 Handle<JSFunction> getter) { | |
1330 { | 1226 { |
1331 FrameScope scope(masm, StackFrame::INTERNAL); | 1227 FrameScope scope(masm, StackFrame::INTERNAL); |
1332 | 1228 |
1333 if (!getter.is_null()) { | 1229 if (!getter.is_null()) { |
1334 // Call the JavaScript getter with the receiver on the stack. | 1230 // Call the JavaScript getter with the receiver on the stack. |
1335 if (IC::TypeToMap(*type, masm->isolate())->IsJSGlobalObjectMap()) { | 1231 if (IC::TypeToMap(*type, masm->isolate())->IsJSGlobalObjectMap()) { |
1336 // Swap in the global receiver. | 1232 // Swap in the global receiver. |
1337 __ mov(receiver, | 1233 __ mov(receiver, |
1338 FieldOperand(receiver, JSGlobalObject::kGlobalProxyOffset)); | 1234 FieldOperand(receiver, JSGlobalObject::kGlobalProxyOffset)); |
1339 } | 1235 } |
(...skipping 12 matching lines...) Expand all Loading... |
1352 __ mov(esi, Operand(ebp, StandardFrameConstants::kContextOffset)); | 1248 __ mov(esi, Operand(ebp, StandardFrameConstants::kContextOffset)); |
1353 } | 1249 } |
1354 __ ret(0); | 1250 __ ret(0); |
1355 } | 1251 } |
1356 | 1252 |
1357 | 1253 |
1358 #undef __ | 1254 #undef __ |
1359 #define __ ACCESS_MASM(masm()) | 1255 #define __ ACCESS_MASM(masm()) |
1360 | 1256 |
1361 | 1257 |
1362 Handle<Code> LoadStubCompiler::CompileLoadGlobal( | 1258 Handle<Code> NamedLoadHandlerCompiler::CompileLoadGlobal( |
1363 Handle<HeapType> type, | 1259 Handle<HeapType> type, Handle<GlobalObject> global, |
1364 Handle<GlobalObject> global, | 1260 Handle<PropertyCell> cell, Handle<Name> name, bool is_dont_delete) { |
1365 Handle<PropertyCell> cell, | |
1366 Handle<Name> name, | |
1367 bool is_dont_delete) { | |
1368 Label miss; | 1261 Label miss; |
1369 | 1262 |
1370 HandlerFrontendHeader(type, receiver(), global, name, &miss); | 1263 FrontendHeader(type, receiver(), global, name, &miss); |
1371 // Get the value from the cell. | 1264 // Get the value from the cell. |
1372 if (masm()->serializer_enabled()) { | 1265 if (masm()->serializer_enabled()) { |
1373 __ mov(eax, Immediate(cell)); | 1266 __ mov(eax, Immediate(cell)); |
1374 __ mov(eax, FieldOperand(eax, PropertyCell::kValueOffset)); | 1267 __ mov(eax, FieldOperand(eax, PropertyCell::kValueOffset)); |
1375 } else { | 1268 } else { |
1376 __ mov(eax, Operand::ForCell(cell)); | 1269 __ mov(eax, Operand::ForCell(cell)); |
1377 } | 1270 } |
1378 | 1271 |
1379 // Check for deleted property if property can actually be deleted. | 1272 // Check for deleted property if property can actually be deleted. |
1380 if (!is_dont_delete) { | 1273 if (!is_dont_delete) { |
1381 __ cmp(eax, factory()->the_hole_value()); | 1274 __ cmp(eax, factory()->the_hole_value()); |
1382 __ j(equal, &miss); | 1275 __ j(equal, &miss); |
1383 } else if (FLAG_debug_code) { | 1276 } else if (FLAG_debug_code) { |
1384 __ cmp(eax, factory()->the_hole_value()); | 1277 __ cmp(eax, factory()->the_hole_value()); |
1385 __ Check(not_equal, kDontDeleteCellsCannotContainTheHole); | 1278 __ Check(not_equal, kDontDeleteCellsCannotContainTheHole); |
1386 } | 1279 } |
1387 | 1280 |
1388 Counters* counters = isolate()->counters(); | 1281 Counters* counters = isolate()->counters(); |
1389 __ IncrementCounter(counters->named_load_global_stub(), 1); | 1282 __ IncrementCounter(counters->named_load_global_stub(), 1); |
1390 // The code above already loads the result into the return register. | 1283 // The code above already loads the result into the return register. |
1391 __ ret(0); | 1284 __ ret(0); |
1392 | 1285 |
1393 HandlerFrontendFooter(name, &miss); | 1286 FrontendFooter(name, &miss); |
1394 | 1287 |
1395 // Return the generated code. | 1288 // Return the generated code. |
1396 return GetCode(kind(), Code::NORMAL, name); | 1289 return GetCode(kind(), Code::NORMAL, name); |
1397 } | 1290 } |
1398 | 1291 |
1399 | 1292 |
1400 Handle<Code> BaseLoadStoreStubCompiler::CompilePolymorphicIC( | 1293 Handle<Code> PropertyICCompiler::CompilePolymorphic(TypeHandleList* types, |
1401 TypeHandleList* types, | 1294 CodeHandleList* handlers, |
1402 CodeHandleList* handlers, | 1295 Handle<Name> name, |
1403 Handle<Name> name, | 1296 Code::StubType type, |
1404 Code::StubType type, | 1297 IcCheckType check) { |
1405 IcCheckType check) { | |
1406 Label miss; | 1298 Label miss; |
1407 | 1299 |
1408 if (check == PROPERTY && | 1300 if (check == PROPERTY && |
1409 (kind() == Code::KEYED_LOAD_IC || kind() == Code::KEYED_STORE_IC)) { | 1301 (kind() == Code::KEYED_LOAD_IC || kind() == Code::KEYED_STORE_IC)) { |
1410 __ cmp(this->name(), Immediate(name)); | 1302 __ cmp(this->name(), Immediate(name)); |
1411 __ j(not_equal, &miss); | 1303 __ j(not_equal, &miss); |
1412 } | 1304 } |
1413 | 1305 |
1414 Label number_case; | 1306 Label number_case; |
1415 Label* smi_target = IncludesNumberType(types) ? &number_case : &miss; | 1307 Label* smi_target = IncludesNumberType(types) ? &number_case : &miss; |
(...skipping 20 matching lines...) Expand all Loading... |
1436 } | 1328 } |
1437 } | 1329 } |
1438 ASSERT(number_of_handled_maps != 0); | 1330 ASSERT(number_of_handled_maps != 0); |
1439 | 1331 |
1440 __ bind(&miss); | 1332 __ bind(&miss); |
1441 TailCallBuiltin(masm(), MissBuiltin(kind())); | 1333 TailCallBuiltin(masm(), MissBuiltin(kind())); |
1442 | 1334 |
1443 // Return the generated code. | 1335 // Return the generated code. |
1444 InlineCacheState state = | 1336 InlineCacheState state = |
1445 number_of_handled_maps > 1 ? POLYMORPHIC : MONOMORPHIC; | 1337 number_of_handled_maps > 1 ? POLYMORPHIC : MONOMORPHIC; |
1446 return GetICCode(kind(), type, name, state); | 1338 return GetCode(kind(), type, name, state); |
1447 } | 1339 } |
1448 | 1340 |
1449 | 1341 |
1450 #undef __ | 1342 #undef __ |
1451 #define __ ACCESS_MASM(masm) | 1343 #define __ ACCESS_MASM(masm) |
1452 | 1344 |
1453 | 1345 |
1454 void KeyedLoadStubCompiler::GenerateLoadDictionaryElement( | 1346 void IndexedHandlerCompiler::GenerateLoadDictionaryElement( |
1455 MacroAssembler* masm) { | 1347 MacroAssembler* masm) { |
1456 // ----------- S t a t e ------------- | 1348 // ----------- S t a t e ------------- |
1457 // -- ecx : key | 1349 // -- ecx : key |
1458 // -- edx : receiver | 1350 // -- edx : receiver |
1459 // -- esp[0] : return address | 1351 // -- esp[0] : return address |
1460 // ----------------------------------- | 1352 // ----------------------------------- |
1461 ASSERT(edx.is(LoadIC::ReceiverRegister())); | 1353 ASSERT(edx.is(LoadIC::ReceiverRegister())); |
1462 ASSERT(ecx.is(LoadIC::NameRegister())); | 1354 ASSERT(ecx.is(LoadIC::NameRegister())); |
1463 Label slow, miss; | 1355 Label slow, miss; |
1464 | 1356 |
(...skipping 30 matching lines...) Expand all Loading... |
1495 // ----------------------------------- | 1387 // ----------------------------------- |
1496 TailCallBuiltin(masm, Builtins::kKeyedLoadIC_Miss); | 1388 TailCallBuiltin(masm, Builtins::kKeyedLoadIC_Miss); |
1497 } | 1389 } |
1498 | 1390 |
1499 | 1391 |
1500 #undef __ | 1392 #undef __ |
1501 | 1393 |
1502 } } // namespace v8::internal | 1394 } } // namespace v8::internal |
1503 | 1395 |
1504 #endif // V8_TARGET_ARCH_X87 | 1396 #endif // V8_TARGET_ARCH_X87 |
OLD | NEW |