00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028 #include "v8.h"
00029
00030 #include "codegen-inl.h"
00031 #include "ic-inl.h"
00032 #include "runtime.h"
00033 #include "stub-cache.h"
00034
00035 namespace v8 { namespace internal {
00036
00037
00038
00039
00040
00041 #define __ masm->
00042
00043
00044
00045 static void GenerateDictionaryLoad(MacroAssembler* masm, Label* miss_label,
00046 Register r0, Register r1, Register r2,
00047 Register name) {
00048
00049
00050
00051
00052
00053
00054
00055
00056
00057
00058
00059
00060 Label done;
00061
00062
00063
00064 __ mov(r0, FieldOperand(r1, JSObject::kMapOffset));
00065
00066 __ test(FieldOperand(r0, Map::kInstanceAttributesOffset),
00067 Immediate(1 << (Map::kHasNamedInterceptor + (3 * 8))));
00068
00069 __ j(not_zero, miss_label, not_taken);
00070
00071
00072 __ mov(r0, FieldOperand(r1, JSObject::kPropertiesOffset));
00073 __ cmp(FieldOperand(r0, HeapObject::kMapOffset),
00074 Immediate(Factory::hash_table_map()));
00075 __ j(not_equal, miss_label);
00076
00077
00078 const int kCapacityOffset =
00079 Array::kHeaderSize + Dictionary::kCapacityIndex * kPointerSize;
00080 __ mov(r2, FieldOperand(r0, kCapacityOffset));
00081 __ shr(r2, kSmiTagSize);
00082 __ dec(r2);
00083
00084
00085
00086
00087 static const int kProbes = 4;
00088 const int kElementsStartOffset =
00089 Array::kHeaderSize + Dictionary::kElementsStartIndex * kPointerSize;
00090 for (int i = 0; i < kProbes; i++) {
00091
00092 __ mov(r1, FieldOperand(name, String::kLengthOffset));
00093 __ shr(r1, String::kHashShift);
00094 if (i > 0) __ add(Operand(r1), Immediate(Dictionary::GetProbeOffset(i)));
00095 __ and_(r1, Operand(r2));
00096
00097
00098 ASSERT(Dictionary::kElementSize == 3);
00099 __ lea(r1, Operand(r1, r1, times_2, 0));
00100
00101
00102 __ cmp(name,
00103 Operand(r0, r1, times_4, kElementsStartOffset - kHeapObjectTag));
00104 if (i != kProbes - 1) {
00105 __ j(equal, &done, taken);
00106 } else {
00107 __ j(not_equal, miss_label, not_taken);
00108 }
00109 }
00110
00111
00112 __ bind(&done);
00113 const int kDetailsOffset = kElementsStartOffset + 2 * kPointerSize;
00114 __ test(Operand(r0, r1, times_4, kDetailsOffset - kHeapObjectTag),
00115 Immediate(PropertyDetails::TypeField::mask() << kSmiTagSize));
00116 __ j(not_zero, miss_label, not_taken);
00117
00118
00119 const int kValueOffset = kElementsStartOffset + kPointerSize;
00120 __ mov(r1, Operand(r0, r1, times_4, kValueOffset - kHeapObjectTag));
00121 }
00122
00123
00124 void LoadIC::GenerateArrayLength(MacroAssembler* masm) {
00125
00126
00127
00128
00129
00130
00131 Label miss;
00132
00133 __ mov(eax, Operand(esp, kPointerSize));
00134
00135 StubCompiler::GenerateLoadArrayLength(masm, eax, edx, &miss);
00136 __ bind(&miss);
00137 StubCompiler::GenerateLoadMiss(masm, Code::LOAD_IC);
00138 }
00139
00140
00141 void LoadIC::GenerateStringLength(MacroAssembler* masm) {
00142
00143
00144
00145
00146
00147
00148 Label miss;
00149
00150 __ mov(eax, Operand(esp, kPointerSize));
00151
00152 StubCompiler::GenerateLoadStringLength(masm, eax, edx, &miss);
00153 __ bind(&miss);
00154 StubCompiler::GenerateLoadMiss(masm, Code::LOAD_IC);
00155 }
00156
00157
00158 void LoadIC::GenerateFunctionPrototype(MacroAssembler* masm) {
00159
00160
00161
00162
00163
00164
00165 Label miss;
00166
00167 __ mov(eax, Operand(esp, kPointerSize));
00168
00169 StubCompiler::GenerateLoadFunctionPrototype(masm, eax, edx, ebx, &miss);
00170 __ bind(&miss);
00171 StubCompiler::GenerateLoadMiss(masm, Code::LOAD_IC);
00172 }
00173
00174
00175 #ifdef DEBUG
00176
00177 static int TenToThe(int exponent) {
00178 ASSERT(exponent <= 9);
00179 ASSERT(exponent >= 1);
00180 int answer = 10;
00181 for (int i = 1; i < exponent; i++) answer *= 10;
00182 return answer;
00183 }
00184 #endif
00185
00186
00187 void KeyedLoadIC::GenerateGeneric(MacroAssembler* masm) {
00188
00189
00190
00191
00192
00193 Label slow, fast, check_string, index_int, index_string;
00194
00195 __ mov(eax, (Operand(esp, kPointerSize)));
00196 __ mov(ecx, (Operand(esp, 2 * kPointerSize)));
00197
00198
00199 __ test(ecx, Immediate(kSmiTagMask));
00200 __ j(zero, &slow, not_taken);
00201
00202
00203
00204
00205 ASSERT(JS_OBJECT_TYPE > JS_VALUE_TYPE);
00206 __ mov(edx, FieldOperand(ecx, HeapObject::kMapOffset));
00207 __ movzx_b(edx, FieldOperand(edx, Map::kInstanceTypeOffset));
00208 __ cmp(edx, JS_OBJECT_TYPE);
00209 __ j(less, &slow, not_taken);
00210
00211 __ test(eax, Immediate(kSmiTagMask));
00212 __ j(not_zero, &check_string, not_taken);
00213 __ sar(eax, kSmiTagSize);
00214
00215 __ bind(&index_int);
00216 __ mov(ecx, FieldOperand(ecx, JSObject::kElementsOffset));
00217
00218 __ cmp(FieldOperand(ecx, HeapObject::kMapOffset),
00219 Immediate(Factory::hash_table_map()));
00220 __ j(equal, &slow, not_taken);
00221
00222 __ cmp(eax, FieldOperand(ecx, Array::kLengthOffset));
00223 __ j(below, &fast, taken);
00224
00225 __ bind(&slow);
00226 __ IncrementCounter(&Counters::keyed_load_generic_slow, 1);
00227 KeyedLoadIC::Generate(masm, ExternalReference(Runtime::kKeyedGetProperty));
00228
00229 __ bind(&check_string);
00230 __ mov(ebx, FieldOperand(eax, String::kLengthOffset));
00231 __ test(ebx, Immediate(String::kIsArrayIndexMask));
00232 __ j(not_zero, &index_string, not_taken);
00233 __ mov(ebx, FieldOperand(eax, HeapObject::kMapOffset));
00234 __ movzx_b(ebx, FieldOperand(ebx, Map::kInstanceTypeOffset));
00235 __ test(ebx, Immediate(kIsSymbolMask));
00236 __ j(not_zero, &slow, not_taken);
00237
00238 GenerateDictionaryLoad(masm, &slow, ebx, ecx, edx, eax);
00239 __ mov(eax, Operand(ecx));
00240 __ IncrementCounter(&Counters::keyed_load_generic_symbol, 1);
00241 __ ret(0);
00242
00243
00244
00245
00246 ASSERT(TenToThe(String::kMaxCachedArrayIndexLength) <
00247 (1 << (String::kShortLengthShift - String::kHashShift)));
00248 __ bind(&index_string);
00249 const int kLengthFieldLimit =
00250 (String::kMaxCachedArrayIndexLength + 1) << String::kShortLengthShift;
00251 __ cmp(ebx, kLengthFieldLimit);
00252 __ j(above_equal, &slow);
00253 __ mov(eax, Operand(ebx));
00254 __ and_(eax, (1 << String::kShortLengthShift) - 1);
00255 __ shr(eax, String::kLongLengthShift);
00256 __ jmp(&index_int);
00257
00258 __ bind(&fast);
00259 __ mov(eax, Operand(ecx, eax, times_4, Array::kHeaderSize - kHeapObjectTag));
00260 __ cmp(Operand(eax), Immediate(Factory::the_hole_value()));
00261
00262
00263 __ j(equal, &slow, not_taken);
00264 __ IncrementCounter(&Counters::keyed_load_generic_smi, 1);
00265 __ ret(0);
00266 }
00267
00268
00269 void KeyedStoreIC::GenerateGeneric(MacroAssembler* masm) {
00270
00271
00272
00273
00274
00275
00276 Label slow, fast, array, extra;
00277
00278 __ mov(ebx, Operand(esp, 1 * kPointerSize));
00279 __ mov(edx, Operand(esp, 2 * kPointerSize));
00280
00281 __ test(ebx, Immediate(kSmiTagMask));
00282 __ j(not_zero, &slow, not_taken);
00283
00284 __ test(edx, Immediate(kSmiTagMask));
00285 __ j(zero, &slow, not_taken);
00286
00287 __ mov(ecx, FieldOperand(edx, HeapObject::kMapOffset));
00288 __ movzx_b(ecx, FieldOperand(ecx, Map::kInstanceTypeOffset));
00289
00290 __ cmp(ecx, JS_ARRAY_TYPE);
00291 __ j(equal, &array);
00292
00293 __ cmp(ecx, FIRST_JS_OBJECT_TYPE);
00294 __ j(less, &slow, not_taken);
00295
00296
00297
00298
00299
00300
00301 __ mov(ecx, FieldOperand(edx, JSObject::kElementsOffset));
00302
00303 __ cmp(FieldOperand(ecx, HeapObject::kMapOffset),
00304 Immediate(Factory::hash_table_map()));
00305 __ j(equal, &slow, not_taken);
00306
00307 __ mov(edx, Operand(ebx));
00308 __ sar(edx, kSmiTagSize);
00309 __ cmp(edx, FieldOperand(ecx, Array::kLengthOffset));
00310
00311
00312
00313 __ j(below, &fast, taken);
00314
00315
00316
00317 __ bind(&slow);
00318 __ pop(ecx);
00319 __ push(Operand(esp, 1 * kPointerSize));
00320 __ push(Operand(esp, 1 * kPointerSize));
00321 __ push(eax);
00322 __ push(ecx);
00323
00324 __ TailCallRuntime(ExternalReference(Runtime::kSetProperty), 3);
00325
00326
00327
00328
00329
00330 __ bind(&extra);
00331
00332
00333
00334
00335
00336 __ j(not_equal, &slow, not_taken);
00337 __ sar(ebx, kSmiTagSize);
00338 __ cmp(ebx, FieldOperand(ecx, Array::kLengthOffset));
00339 __ j(above_equal, &slow, not_taken);
00340
00341 __ lea(ebx, Operand(ebx, times_2, 1 << kSmiTagSize));
00342 __ mov(FieldOperand(edx, JSArray::kLengthOffset), ebx);
00343 __ sub(Operand(ebx), Immediate(1 << kSmiTagSize));
00344 __ jmp(&fast);
00345
00346
00347
00348
00349
00350 __ bind(&array);
00351
00352
00353
00354 __ mov(ecx, FieldOperand(edx, JSObject::kElementsOffset));
00355 __ cmp(FieldOperand(ecx, HeapObject::kMapOffset),
00356 Immediate(Factory::hash_table_map()));
00357 __ j(equal, &slow, not_taken);
00358
00359
00360
00361 __ cmp(ebx, FieldOperand(edx, JSArray::kLengthOffset));
00362 __ j(above_equal, &extra, not_taken);
00363
00364
00365
00366 __ bind(&fast);
00367
00368
00369
00370 __ mov(Operand(ecx, ebx, times_2, Array::kHeaderSize - kHeapObjectTag), eax);
00371
00372 __ mov(edx, Operand(eax));
00373 __ RecordWrite(ecx, 0, edx, ebx);
00374 __ ret(0);
00375 }
00376
00377
00378
00379 Object* CallIC_Miss(Arguments args);
00380
00381 void CallIC::GenerateMegamorphic(MacroAssembler* masm, int argc) {
00382
00383
00384 Label number, non_number, non_string, boolean, probe, miss;
00385
00386
00387 __ mov(edx, Operand(esp, (argc + 1) * kPointerSize));
00388
00389 __ mov(ecx, Operand(esp, (argc + 2) * kPointerSize));
00390
00391
00392 Code::Flags flags =
00393 Code::ComputeFlags(Code::CALL_IC, MONOMORPHIC, NORMAL, argc);
00394 StubCache::GenerateProbe(masm, flags, edx, ecx, ebx);
00395
00396
00397
00398
00399
00400
00401
00402 __ test(edx, Immediate(kSmiTagMask));
00403 __ j(zero, &number, not_taken);
00404 __ mov(ebx, FieldOperand(edx, HeapObject::kMapOffset));
00405 __ movzx_b(ebx, FieldOperand(ebx, Map::kInstanceTypeOffset));
00406 __ cmp(ebx, HEAP_NUMBER_TYPE);
00407 __ j(not_equal, &non_number, taken);
00408 __ bind(&number);
00409 StubCompiler::GenerateLoadGlobalFunctionPrototype(
00410 masm, Context::NUMBER_FUNCTION_INDEX, edx);
00411 __ jmp(&probe);
00412
00413
00414 __ bind(&non_number);
00415 __ cmp(ebx, FIRST_NONSTRING_TYPE);
00416 __ j(above_equal, &non_string, taken);
00417 StubCompiler::GenerateLoadGlobalFunctionPrototype(
00418 masm, Context::STRING_FUNCTION_INDEX, edx);
00419 __ jmp(&probe);
00420
00421
00422 __ bind(&non_string);
00423 __ cmp(edx, Factory::true_value());
00424 __ j(equal, &boolean, not_taken);
00425 __ cmp(edx, Factory::false_value());
00426 __ j(not_equal, &miss, taken);
00427 __ bind(&boolean);
00428 StubCompiler::GenerateLoadGlobalFunctionPrototype(
00429 masm, Context::BOOLEAN_FUNCTION_INDEX, edx);
00430
00431
00432 __ bind(&probe);
00433 StubCache::GenerateProbe(masm, flags, edx, ecx, ebx);
00434
00435
00436 __ bind(&miss);
00437 Generate(masm, argc, ExternalReference(IC_Utility(kCallIC_Miss)));
00438 }
00439
00440
00441 static void GenerateNormalHelper(MacroAssembler* masm,
00442 int argc,
00443 bool is_global_object,
00444 Label* miss) {
00445
00446 GenerateDictionaryLoad(masm, miss, eax, edx, ebx, ecx);
00447
00448
00449 __ mov(edi, Operand(edx));
00450 __ test(edx, Immediate(kSmiTagMask));
00451 __ j(zero, miss, not_taken);
00452
00453
00454 __ mov(edx, FieldOperand(edx, HeapObject::kMapOffset));
00455 __ movzx_b(edx, FieldOperand(edx, Map::kInstanceTypeOffset));
00456 __ cmp(edx, JS_FUNCTION_TYPE);
00457 __ j(not_equal, miss, not_taken);
00458
00459
00460 if (is_global_object) {
00461 __ mov(edx, Operand(esp, (argc + 1) * kPointerSize));
00462 __ mov(edx, FieldOperand(edx, GlobalObject::kGlobalReceiverOffset));
00463 __ mov(Operand(esp, (argc + 1) * kPointerSize), edx);
00464 }
00465
00466
00467 ParameterCount actual(argc);
00468 __ InvokeFunction(edi, actual, JUMP_FUNCTION);
00469 }
00470
00471
00472 void CallIC::GenerateNormal(MacroAssembler* masm, int argc) {
00473
00474
00475
00476 Label miss, global_object, non_global_object;
00477
00478
00479 __ mov(edx, Operand(esp, (argc + 1) * kPointerSize));
00480
00481 __ mov(ecx, Operand(esp, (argc + 2) * kPointerSize));
00482
00483
00484 __ test(edx, Immediate(kSmiTagMask));
00485 __ j(zero, &miss, not_taken);
00486
00487
00488 __ mov(eax, FieldOperand(edx, HeapObject::kMapOffset));
00489 __ movzx_b(eax, FieldOperand(eax, Map::kInstanceTypeOffset));
00490 __ cmp(eax, FIRST_JS_OBJECT_TYPE);
00491 __ j(less, &miss, not_taken);
00492
00493
00494 ASSERT(LAST_TYPE == JS_FUNCTION_TYPE);
00495
00496
00497 __ cmp(eax, JS_GLOBAL_OBJECT_TYPE);
00498 __ j(equal, &global_object);
00499 __ cmp(eax, JS_BUILTINS_OBJECT_TYPE);
00500 __ j(not_equal, &non_global_object);
00501
00502
00503 __ bind(&global_object);
00504 GenerateNormalHelper(masm, argc, true, &miss);
00505
00506
00507 Label global_proxy, invoke;
00508 __ bind(&non_global_object);
00509 __ cmp(eax, JS_GLOBAL_PROXY_TYPE);
00510 __ j(equal, &global_proxy, not_taken);
00511 __ bind(&invoke);
00512 GenerateNormalHelper(masm, argc, false, &miss);
00513
00514
00515 __ bind(&global_proxy);
00516 __ CheckAccessGlobalProxy(edx, eax, &miss);
00517 __ jmp(&invoke);
00518
00519
00520 __ bind(&miss);
00521 Generate(masm, argc, ExternalReference(IC_Utility(kCallIC_Miss)));
00522 }
00523
00524
00525 void CallIC::Generate(MacroAssembler* masm,
00526 int argc,
00527 const ExternalReference& f) {
00528
00529
00530
00531
00532 __ mov(edx, Operand(esp, (argc + 1) * kPointerSize));
00533
00534
00535 __ mov(ebx, Operand(esp, (argc + 2) * kPointerSize));
00536
00537
00538 __ EnterInternalFrame();
00539
00540
00541 __ push(Operand(edx));
00542 __ push(Operand(ebx));
00543
00544
00545 CEntryStub stub;
00546 __ mov(Operand(eax), Immediate(2));
00547 __ mov(Operand(ebx), Immediate(f));
00548 __ CallStub(&stub);
00549
00550
00551 __ mov(Operand(edi), eax);
00552 __ LeaveInternalFrame();
00553
00554
00555 Label invoke, global;
00556 __ mov(edx, Operand(esp, (argc + 1) * kPointerSize));
00557 __ test(edx, Immediate(kSmiTagMask));
00558 __ j(zero, &invoke, not_taken);
00559 __ mov(ecx, FieldOperand(edx, HeapObject::kMapOffset));
00560 __ movzx_b(ecx, FieldOperand(ecx, Map::kInstanceTypeOffset));
00561 __ cmp(ecx, JS_GLOBAL_OBJECT_TYPE);
00562 __ j(equal, &global);
00563 __ cmp(ecx, JS_BUILTINS_OBJECT_TYPE);
00564 __ j(not_equal, &invoke);
00565
00566
00567 __ bind(&global);
00568 __ mov(edx, FieldOperand(edx, GlobalObject::kGlobalReceiverOffset));
00569 __ mov(Operand(esp, (argc + 1) * kPointerSize), edx);
00570
00571
00572 ParameterCount actual(argc);
00573 __ bind(&invoke);
00574 __ InvokeFunction(edi, actual, JUMP_FUNCTION);
00575 }
00576
00577
00578
00579 Object* LoadIC_Miss(Arguments args);
00580
00581 void LoadIC::GenerateMegamorphic(MacroAssembler* masm) {
00582
00583
00584
00585
00586
00587
00588 __ mov(eax, Operand(esp, kPointerSize));
00589
00590
00591 Code::Flags flags = Code::ComputeFlags(Code::LOAD_IC, MONOMORPHIC);
00592 StubCache::GenerateProbe(masm, flags, eax, ecx, ebx);
00593
00594
00595 Generate(masm, ExternalReference(IC_Utility(kLoadIC_Miss)));
00596 }
00597
00598
00599 void LoadIC::GenerateNormal(MacroAssembler* masm) {
00600
00601
00602
00603
00604
00605
00606 Label miss, probe, global;
00607
00608 __ mov(eax, Operand(esp, kPointerSize));
00609
00610
00611 __ test(eax, Immediate(kSmiTagMask));
00612 __ j(zero, &miss, not_taken);
00613
00614
00615 __ mov(edx, FieldOperand(eax, HeapObject::kMapOffset));
00616 __ movzx_b(edx, FieldOperand(edx, Map::kInstanceTypeOffset));
00617 __ cmp(edx, FIRST_JS_OBJECT_TYPE);
00618 __ j(less, &miss, not_taken);
00619
00620
00621 ASSERT(LAST_TYPE == JS_FUNCTION_TYPE);
00622
00623
00624 __ cmp(edx, JS_GLOBAL_PROXY_TYPE);
00625 __ j(equal, &global, not_taken);
00626
00627
00628 __ bind(&probe);
00629 GenerateDictionaryLoad(masm, &miss, edx, eax, ebx, ecx);
00630 __ ret(0);
00631
00632
00633 __ bind(&global);
00634 __ CheckAccessGlobalProxy(eax, edx, &miss);
00635 __ jmp(&probe);
00636
00637
00638 __ bind(&miss);
00639 __ mov(eax, Operand(esp, 1 * kPointerSize));
00640 Generate(masm, ExternalReference(IC_Utility(kLoadIC_Miss)));
00641 }
00642
00643
00644 void LoadIC::GenerateMiss(MacroAssembler* masm) {
00645
00646
00647
00648
00649
00650
00651 Generate(masm, ExternalReference(IC_Utility(kLoadIC_Miss)));
00652 }
00653
00654
00655 void LoadIC::Generate(MacroAssembler* masm, const ExternalReference& f) {
00656
00657
00658
00659
00660
00661
00662 __ mov(eax, Operand(esp, kPointerSize));
00663
00664
00665 __ pop(ebx);
00666 __ push(eax);
00667 __ push(ecx);
00668 __ push(ebx);
00669
00670
00671 __ TailCallRuntime(f, 2);
00672 }
00673
00674
00675
00676 Object* KeyedLoadIC_Miss(Arguments args);
00677
00678
00679 void KeyedLoadIC::GenerateMiss(MacroAssembler* masm) {
00680
00681
00682
00683
00684
00685
00686 Generate(masm, ExternalReference(IC_Utility(kKeyedLoadIC_Miss)));
00687 }
00688
00689
00690 void KeyedLoadIC::Generate(MacroAssembler* masm, const ExternalReference& f) {
00691
00692
00693
00694
00695
00696
00697 __ mov(eax, Operand(esp, kPointerSize));
00698 __ mov(ecx, Operand(esp, 2 * kPointerSize));
00699
00700
00701 __ pop(ebx);
00702 __ push(ecx);
00703 __ push(eax);
00704 __ push(ebx);
00705
00706
00707 __ TailCallRuntime(f, 2);
00708 }
00709
00710
00711 void StoreIC::GenerateMegamorphic(MacroAssembler* masm) {
00712
00713
00714
00715
00716
00717
00718
00719
00720 __ mov(edx, Operand(esp, 4));
00721 Code::Flags flags = Code::ComputeFlags(Code::STORE_IC, MONOMORPHIC);
00722 StubCache::GenerateProbe(masm, flags, edx, ecx, ebx);
00723
00724
00725 Generate(masm, ExternalReference(IC_Utility(kStoreIC_Miss)));
00726 }
00727
00728
00729 void StoreIC::GenerateExtendStorage(MacroAssembler* masm) {
00730
00731
00732
00733
00734
00735
00736
00737
00738 __ pop(ebx);
00739 __ push(Operand(esp, 0));
00740 __ push(ecx);
00741 __ push(eax);
00742 __ push(ebx);
00743
00744 __ TailCallRuntime(
00745 ExternalReference(IC_Utility(kSharedStoreIC_ExtendStorage)), 3);
00746 }
00747
00748
00749 void StoreIC::Generate(MacroAssembler* masm, const ExternalReference& f) {
00750
00751
00752
00753
00754
00755
00756
00757
00758 __ pop(ebx);
00759 __ push(Operand(esp, 0));
00760 __ push(ecx);
00761 __ push(eax);
00762 __ push(ebx);
00763
00764
00765 __ TailCallRuntime(f, 3);
00766 }
00767
00768
00769
00770 Object* KeyedStoreIC_Miss(Arguments args);
00771
00772 void KeyedStoreIC::Generate(MacroAssembler* masm, const ExternalReference& f) {
00773
00774
00775
00776
00777
00778
00779
00780
00781 __ pop(ecx);
00782 __ push(Operand(esp, 1 * kPointerSize));
00783 __ push(Operand(esp, 1 * kPointerSize));
00784 __ push(eax);
00785 __ push(ecx);
00786
00787
00788 __ TailCallRuntime(f, 3);
00789 }
00790
00791
00792 void KeyedStoreIC::GenerateExtendStorage(MacroAssembler* masm) {
00793
00794
00795
00796
00797
00798
00799
00800
00801
00802 __ pop(ebx);
00803 __ push(Operand(esp, 1 * kPointerSize));
00804 __ push(ecx);
00805 __ push(eax);
00806 __ push(ebx);
00807
00808
00809 __ TailCallRuntime(
00810 ExternalReference(IC_Utility(kSharedStoreIC_ExtendStorage)), 3);
00811 }
00812
00813 #undef __
00814
00815
00816 } }