451
451
Label probe_dictionary, check_number_dictionary;
453
453
// Check that the key is a smi.
454
__ JumpIfNotSmi(eax, &check_string);
454
__ JumpIfNotSmi(ecx, &check_string);
455
455
__ bind(&index_smi);
456
456
// Now the key is known to be a smi. This place is also jumped to from
457
457
// where a numeric string is converted to a smi.
459
459
GenerateKeyedLoadReceiverCheck(
460
masm, edx, ecx, Map::kHasIndexedInterceptor, &slow);
460
masm, edx, eax, Map::kHasIndexedInterceptor, &slow);
462
462
// Check the receiver's map to see if it has fast elements.
463
__ CheckFastElements(ecx, &check_number_dictionary);
463
__ CheckFastElements(eax, &check_number_dictionary);
465
GenerateFastArrayLoad(masm,
465
GenerateFastArrayLoad(masm, edx, ecx, eax, eax, NULL, &slow);
472
466
Isolate* isolate = masm->isolate();
473
467
Counters* counters = isolate->counters();
474
468
__ IncrementCounter(counters->keyed_load_generic_smi(), 1);
477
471
__ bind(&check_number_dictionary);
479
473
__ SmiUntag(ebx);
480
__ mov(ecx, FieldOperand(edx, JSObject::kElementsOffset));
474
__ mov(eax, FieldOperand(edx, JSObject::kElementsOffset));
482
476
// Check whether the elements is a number dictionary.
484
478
// ebx: untagged index
488
482
isolate->factory()->hash_table_map(),
490
484
DONT_DO_SMI_CHECK);
511
499
// Slow case: jump to runtime.
514
502
__ IncrementCounter(counters->keyed_load_generic_slow(), 1);
515
503
GenerateRuntimeGetProperty(masm);
517
505
__ bind(&check_string);
518
GenerateKeyStringCheck(masm, eax, ecx, ebx, &index_string, &slow);
506
GenerateKeyStringCheck(masm, ecx, eax, ebx, &index_string, &slow);
520
508
GenerateKeyedLoadReceiverCheck(
521
masm, edx, ecx, Map::kHasNamedInterceptor, &slow);
509
masm, edx, eax, Map::kHasNamedInterceptor, &slow);
523
511
// If the receiver is a fast-case object, check the keyed lookup
524
512
// cache. Otherwise probe the dictionary.
527
515
Immediate(isolate->factory()->hash_table_map()));
528
516
__ j(equal, &probe_dictionary);
530
// Load the map of the receiver, compute the keyed lookup cache hash
518
// The receiver's map is still in eax, compute the keyed lookup cache hash
531
519
// based on 32 bits of the map pointer and the string hash.
532
__ mov(ebx, FieldOperand(edx, HeapObject::kMapOffset));
534
__ shr(ecx, KeyedLookupCache::kMapHashShift);
535
__ mov(edi, FieldOperand(eax, String::kHashFieldOffset));
520
if (FLAG_debug_code) {
521
__ cmp(eax, FieldOperand(edx, HeapObject::kMapOffset));
522
__ Check(equal, "Map is no longer in eax.");
524
__ mov(ebx, eax); // Keep the map around for later.
525
__ shr(eax, KeyedLookupCache::kMapHashShift);
526
__ mov(edi, FieldOperand(ecx, String::kHashFieldOffset));
536
527
__ shr(edi, String::kHashShift);
537
__ xor_(ecx, Operand(edi));
538
__ and_(ecx, KeyedLookupCache::kCapacityMask);
529
__ and_(eax, KeyedLookupCache::kCapacityMask & KeyedLookupCache::kHashMask);
540
531
// Load the key (consisting of map and symbol) from the cache and
541
532
// check for match.
533
Label load_in_object_property;
534
static const int kEntriesPerBucket = KeyedLookupCache::kEntriesPerBucket;
535
Label hit_on_nth_entry[kEntriesPerBucket];
542
536
ExternalReference cache_keys =
543
537
ExternalReference::keyed_lookup_cache_keys(masm->isolate());
539
for (int i = 0; i < kEntriesPerBucket - 1; i++) {
540
Label try_next_entry;
542
__ shl(edi, kPointerSizeLog2 + 1);
544
__ add(edi, Immediate(kPointerSize * i * 2));
546
__ cmp(ebx, Operand::StaticArray(edi, times_1, cache_keys));
547
__ j(not_equal, &try_next_entry);
548
__ add(edi, Immediate(kPointerSize));
549
__ cmp(ecx, Operand::StaticArray(edi, times_1, cache_keys));
550
__ j(equal, &hit_on_nth_entry[i]);
551
__ bind(&try_next_entry);
554
__ lea(edi, Operand(eax, 1));
545
555
__ shl(edi, kPointerSizeLog2 + 1);
556
__ add(edi, Immediate(kPointerSize * (kEntriesPerBucket - 1) * 2));
546
557
__ cmp(ebx, Operand::StaticArray(edi, times_1, cache_keys));
547
558
__ j(not_equal, &slow);
548
__ add(Operand(edi), Immediate(kPointerSize));
549
__ cmp(eax, Operand::StaticArray(edi, times_1, cache_keys));
559
__ add(edi, Immediate(kPointerSize));
560
__ cmp(ecx, Operand::StaticArray(edi, times_1, cache_keys));
550
561
__ j(not_equal, &slow);
552
563
// Get field offset.
553
564
// edx : receiver
554
565
// ebx : receiver's map
556
// ecx : lookup cache index
567
// eax : lookup cache index
557
568
ExternalReference cache_field_offsets =
558
569
ExternalReference::keyed_lookup_cache_field_offsets(masm->isolate());
560
Operand::StaticArray(ecx, times_pointer_size, cache_field_offsets));
561
__ movzx_b(ecx, FieldOperand(ebx, Map::kInObjectPropertiesOffset));
562
__ sub(edi, Operand(ecx));
563
__ j(above_equal, &property_array_property);
572
for (int i = kEntriesPerBucket - 1; i >= 0; i--) {
573
__ bind(&hit_on_nth_entry[i]);
575
__ add(eax, Immediate(i));
578
Operand::StaticArray(eax, times_pointer_size, cache_field_offsets));
579
__ movzx_b(eax, FieldOperand(ebx, Map::kInObjectPropertiesOffset));
581
__ j(above_equal, &property_array_property);
583
__ jmp(&load_in_object_property);
565
587
// Load in-object property.
566
__ movzx_b(ecx, FieldOperand(ebx, Map::kInstanceSizeOffset));
567
__ add(ecx, Operand(edi));
568
__ mov(eax, FieldOperand(edx, ecx, times_pointer_size, 0));
588
__ bind(&load_in_object_property);
589
__ movzx_b(eax, FieldOperand(ebx, Map::kInstanceSizeOffset));
591
__ mov(eax, FieldOperand(edx, eax, times_pointer_size, 0));
569
592
__ IncrementCounter(counters->keyed_load_generic_lookup_cache(), 1);
582
605
__ bind(&probe_dictionary);
584
__ mov(ecx, FieldOperand(edx, JSObject::kMapOffset));
585
__ movzx_b(ecx, FieldOperand(ecx, Map::kInstanceTypeOffset));
586
GenerateGlobalInstanceTypeCheck(masm, ecx, &slow);
607
__ mov(eax, FieldOperand(edx, JSObject::kMapOffset));
608
__ movzx_b(eax, FieldOperand(eax, Map::kInstanceTypeOffset));
609
GenerateGlobalInstanceTypeCheck(masm, eax, &slow);
588
GenerateDictionaryLoad(masm, &slow, ebx, eax, ecx, edi, eax);
611
GenerateDictionaryLoad(masm, &slow, ebx, ecx, eax, edi, eax);
589
612
__ IncrementCounter(counters->keyed_load_generic_symbol(), 1);
592
615
__ bind(&index_string);
593
__ IndexFromHash(ebx, eax);
616
__ IndexFromHash(ebx, ecx);
594
617
// Now jump to the place where smi keys are handled.
595
618
__ jmp(&index_smi);
642
663
__ JumpIfSmi(edx, &slow);
644
665
// Check that the key is an array index, that is Uint32.
645
__ test(eax, Immediate(kSmiTagMask | kSmiSignMask));
666
__ test(ecx, Immediate(kSmiTagMask | kSmiSignMask));
646
667
__ j(not_zero, &slow);
648
669
// Get the map of the receiver.
649
__ mov(ecx, FieldOperand(edx, HeapObject::kMapOffset));
670
__ mov(eax, FieldOperand(edx, HeapObject::kMapOffset));
651
672
// Check that it has indexed interceptor and access checks
652
673
// are not enabled for this object.
653
__ movzx_b(ecx, FieldOperand(ecx, Map::kBitFieldOffset));
654
__ and_(Operand(ecx), Immediate(kSlowCaseBitFieldMask));
655
__ cmp(Operand(ecx), Immediate(1 << Map::kHasIndexedInterceptor));
674
__ movzx_b(eax, FieldOperand(eax, Map::kBitFieldOffset));
675
__ and_(eax, Immediate(kSlowCaseBitFieldMask));
676
__ cmp(eax, Immediate(1 << Map::kHasIndexedInterceptor));
656
677
__ j(not_zero, &slow);
658
679
// Everything is fine, call runtime.
660
681
__ push(edx); // receiver
662
__ push(ecx); // return address
683
__ push(eax); // return address
664
685
// Perform tail call to the entry.
665
686
ExternalReference ref =
675
696
void KeyedLoadIC::GenerateNonStrictArguments(MacroAssembler* masm) {
676
697
// ----------- S t a t e -------------
678
699
// -- edx : receiver
679
700
// -- esp[0] : return address
680
701
// -----------------------------------
681
702
Label slow, notin;
682
703
Factory* factory = masm->isolate()->factory();
683
704
Operand mapped_location =
684
GenerateMappedArgumentsLookup(masm, edx, eax, ebx, ecx, ¬in, &slow);
705
GenerateMappedArgumentsLookup(masm, edx, ecx, ebx, eax, ¬in, &slow);
685
706
__ mov(eax, mapped_location);
688
709
// The unmapped lookup expects that the parameter map is in ebx.
689
710
Operand unmapped_location =
690
GenerateUnmappedArgumentsLookup(masm, eax, ebx, ecx, &slow);
711
GenerateUnmappedArgumentsLookup(masm, ecx, ebx, eax, &slow);
691
712
__ cmp(unmapped_location, factory->the_hole_value());
692
713
__ j(equal, &slow);
693
714
__ mov(eax, unmapped_location);
719
740
__ mov(unmapped_location, eax);
720
741
__ lea(edi, unmapped_location);
721
742
__ mov(edx, eax);
722
__ RecordWrite(ebx, edi, edx);
743
__ RecordWrite(ebx, edi, edx, kDontSaveFPRegs);
725
746
GenerateMiss(masm, false);
750
static void KeyedStoreGenerateGenericHelper(
751
MacroAssembler* masm,
755
KeyedStoreCheckMap check_map,
756
KeyedStoreIncrementLength increment_length) {
757
Label transition_smi_elements;
758
Label finish_object_store, non_double_value, transition_double_elements;
759
Label fast_double_without_map_check;
763
// ebx: FixedArray receiver->elements
765
// Fast case: Do the store, could either Object or double.
766
__ bind(fast_object);
767
if (check_map == kCheckMap) {
768
__ mov(edi, FieldOperand(ebx, HeapObject::kMapOffset));
769
__ cmp(edi, masm->isolate()->factory()->fixed_array_map());
770
__ j(not_equal, fast_double);
772
// Smi stores don't require further checks.
774
__ JumpIfNotSmi(eax, &non_smi_value);
775
if (increment_length == kIncrementLength) {
776
// Add 1 to receiver->length.
777
__ add(FieldOperand(edx, JSArray::kLengthOffset),
778
Immediate(Smi::FromInt(1)));
780
// It's irrelevant whether array is smi-only or not when writing a smi.
781
__ mov(CodeGenerator::FixedArrayElementOperand(ebx, ecx), eax);
784
__ bind(&non_smi_value);
785
// Escape to elements kind transition case.
786
__ mov(edi, FieldOperand(edx, HeapObject::kMapOffset));
787
__ CheckFastObjectElements(edi, &transition_smi_elements);
789
// Fast elements array, store the value to the elements backing store.
790
__ bind(&finish_object_store);
791
if (increment_length == kIncrementLength) {
792
// Add 1 to receiver->length.
793
__ add(FieldOperand(edx, JSArray::kLengthOffset),
794
Immediate(Smi::FromInt(1)));
796
__ mov(CodeGenerator::FixedArrayElementOperand(ebx, ecx), eax);
797
// Update write barrier for the elements array address.
798
__ mov(edx, eax); // Preserve the value which is returned.
800
ebx, edx, ecx, kDontSaveFPRegs, EMIT_REMEMBERED_SET, OMIT_SMI_CHECK);
803
__ bind(fast_double);
804
if (check_map == kCheckMap) {
805
// Check for fast double array case. If this fails, call through to the
807
__ cmp(edi, masm->isolate()->factory()->fixed_double_array_map());
808
__ j(not_equal, slow);
809
// If the value is a number, store it as a double in the FastDoubleElements
812
__ bind(&fast_double_without_map_check);
813
__ StoreNumberToDoubleElements(eax, ebx, ecx, edi, xmm0,
814
&transition_double_elements, false);
815
if (increment_length == kIncrementLength) {
816
// Add 1 to receiver->length.
817
__ add(FieldOperand(edx, JSArray::kLengthOffset),
818
Immediate(Smi::FromInt(1)));
822
__ bind(&transition_smi_elements);
823
__ mov(ebx, FieldOperand(edx, HeapObject::kMapOffset));
825
// Transition the array appropriately depending on the value type.
827
masm->isolate()->factory()->heap_number_map(),
831
// Value is a double. Transition FAST_SMI_ELEMENTS -> FAST_DOUBLE_ELEMENTS
832
// and complete the store.
833
__ LoadTransitionedArrayMapConditional(FAST_SMI_ELEMENTS,
834
FAST_DOUBLE_ELEMENTS,
838
ElementsTransitionGenerator::GenerateSmiToDouble(masm, slow);
839
__ mov(ebx, FieldOperand(edx, JSObject::kElementsOffset));
840
__ jmp(&fast_double_without_map_check);
842
__ bind(&non_double_value);
843
// Value is not a double, FAST_SMI_ELEMENTS -> FAST_ELEMENTS
844
__ LoadTransitionedArrayMapConditional(FAST_SMI_ELEMENTS,
849
ElementsTransitionGenerator::GenerateMapChangeElementsTransition(masm);
850
__ mov(ebx, FieldOperand(edx, JSObject::kElementsOffset));
851
__ jmp(&finish_object_store);
853
__ bind(&transition_double_elements);
854
// Elements are FAST_DOUBLE_ELEMENTS, but value is an Object that's not a
855
// HeapNumber. Make sure that the receiver is a Array with FAST_ELEMENTS and
856
// transition array from FAST_DOUBLE_ELEMENTS to FAST_ELEMENTS
857
__ mov(ebx, FieldOperand(edx, HeapObject::kMapOffset));
858
__ LoadTransitionedArrayMapConditional(FAST_DOUBLE_ELEMENTS,
863
ElementsTransitionGenerator::GenerateDoubleToObject(masm, slow);
864
__ mov(ebx, FieldOperand(edx, JSObject::kElementsOffset));
865
__ jmp(&finish_object_store);
729
869
void KeyedStoreIC::GenerateGeneric(MacroAssembler* masm,
730
870
StrictModeFlag strict_mode) {
731
871
// ----------- S t a t e -------------
750
892
__ CmpInstanceType(edi, JS_ARRAY_TYPE);
751
893
__ j(equal, &array);
752
894
// Check that the object is some kind of JSObject.
753
__ CmpInstanceType(edi, FIRST_JS_RECEIVER_TYPE);
895
__ CmpInstanceType(edi, FIRST_JS_OBJECT_TYPE);
754
896
__ j(below, &slow);
755
__ CmpInstanceType(edi, JS_PROXY_TYPE);
757
__ CmpInstanceType(edi, JS_FUNCTION_PROXY_TYPE);
760
898
// Object case: Check key against length in the elements array.
763
901
// ecx: key (a smi)
764
__ mov(edi, FieldOperand(edx, JSObject::kElementsOffset));
765
// Check that the object is in fast mode and writable.
766
__ CheckMap(edi, FACTORY->fixed_array_map(), &slow, DONT_DO_SMI_CHECK);
767
__ cmp(ecx, FieldOperand(edi, FixedArray::kLengthOffset));
903
__ mov(ebx, FieldOperand(edx, JSObject::kElementsOffset));
904
// Check array bounds. Both the key and the length of FixedArray are smis.
905
__ cmp(ecx, FieldOperand(ebx, FixedArray::kLengthOffset));
906
__ j(below, &fast_object);
770
908
// Slow case: call runtime.
779
917
// edx: receiver, a JSArray
780
918
// ecx: key, a smi.
781
// edi: receiver->elements, a FixedArray
919
// ebx: receiver->elements, a FixedArray
782
921
// flags: compare (ecx, edx.length())
783
922
// do not leave holes in the array:
784
923
__ j(not_equal, &slow);
785
__ cmp(ecx, FieldOperand(edi, FixedArray::kLengthOffset));
924
__ cmp(ecx, FieldOperand(ebx, FixedArray::kLengthOffset));
786
925
__ j(above_equal, &slow);
787
// Add 1 to receiver->length, and go to fast array write.
788
__ add(FieldOperand(edx, JSArray::kLengthOffset),
789
Immediate(Smi::FromInt(1)));
926
__ mov(edi, FieldOperand(ebx, HeapObject::kMapOffset));
927
__ cmp(edi, masm->isolate()->factory()->fixed_array_map());
928
__ j(not_equal, &check_if_double_array);
929
__ jmp(&fast_object_grow);
931
__ bind(&check_if_double_array);
932
__ cmp(edi, masm->isolate()->factory()->fixed_double_array_map());
933
__ j(not_equal, &slow);
934
__ jmp(&fast_double_grow);
792
936
// Array case: Get the length and the elements array from the JS
793
937
// array. Check that the array is in fast mode (and writable); if it
797
941
// edx: receiver, a JSArray
798
942
// ecx: key, a smi.
799
__ mov(edi, FieldOperand(edx, JSObject::kElementsOffset));
800
__ CheckMap(edi, FACTORY->fixed_array_map(), &slow, DONT_DO_SMI_CHECK);
944
__ mov(ebx, FieldOperand(edx, JSObject::kElementsOffset));
802
// Check the key against the length in the array, compute the
803
// address to store into and fall through to fast case.
946
// Check the key against the length in the array and fall through to the
947
// common store code.
804
948
__ cmp(ecx, FieldOperand(edx, JSArray::kLengthOffset)); // Compare smis.
805
949
__ j(above_equal, &extra);
807
// Fast case: Do the store.
812
// edi: FixedArray receiver->elements
813
__ mov(CodeGenerator::FixedArrayElementOperand(edi, ecx), eax);
814
// Update write barrier for the elements array address.
815
__ mov(edx, Operand(eax));
816
__ RecordWrite(edi, 0, edx, ecx);
951
KeyedStoreGenerateGenericHelper(masm, &fast_object, &fast_double,
952
&slow, kCheckMap, kDontIncrementLength);
953
KeyedStoreGenerateGenericHelper(masm, &fast_object_grow, &fast_double_grow,
954
&slow, kDontCheckMap, kIncrementLength);
821
958
// The generated code does not accept smi keys.
822
959
// The generated code falls through if both probes miss.
823
static void GenerateMonomorphicCacheProbe(MacroAssembler* masm,
826
Code::ExtraICState extra_ic_state) {
960
void CallICBase::GenerateMonomorphicCacheProbe(MacroAssembler* masm,
963
Code::ExtraICState extra_state) {
827
964
// ----------- S t a t e -------------
829
966
// -- edx : receiver
951
1088
// Get the receiver of the function from the stack; 1 ~ return address.
952
1089
__ mov(edx, Operand(esp, (argc + 1) * kPointerSize));
954
// Enter an internal frame.
955
__ EnterInternalFrame();
957
// Push the receiver and the name of the function.
963
__ mov(eax, Immediate(2));
964
__ mov(ebx, Immediate(ExternalReference(IC_Utility(id), masm->isolate())));
967
// Move result to edi and exit the internal frame.
969
__ LeaveInternalFrame();
1092
FrameScope scope(masm, StackFrame::INTERNAL);
1094
// Push the receiver and the name of the function.
1100
__ mov(eax, Immediate(2));
1101
__ mov(ebx, Immediate(ExternalReference(IC_Utility(id), masm->isolate())));
1104
// Move result to edi and exit the internal frame.
971
1108
// Check if the receiver is a global object of some sort.
972
1109
// This can happen only for regular CallIC but not KeyedCallIC.
1015
1152
// Get the receiver of the function from the stack; 1 ~ return address.
1016
1153
__ mov(edx, Operand(esp, (argc + 1) * kPointerSize));
1017
GenerateMonomorphicCacheProbe(masm, argc, Code::CALL_IC, extra_ic_state);
1019
GenerateMiss(masm, argc, extra_ic_state);
1023
void CallIC::GenerateNormal(MacroAssembler* masm, int argc) {
1024
// ----------- S t a t e -------------
1026
// -- esp[0] : return address
1027
// -- esp[(argc - n) * 4] : arg[n] (zero-based)
1029
// -- esp[(argc + 1) * 4] : receiver
1030
// -----------------------------------
1032
GenerateCallNormal(masm, argc);
1033
GenerateMiss(masm, argc, Code::kNoExtraICState);
1037
void CallIC::GenerateMiss(MacroAssembler* masm,
1039
Code::ExtraICState extra_ic_state) {
1040
// ----------- S t a t e -------------
1042
// -- esp[0] : return address
1043
// -- esp[(argc - n) * 4] : arg[n] (zero-based)
1045
// -- esp[(argc + 1) * 4] : receiver
1046
// -----------------------------------
1048
GenerateCallMiss(masm, argc, IC::kCallIC_Miss, extra_ic_state);
1154
CallICBase::GenerateMonomorphicCacheProbe(masm, argc, Code::CALL_IC,
1157
GenerateMiss(masm, argc, extra_state);
1209
1320
__ JumpIfSmi(ecx, &miss);
1210
1321
Condition cond = masm->IsObjectStringType(ecx, eax, eax);
1211
1322
__ j(NegateCondition(cond), &miss);
1212
GenerateCallNormal(masm, argc);
1323
CallICBase::GenerateNormal(masm, argc);
1213
1324
__ bind(&miss);
1214
1325
GenerateMiss(masm, argc);
1218
void KeyedCallIC::GenerateMiss(MacroAssembler* masm, int argc) {
1219
// ----------- S t a t e -------------
1221
// -- esp[0] : return address
1222
// -- esp[(argc - n) * 4] : arg[n] (zero-based)
1224
// -- esp[(argc + 1) * 4] : receiver
1225
// -----------------------------------
1227
GenerateCallMiss(masm, argc, IC::kKeyedCallIC_Miss, Code::kNoExtraICState);
1231
1329
void LoadIC::GenerateMegamorphic(MacroAssembler* masm) {
1232
1330
// ----------- S t a t e -------------
1233
// -- eax : receiver
1234
1331
// -- ecx : name
1332
// -- edx : receiver
1235
1333
// -- esp[0] : return address
1236
1334
// -----------------------------------
1238
1336
// Probe the stub cache.
1239
1337
Code::Flags flags = Code::ComputeFlags(Code::LOAD_IC, MONOMORPHIC);
1240
Isolate::Current()->stub_cache()->GenerateProbe(masm, flags, eax, ecx, ebx,
1338
Isolate::Current()->stub_cache()->GenerateProbe(masm, flags, edx, ecx, ebx,
1243
1341
// Cache miss: Jump to runtime.
1244
1342
GenerateMiss(masm);
1248
1346
void LoadIC::GenerateNormal(MacroAssembler* masm) {
1249
1347
// ----------- S t a t e -------------
1250
// -- eax : receiver
1251
1348
// -- ecx : name
1349
// -- edx : receiver
1252
1350
// -- esp[0] : return address
1253
1351
// -----------------------------------
1256
GenerateStringDictionaryReceiverCheck(masm, eax, edx, ebx, &miss);
1354
GenerateStringDictionaryReceiverCheck(masm, edx, eax, ebx, &miss);
1259
1357
// Search the dictionary placing the result in eax.
1260
GenerateDictionaryLoad(masm, &miss, edx, ecx, edi, ebx, eax);
1358
GenerateDictionaryLoad(masm, &miss, eax, ecx, edi, ebx, eax);
1263
1361
// Cache miss: Jump to runtime.
1644
void KeyedStoreIC::GenerateTransitionElementsSmiToDouble(MacroAssembler* masm) {
1645
// ----------- S t a t e -------------
1646
// -- ebx : target map
1647
// -- edx : receiver
1648
// -- esp[0] : return address
1649
// -----------------------------------
1650
// Must return the modified receiver in eax.
1651
if (!FLAG_trace_elements_transitions) {
1653
ElementsTransitionGenerator::GenerateSmiToDouble(masm, &fail);
1661
__ push(ebx); // return address
1662
// Leaving the code managed by the register allocator and return to the
1663
// convention of using esi as context register.
1664
__ mov(esi, Operand(ebp, StandardFrameConstants::kContextOffset));
1665
__ TailCallRuntime(Runtime::kTransitionElementsSmiToDouble, 1, 1);
1669
void KeyedStoreIC::GenerateTransitionElementsDoubleToObject(
1670
MacroAssembler* masm) {
1671
// ----------- S t a t e -------------
1672
// -- ebx : target map
1673
// -- edx : receiver
1674
// -- esp[0] : return address
1675
// -----------------------------------
1676
// Must return the modified receiver in eax.
1677
if (!FLAG_trace_elements_transitions) {
1679
ElementsTransitionGenerator::GenerateDoubleToObject(masm, &fail);
1687
__ push(ebx); // return address
1688
// Leaving the code managed by the register allocator and return to the
1689
// convention of using esi as context register.
1690
__ mov(esi, Operand(ebp, StandardFrameConstants::kContextOffset));
1691
__ TailCallRuntime(Runtime::kTransitionElementsDoubleToObject, 1, 1);
1624
1781
address, test_instruction_address, delta);
1627
// Patch with a short conditional jump. There must be a
1628
// short jump-if-carry/not-carry at this position.
1784
// Patch with a short conditional jump. Enabling means switching from a short
1785
// jump-if-carry/not-carry to jump-if-zero/not-zero, whereas disabling is the
1786
// reverse operation of that.
1629
1787
Address jmp_address = test_instruction_address - delta;
1630
ASSERT(*jmp_address == Assembler::kJncShortOpcode ||
1631
*jmp_address == Assembler::kJcShortOpcode);
1632
Condition cc = *jmp_address == Assembler::kJncShortOpcode
1788
ASSERT((check == ENABLE_INLINED_SMI_CHECK)
1789
? (*jmp_address == Assembler::kJncShortOpcode ||
1790
*jmp_address == Assembler::kJcShortOpcode)
1791
: (*jmp_address == Assembler::kJnzShortOpcode ||
1792
*jmp_address == Assembler::kJzShortOpcode));
1793
Condition cc = (check == ENABLE_INLINED_SMI_CHECK)
1794
? (*jmp_address == Assembler::kJncShortOpcode ? not_zero : zero)
1795
: (*jmp_address == Assembler::kJnzShortOpcode ? not_carry : carry);
1635
1796
*jmp_address = static_cast<byte>(Assembler::kJccShortPrefix | cc);