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 "ic-inl.h"
00031 #include "codegen-inl.h"
00032 #include "stub-cache.h"
00033
00034 namespace v8 { namespace internal {
00035
00036 #define __ masm->
00037
00038
00039 static void ProbeTable(MacroAssembler* masm,
00040 Code::Flags flags,
00041 StubCache::Table table,
00042 Register name,
00043 Register offset) {
00044 ExternalReference key_offset(SCTableReference::keyReference(table));
00045 ExternalReference value_offset(SCTableReference::valueReference(table));
00046
00047 Label miss;
00048
00049
00050 __ push(offset);
00051
00052
00053 __ cmp(name, Operand::StaticArray(offset, times_2, key_offset));
00054 __ j(not_equal, &miss, not_taken);
00055
00056
00057 __ mov(offset, Operand::StaticArray(offset, times_2, value_offset));
00058
00059
00060 __ mov(offset, FieldOperand(offset, Code::kFlagsOffset));
00061 __ and_(offset, ~Code::kFlagsTypeMask);
00062 __ cmp(offset, flags);
00063 __ j(not_equal, &miss);
00064
00065
00066 __ pop(offset);
00067 __ mov(offset, Operand::StaticArray(offset, times_2, value_offset));
00068
00069
00070 __ add(Operand(offset), Immediate(Code::kHeaderSize - kHeapObjectTag));
00071 __ jmp(Operand(offset));
00072
00073
00074 __ bind(&miss);
00075 __ pop(offset);
00076 }
00077
00078
00079 void StubCache::GenerateProbe(MacroAssembler* masm,
00080 Code::Flags flags,
00081 Register receiver,
00082 Register name,
00083 Register scratch) {
00084 Label miss;
00085
00086
00087
00088 ASSERT(sizeof(Entry) == 8);
00089
00090
00091 ASSERT(Code::ExtractTypeFromFlags(flags) == 0);
00092
00093
00094 ASSERT(!scratch.is(receiver));
00095 ASSERT(!scratch.is(name));
00096
00097
00098 __ test(receiver, Immediate(kSmiTagMask));
00099 __ j(zero, &miss, not_taken);
00100
00101
00102 __ mov(scratch, FieldOperand(name, String::kLengthOffset));
00103 __ add(scratch, FieldOperand(receiver, HeapObject::kMapOffset));
00104 __ xor_(scratch, flags);
00105 __ and_(scratch, (kPrimaryTableSize - 1) << kHeapObjectTagSize);
00106
00107
00108 ProbeTable(masm, flags, kPrimary, name, scratch);
00109
00110
00111 __ sub(scratch, Operand(name));
00112 __ add(Operand(scratch), Immediate(flags));
00113 __ and_(scratch, (kSecondaryTableSize - 1) << kHeapObjectTagSize);
00114
00115
00116 ProbeTable(masm, flags, kSecondary, name, scratch);
00117
00118
00119
00120 __ bind(&miss);
00121 }
00122
00123
00124 void StubCompiler::GenerateLoadGlobalFunctionPrototype(MacroAssembler* masm,
00125 int index,
00126 Register prototype) {
00127
00128 __ mov(prototype, Operand(esi, Context::SlotOffset(Context::GLOBAL_INDEX)));
00129
00130 __ mov(prototype,
00131 FieldOperand(prototype, GlobalObject::kGlobalContextOffset));
00132
00133 __ mov(prototype, Operand(prototype, Context::SlotOffset(index)));
00134
00135 __ mov(prototype,
00136 FieldOperand(prototype, JSFunction::kPrototypeOrInitialMapOffset));
00137
00138 __ mov(prototype, FieldOperand(prototype, Map::kPrototypeOffset));
00139 }
00140
00141
00142 void StubCompiler::GenerateLoadArrayLength(MacroAssembler* masm,
00143 Register receiver,
00144 Register scratch,
00145 Label* miss_label) {
00146
00147 __ test(receiver, Immediate(kSmiTagMask));
00148 __ j(zero, miss_label, not_taken);
00149
00150
00151 __ mov(scratch, FieldOperand(receiver, HeapObject::kMapOffset));
00152 __ movzx_b(scratch, FieldOperand(scratch, Map::kInstanceTypeOffset));
00153 __ cmp(scratch, JS_ARRAY_TYPE);
00154 __ j(not_equal, miss_label, not_taken);
00155
00156
00157 __ mov(eax, FieldOperand(receiver, JSArray::kLengthOffset));
00158 __ ret(0);
00159 }
00160
00161
00162
00163
00164 static void GenerateStringCheck(MacroAssembler* masm,
00165 Register receiver,
00166 Register scratch,
00167 Label* smi,
00168 Label* non_string_object) {
00169
00170 __ test(receiver, Immediate(kSmiTagMask));
00171 __ j(zero, smi, not_taken);
00172
00173
00174 __ mov(scratch, FieldOperand(receiver, HeapObject::kMapOffset));
00175 __ movzx_b(scratch, FieldOperand(scratch, Map::kInstanceTypeOffset));
00176 ASSERT(kNotStringTag != 0);
00177 __ test(scratch, Immediate(kNotStringTag));
00178 __ j(not_zero, non_string_object, not_taken);
00179 }
00180
00181
00182 void StubCompiler::GenerateLoadStringLength(MacroAssembler* masm,
00183 Register receiver,
00184 Register scratch,
00185 Label* miss) {
00186 Label load_length, check_wrapper;
00187
00188
00189
00190 GenerateStringCheck(masm, receiver, scratch, miss, &check_wrapper);
00191
00192
00193 __ bind(&load_length);
00194 __ and_(scratch, kStringSizeMask);
00195 __ mov(eax, FieldOperand(receiver, String::kLengthOffset));
00196
00197 __ lea(ecx, Operand(scratch, String::kLongLengthShift));
00198 __ shr(eax);
00199 __ shl(eax, kSmiTagSize);
00200 __ ret(0);
00201
00202
00203 __ bind(&check_wrapper);
00204 __ cmp(scratch, JS_VALUE_TYPE);
00205 __ j(not_equal, miss, not_taken);
00206
00207
00208
00209 __ mov(receiver, FieldOperand(receiver, JSValue::kValueOffset));
00210 GenerateStringCheck(masm, receiver, scratch, miss, miss);
00211 __ jmp(&load_length);
00212 }
00213
00214
00215 void StubCompiler::GenerateLoadFunctionPrototype(MacroAssembler* masm,
00216 Register receiver,
00217 Register scratch1,
00218 Register scratch2,
00219 Label* miss_label) {
00220 __ TryGetFunctionPrototype(receiver, scratch1, scratch2, miss_label);
00221 __ mov(eax, Operand(scratch1));
00222 __ ret(0);
00223 }
00224
00225
00226
00227
00228
00229 void StubCompiler::GenerateFastPropertyLoad(MacroAssembler* masm,
00230 Register dst, Register src,
00231 JSObject* holder, int index) {
00232
00233 index -= holder->map()->inobject_properties();
00234 if (index < 0) {
00235
00236 int offset = holder->map()->instance_size() + (index * kPointerSize);
00237 __ mov(dst, FieldOperand(src, offset));
00238 } else {
00239
00240 int offset = index * kPointerSize + Array::kHeaderSize;
00241 __ mov(dst, FieldOperand(src, JSObject::kPropertiesOffset));
00242 __ mov(dst, FieldOperand(dst, offset));
00243 }
00244 }
00245
00246
00247 void StubCompiler::GenerateLoadField(MacroAssembler* masm,
00248 JSObject* object,
00249 JSObject* holder,
00250 Register receiver,
00251 Register scratch1,
00252 Register scratch2,
00253 int index,
00254 Label* miss_label) {
00255
00256 __ test(receiver, Immediate(kSmiTagMask));
00257 __ j(zero, miss_label, not_taken);
00258
00259
00260 Register reg =
00261 __ CheckMaps(object, receiver, holder, scratch1, scratch2, miss_label);
00262
00263
00264 GenerateFastPropertyLoad(masm, eax, reg, holder, index);
00265 __ ret(0);
00266 }
00267
00268
00269 void StubCompiler::GenerateLoadCallback(MacroAssembler* masm,
00270 JSObject* object,
00271 JSObject* holder,
00272 Register receiver,
00273 Register name,
00274 Register scratch1,
00275 Register scratch2,
00276 AccessorInfo* callback,
00277 Label* miss_label) {
00278
00279 __ test(receiver, Immediate(kSmiTagMask));
00280 __ j(zero, miss_label, not_taken);
00281
00282
00283 Register reg =
00284 __ CheckMaps(object, receiver, holder, scratch1, scratch2, miss_label);
00285
00286
00287 __ pop(scratch2);
00288 __ push(receiver);
00289 __ push(Immediate(Handle<AccessorInfo>(callback)));
00290 __ push(name);
00291 __ push(reg);
00292 __ push(scratch2);
00293
00294
00295 ExternalReference load_callback_property =
00296 ExternalReference(IC_Utility(IC::kLoadCallbackProperty));
00297 __ TailCallRuntime(load_callback_property, 4);
00298 }
00299
00300
00301 void StubCompiler::GenerateLoadConstant(MacroAssembler* masm,
00302 JSObject* object,
00303 JSObject* holder,
00304 Register receiver,
00305 Register scratch1,
00306 Register scratch2,
00307 Object* value,
00308 Label* miss_label) {
00309
00310 __ test(receiver, Immediate(kSmiTagMask));
00311 __ j(zero, miss_label, not_taken);
00312
00313
00314 Register reg =
00315 __ CheckMaps(object, receiver, holder, scratch1, scratch2, miss_label);
00316
00317
00318 __ mov(eax, Handle<Object>(value));
00319 __ ret(0);
00320 }
00321
00322
00323 void StubCompiler::GenerateLoadInterceptor(MacroAssembler* masm,
00324 JSObject* object,
00325 JSObject* holder,
00326 Register receiver,
00327 Register name,
00328 Register scratch1,
00329 Register scratch2,
00330 Label* miss_label) {
00331
00332 __ test(receiver, Immediate(kSmiTagMask));
00333 __ j(zero, miss_label, not_taken);
00334
00335
00336 Register reg =
00337 __ CheckMaps(object, receiver, holder, scratch1, scratch2, miss_label);
00338
00339
00340 __ pop(scratch2);
00341 __ push(receiver);
00342 __ push(reg);
00343 __ push(name);
00344 __ push(scratch2);
00345
00346
00347 ExternalReference load_ic_property =
00348 ExternalReference(IC_Utility(IC::kLoadInterceptorProperty));
00349 __ TailCallRuntime(load_ic_property, 3);
00350 }
00351
00352
00353 void StubCompiler::GenerateLoadMiss(MacroAssembler* masm, Code::Kind kind) {
00354 ASSERT(kind == Code::LOAD_IC || kind == Code::KEYED_LOAD_IC);
00355 Code* code = NULL;
00356 if (kind == Code::LOAD_IC) {
00357 code = Builtins::builtin(Builtins::LoadIC_Miss);
00358 } else {
00359 code = Builtins::builtin(Builtins::KeyedLoadIC_Miss);
00360 }
00361
00362 Handle<Code> ic(code);
00363 __ jmp(ic, RelocInfo::CODE_TARGET);
00364 }
00365
00366
00367 void StubCompiler::GenerateStoreField(MacroAssembler* masm,
00368 Builtins::Name storage_extend,
00369 JSObject* object,
00370 int index,
00371 Map* transition,
00372 Register receiver_reg,
00373 Register name_reg,
00374 Register scratch,
00375 Label* miss_label) {
00376
00377 __ test(receiver_reg, Immediate(kSmiTagMask));
00378 __ j(zero, miss_label, not_taken);
00379
00380
00381 __ cmp(FieldOperand(receiver_reg, HeapObject::kMapOffset),
00382 Immediate(Handle<Map>(object->map())));
00383 __ j(not_equal, miss_label, not_taken);
00384
00385
00386 if (object->IsJSGlobalProxy()) {
00387 __ CheckAccessGlobalProxy(receiver_reg, scratch, miss_label);
00388 }
00389
00390
00391
00392 ASSERT(object->IsJSGlobalProxy() || !object->IsAccessCheckNeeded());
00393
00394
00395 if ((transition != NULL) && (object->map()->unused_property_fields() == 0)) {
00396
00397
00398 __ mov(Operand(ecx), Immediate(Handle<Map>(transition)));
00399 Handle<Code> ic(Builtins::builtin(storage_extend));
00400 __ jmp(ic, RelocInfo::CODE_TARGET);
00401 return;
00402 }
00403
00404
00405
00406
00407 index -= object->map()->inobject_properties();
00408
00409 if (index >= 0) {
00410
00411 __ mov(scratch, FieldOperand(receiver_reg, JSObject::kPropertiesOffset));
00412 }
00413
00414 if (transition != NULL) {
00415
00416
00417 __ mov(FieldOperand(receiver_reg, HeapObject::kMapOffset),
00418 Immediate(Handle<Map>(transition)));
00419 }
00420
00421 if (index < 0) {
00422
00423 int offset = object->map()->instance_size() + (index * kPointerSize);
00424 __ mov(FieldOperand(receiver_reg, offset), eax);
00425
00426
00427
00428 __ mov(name_reg, Operand(eax));
00429 __ RecordWrite(receiver_reg, offset, name_reg, scratch);
00430 } else {
00431
00432 int offset = index * kPointerSize + Array::kHeaderSize;
00433 __ mov(FieldOperand(scratch, offset), eax);
00434
00435
00436
00437 __ mov(name_reg, Operand(eax));
00438 __ RecordWrite(scratch, offset, name_reg, receiver_reg);
00439 }
00440
00441
00442 __ ret(0);
00443 }
00444
00445
00446 #undef __
00447
00448 #define __ masm()->
00449
00450
00451
00452
00453 Object* StubCompiler::CompileLazyCompile(Code::Flags flags) {
00454 HandleScope scope;
00455
00456
00457 __ EnterInternalFrame();
00458
00459
00460 __ push(edi);
00461
00462 __ push(edi);
00463 __ CallRuntime(Runtime::kLazyCompile, 1);
00464 __ pop(edi);
00465
00466
00467 __ LeaveInternalFrame();
00468
00469
00470 __ lea(ecx, FieldOperand(eax, Code::kHeaderSize));
00471 __ jmp(Operand(ecx));
00472
00473 return GetCodeWithFlags(flags);
00474 }
00475
00476
00477 Object* CallStubCompiler::CompileCallField(Object* object,
00478 JSObject* holder,
00479 int index) {
00480
00481
00482
00483 HandleScope scope;
00484 Label miss;
00485
00486
00487 const int argc = arguments().immediate();
00488 __ mov(edx, Operand(esp, (argc + 1) * kPointerSize));
00489
00490
00491 __ test(edx, Immediate(kSmiTagMask));
00492 __ j(zero, &miss, not_taken);
00493
00494
00495 Register reg =
00496 __ CheckMaps(JSObject::cast(object), edx, holder, ebx, ecx, &miss);
00497
00498 GenerateFastPropertyLoad(masm(), edi, reg, holder, index);
00499
00500
00501 __ test(edi, Immediate(kSmiTagMask));
00502 __ j(zero, &miss, not_taken);
00503 __ mov(ebx, FieldOperand(edi, HeapObject::kMapOffset));
00504 __ movzx_b(ebx, FieldOperand(ebx, Map::kInstanceTypeOffset));
00505 __ cmp(ebx, JS_FUNCTION_TYPE);
00506 __ j(not_equal, &miss, not_taken);
00507
00508
00509
00510 if (object->IsGlobalObject()) {
00511 __ mov(edx, FieldOperand(edx, GlobalObject::kGlobalReceiverOffset));
00512 __ mov(Operand(esp, (argc + 1) * kPointerSize), edx);
00513 }
00514
00515
00516 __ InvokeFunction(edi, arguments(), JUMP_FUNCTION);
00517
00518
00519 __ bind(&miss);
00520 Handle<Code> ic = ComputeCallMiss(arguments().immediate());
00521 __ jmp(ic, RelocInfo::CODE_TARGET);
00522
00523
00524 return GetCode(FIELD);
00525 }
00526
00527
00528 Object* CallStubCompiler::CompileCallConstant(Object* object,
00529 JSObject* holder,
00530 JSFunction* function,
00531 CheckType check) {
00532
00533
00534
00535 HandleScope scope;
00536 Label miss;
00537
00538
00539 const int argc = arguments().immediate();
00540 __ mov(edx, Operand(esp, (argc + 1) * kPointerSize));
00541
00542
00543 if (check != NUMBER_CHECK) {
00544 __ test(edx, Immediate(kSmiTagMask));
00545 __ j(zero, &miss, not_taken);
00546 }
00547
00548
00549
00550 ASSERT(!object->IsGlobalObject() || check == RECEIVER_MAP_CHECK);
00551
00552 switch (check) {
00553 case RECEIVER_MAP_CHECK:
00554
00555 __ CheckMaps(JSObject::cast(object), edx, holder, ebx, ecx, &miss);
00556
00557
00558
00559 if (object->IsGlobalObject()) {
00560 __ mov(edx, FieldOperand(edx, GlobalObject::kGlobalReceiverOffset));
00561 __ mov(Operand(esp, (argc + 1) * kPointerSize), edx);
00562 }
00563 break;
00564
00565 case STRING_CHECK:
00566
00567 __ mov(ecx, FieldOperand(edx, HeapObject::kMapOffset));
00568 __ movzx_b(ecx, FieldOperand(ecx, Map::kInstanceTypeOffset));
00569 __ cmp(ecx, FIRST_NONSTRING_TYPE);
00570 __ j(above_equal, &miss, not_taken);
00571
00572 GenerateLoadGlobalFunctionPrototype(masm(),
00573 Context::STRING_FUNCTION_INDEX,
00574 ecx);
00575 __ CheckMaps(JSObject::cast(object->GetPrototype()),
00576 ecx, holder, ebx, edx, &miss);
00577 break;
00578
00579 case NUMBER_CHECK: {
00580 Label fast;
00581
00582 __ test(edx, Immediate(kSmiTagMask));
00583 __ j(zero, &fast, taken);
00584 __ mov(ecx, FieldOperand(edx, HeapObject::kMapOffset));
00585 __ movzx_b(ecx, FieldOperand(ecx, Map::kInstanceTypeOffset));
00586 __ cmp(ecx, HEAP_NUMBER_TYPE);
00587 __ j(not_equal, &miss, not_taken);
00588 __ bind(&fast);
00589
00590 GenerateLoadGlobalFunctionPrototype(masm(),
00591 Context::NUMBER_FUNCTION_INDEX,
00592 ecx);
00593 __ CheckMaps(JSObject::cast(object->GetPrototype()),
00594 ecx, holder, ebx, edx, &miss);
00595 break;
00596 }
00597
00598 case BOOLEAN_CHECK: {
00599 Label fast;
00600
00601 __ cmp(edx, Factory::true_value());
00602 __ j(equal, &fast, taken);
00603 __ cmp(edx, Factory::false_value());
00604 __ j(not_equal, &miss, not_taken);
00605 __ bind(&fast);
00606
00607 GenerateLoadGlobalFunctionPrototype(masm(),
00608 Context::BOOLEAN_FUNCTION_INDEX,
00609 ecx);
00610 __ CheckMaps(JSObject::cast(object->GetPrototype()),
00611 ecx, holder, ebx, edx, &miss);
00612 break;
00613 }
00614
00615 case JSARRAY_HAS_FAST_ELEMENTS_CHECK:
00616 __ CheckMaps(JSObject::cast(object), edx, holder, ebx, ecx, &miss);
00617
00618
00619 __ mov(ebx, FieldOperand(edx, JSObject::kElementsOffset));
00620
00621 __ cmp(FieldOperand(ebx, HeapObject::kMapOffset),
00622 Immediate(Factory::hash_table_map()));
00623 __ j(equal, &miss, not_taken);
00624 break;
00625
00626 default:
00627 UNREACHABLE();
00628 }
00629
00630
00631 __ mov(Operand(edi), Immediate(Handle<JSFunction>(function)));
00632 __ mov(esi, FieldOperand(edi, JSFunction::kContextOffset));
00633
00634
00635 Handle<Code> code(function->code());
00636 ParameterCount expected(function->shared()->formal_parameter_count());
00637 __ InvokeCode(code, expected, arguments(),
00638 RelocInfo::CODE_TARGET, JUMP_FUNCTION);
00639
00640
00641 __ bind(&miss);
00642 Handle<Code> ic = ComputeCallMiss(arguments().immediate());
00643 __ jmp(ic, RelocInfo::CODE_TARGET);
00644
00645
00646 return GetCode(CONSTANT_FUNCTION);
00647 }
00648
00649
00650 Object* CallStubCompiler::CompileCallInterceptor(Object* object,
00651 JSObject* holder,
00652 String* name) {
00653
00654
00655
00656 HandleScope scope;
00657 Label miss;
00658
00659
00660 const int argc = arguments().immediate();
00661
00662
00663 __ mov(edx, Operand(esp, (argc + 1) * kPointerSize));
00664
00665
00666 __ test(edx, Immediate(kSmiTagMask));
00667 __ j(zero, &miss, not_taken);
00668
00669
00670 Register reg =
00671 __ CheckMaps(JSObject::cast(object), edx, holder, ebx, ecx, &miss);
00672
00673
00674 __ EnterInternalFrame();
00675
00676
00677 __ push(edx);
00678 __ push(reg);
00679 __ push(Operand(ebp, (argc + 3) * kPointerSize));
00680
00681
00682 ExternalReference load_interceptor =
00683 ExternalReference(IC_Utility(IC::kLoadInterceptorProperty));
00684 __ mov(Operand(eax), Immediate(3));
00685 __ mov(Operand(ebx), Immediate(load_interceptor));
00686
00687 CEntryStub stub;
00688 __ CallStub(&stub);
00689
00690
00691 __ mov(Operand(edi), eax);
00692 __ mov(edx, Operand(ebp, (argc + 2) * kPointerSize));
00693
00694
00695 __ LeaveInternalFrame();
00696
00697
00698 __ test(edi, Immediate(kSmiTagMask));
00699 __ j(zero, &miss, not_taken);
00700 __ mov(ebx, FieldOperand(edi, HeapObject::kMapOffset));
00701 __ movzx_b(ebx, FieldOperand(ebx, Map::kInstanceTypeOffset));
00702 __ cmp(ebx, JS_FUNCTION_TYPE);
00703 __ j(not_equal, &miss, not_taken);
00704
00705
00706
00707 if (object->IsGlobalObject()) {
00708 __ mov(edx, FieldOperand(edx, GlobalObject::kGlobalReceiverOffset));
00709 __ mov(Operand(esp, (argc + 1) * kPointerSize), edx);
00710 }
00711
00712
00713 __ InvokeFunction(edi, arguments(), JUMP_FUNCTION);
00714
00715
00716 __ bind(&miss);
00717 Handle<Code> ic = ComputeCallMiss(argc);
00718 __ jmp(ic, RelocInfo::CODE_TARGET);
00719
00720
00721 return GetCode(INTERCEPTOR);
00722 }
00723
00724
00725 Object* StoreStubCompiler::CompileStoreField(JSObject* object,
00726 int index,
00727 Map* transition,
00728 String* name) {
00729
00730
00731
00732
00733
00734
00735
00736 HandleScope scope;
00737 Label miss;
00738
00739
00740 __ mov(ebx, Operand(esp, 1 * kPointerSize));
00741
00742
00743 GenerateStoreField(masm(),
00744 Builtins::StoreIC_ExtendStorage,
00745 object,
00746 index,
00747 transition,
00748 ebx, ecx, edx,
00749 &miss);
00750
00751
00752 __ bind(&miss);
00753 __ mov(Operand(ecx), Immediate(Handle<String>(name)));
00754 Handle<Code> ic(Builtins::builtin(Builtins::StoreIC_Miss));
00755 __ jmp(ic, RelocInfo::CODE_TARGET);
00756
00757
00758 return GetCode(transition == NULL ? FIELD : MAP_TRANSITION);
00759 }
00760
00761
00762 Object* StoreStubCompiler::CompileStoreCallback(JSObject* object,
00763 AccessorInfo* callback,
00764 String* name) {
00765
00766
00767
00768
00769
00770
00771
00772 HandleScope scope;
00773 Label miss;
00774
00775
00776 __ mov(ebx, Operand(esp, 1 * kPointerSize));
00777
00778
00779 __ test(ebx, Immediate(kSmiTagMask));
00780 __ j(zero, &miss, not_taken);
00781
00782
00783 __ cmp(FieldOperand(ebx, HeapObject::kMapOffset),
00784 Immediate(Handle<Map>(object->map())));
00785 __ j(not_equal, &miss, not_taken);
00786
00787
00788 if (object->IsJSGlobalProxy()) {
00789 __ CheckAccessGlobalProxy(ebx, edx, &miss);
00790 }
00791
00792
00793
00794 ASSERT(object->IsJSGlobalProxy() || !object->IsAccessCheckNeeded());
00795
00796 __ pop(ebx);
00797 __ push(Operand(esp, 0));
00798 __ push(Immediate(Handle<AccessorInfo>(callback)));
00799 __ push(ecx);
00800 __ push(eax);
00801 __ push(ebx);
00802
00803
00804 ExternalReference store_callback_property =
00805 ExternalReference(IC_Utility(IC::kStoreCallbackProperty));
00806 __ TailCallRuntime(store_callback_property, 4);
00807
00808
00809 __ bind(&miss);
00810 __ mov(Operand(ecx), Immediate(Handle<String>(name)));
00811 Handle<Code> ic(Builtins::builtin(Builtins::StoreIC_Miss));
00812 __ jmp(ic, RelocInfo::CODE_TARGET);
00813
00814
00815 return GetCode(CALLBACKS);
00816 }
00817
00818
00819 Object* StoreStubCompiler::CompileStoreInterceptor(JSObject* receiver,
00820 String* name) {
00821
00822
00823
00824
00825
00826
00827
00828 HandleScope scope;
00829 Label miss;
00830
00831
00832 __ mov(ebx, Operand(esp, 1 * kPointerSize));
00833
00834
00835 __ test(ebx, Immediate(kSmiTagMask));
00836 __ j(zero, &miss, not_taken);
00837
00838
00839 __ cmp(FieldOperand(ebx, HeapObject::kMapOffset),
00840 Immediate(Handle<Map>(receiver->map())));
00841 __ j(not_equal, &miss, not_taken);
00842
00843
00844 if (receiver->IsJSGlobalProxy()) {
00845 __ CheckAccessGlobalProxy(ebx, edx, &miss);
00846 }
00847
00848
00849
00850 ASSERT(receiver->IsJSGlobalProxy() || !receiver->IsAccessCheckNeeded());
00851
00852 __ pop(ebx);
00853 __ push(Operand(esp, 0));
00854 __ push(ecx);
00855 __ push(eax);
00856 __ push(ebx);
00857
00858
00859 ExternalReference store_ic_property =
00860 ExternalReference(IC_Utility(IC::kStoreInterceptorProperty));
00861 __ TailCallRuntime(store_ic_property, 3);
00862
00863
00864 __ bind(&miss);
00865 __ mov(Operand(ecx), Immediate(Handle<String>(name)));
00866 Handle<Code> ic(Builtins::builtin(Builtins::StoreIC_Miss));
00867 __ jmp(ic, RelocInfo::CODE_TARGET);
00868
00869
00870 return GetCode(INTERCEPTOR);
00871 }
00872
00873
00874 Object* KeyedStoreStubCompiler::CompileStoreField(JSObject* object,
00875 int index,
00876 Map* transition,
00877 String* name) {
00878
00879
00880
00881
00882
00883
00884 HandleScope scope;
00885 Label miss;
00886
00887 __ IncrementCounter(&Counters::keyed_store_field, 1);
00888
00889
00890 __ mov(ecx, Operand(esp, 1 * kPointerSize));
00891
00892 __ cmp(Operand(ecx), Immediate(Handle<String>(name)));
00893 __ j(not_equal, &miss, not_taken);
00894
00895
00896 __ mov(ebx, Operand(esp, 2 * kPointerSize));
00897
00898
00899 GenerateStoreField(masm(),
00900 Builtins::KeyedStoreIC_ExtendStorage,
00901 object,
00902 index,
00903 transition,
00904 ebx, ecx, edx,
00905 &miss);
00906
00907
00908 __ bind(&miss);
00909 __ DecrementCounter(&Counters::keyed_store_field, 1);
00910 Handle<Code> ic(Builtins::builtin(Builtins::KeyedStoreIC_Miss));
00911 __ jmp(ic, RelocInfo::CODE_TARGET);
00912
00913
00914 return GetCode(transition == NULL ? FIELD : MAP_TRANSITION);
00915 }
00916
00917
00918 Object* LoadStubCompiler::CompileLoadField(JSObject* object,
00919 JSObject* holder,
00920 int index) {
00921
00922
00923
00924
00925
00926
00927 HandleScope scope;
00928 Label miss;
00929
00930 __ mov(eax, (Operand(esp, kPointerSize)));
00931 GenerateLoadField(masm(), object, holder, eax, ebx, edx, index, &miss);
00932 __ bind(&miss);
00933 GenerateLoadMiss(masm(), Code::LOAD_IC);
00934
00935
00936 return GetCode(FIELD);
00937 }
00938
00939
00940 Object* LoadStubCompiler::CompileLoadCallback(JSObject* object,
00941 JSObject* holder,
00942 AccessorInfo* callback) {
00943
00944
00945
00946
00947
00948
00949 HandleScope scope;
00950 Label miss;
00951
00952 __ mov(eax, (Operand(esp, kPointerSize)));
00953 GenerateLoadCallback(masm(), object, holder, eax, ecx, ebx,
00954 edx, callback, &miss);
00955 __ bind(&miss);
00956 GenerateLoadMiss(masm(), Code::LOAD_IC);
00957
00958
00959 return GetCode(CALLBACKS);
00960 }
00961
00962
00963 Object* LoadStubCompiler::CompileLoadConstant(JSObject* object,
00964 JSObject* holder,
00965 Object* value) {
00966
00967
00968
00969
00970
00971
00972 HandleScope scope;
00973 Label miss;
00974
00975 __ mov(eax, (Operand(esp, kPointerSize)));
00976 GenerateLoadConstant(masm(), object, holder, eax, ebx, edx, value, &miss);
00977 __ bind(&miss);
00978 GenerateLoadMiss(masm(), Code::LOAD_IC);
00979
00980
00981 return GetCode(CONSTANT_FUNCTION);
00982 }
00983
00984
00985 Object* LoadStubCompiler::CompileLoadInterceptor(JSObject* receiver,
00986 JSObject* holder,
00987 String* name) {
00988
00989
00990
00991
00992
00993 HandleScope scope;
00994 Label miss;
00995
00996 __ mov(eax, (Operand(esp, kPointerSize)));
00997 GenerateLoadInterceptor(masm(), receiver, holder, eax, ecx, edx, ebx, &miss);
00998 __ bind(&miss);
00999 GenerateLoadMiss(masm(), Code::LOAD_IC);
01000
01001
01002 return GetCode(INTERCEPTOR);
01003 }
01004
01005
01006 Object* KeyedLoadStubCompiler::CompileLoadField(String* name,
01007 JSObject* receiver,
01008 JSObject* holder,
01009 int index) {
01010
01011
01012
01013
01014
01015 HandleScope scope;
01016 Label miss;
01017
01018 __ mov(eax, (Operand(esp, kPointerSize)));
01019 __ mov(ecx, (Operand(esp, 2 * kPointerSize)));
01020 __ IncrementCounter(&Counters::keyed_load_field, 1);
01021
01022
01023 __ cmp(Operand(eax), Immediate(Handle<String>(name)));
01024 __ j(not_equal, &miss, not_taken);
01025
01026 GenerateLoadField(masm(), receiver, holder, ecx, ebx, edx, index, &miss);
01027 __ bind(&miss);
01028 __ DecrementCounter(&Counters::keyed_load_field, 1);
01029 GenerateLoadMiss(masm(), Code::KEYED_LOAD_IC);
01030
01031
01032 return GetCode(FIELD);
01033 }
01034
01035
01036 Object* KeyedLoadStubCompiler::CompileLoadCallback(String* name,
01037 JSObject* receiver,
01038 JSObject* holder,
01039 AccessorInfo* callback) {
01040
01041
01042
01043
01044
01045 HandleScope scope;
01046 Label miss;
01047
01048 __ mov(eax, (Operand(esp, kPointerSize)));
01049 __ mov(ecx, (Operand(esp, 2 * kPointerSize)));
01050 __ IncrementCounter(&Counters::keyed_load_callback, 1);
01051
01052
01053 __ cmp(Operand(eax), Immediate(Handle<String>(name)));
01054 __ j(not_equal, &miss, not_taken);
01055
01056 GenerateLoadCallback(masm(), receiver, holder, ecx, eax, ebx, edx,
01057 callback, &miss);
01058 __ bind(&miss);
01059 __ DecrementCounter(&Counters::keyed_load_callback, 1);
01060 GenerateLoadMiss(masm(), Code::KEYED_LOAD_IC);
01061
01062
01063 return GetCode(CALLBACKS);
01064 }
01065
01066
01067 Object* KeyedLoadStubCompiler::CompileLoadConstant(String* name,
01068 JSObject* receiver,
01069 JSObject* holder,
01070 Object* value) {
01071
01072
01073
01074
01075
01076 HandleScope scope;
01077 Label miss;
01078
01079 __ mov(eax, (Operand(esp, kPointerSize)));
01080 __ mov(ecx, (Operand(esp, 2 * kPointerSize)));
01081 __ IncrementCounter(&Counters::keyed_load_constant_function, 1);
01082
01083
01084 __ cmp(Operand(eax), Immediate(Handle<String>(name)));
01085 __ j(not_equal, &miss, not_taken);
01086
01087 GenerateLoadConstant(masm(), receiver, holder, ecx, ebx, edx, value, &miss);
01088 __ bind(&miss);
01089 __ DecrementCounter(&Counters::keyed_load_constant_function, 1);
01090 GenerateLoadMiss(masm(), Code::KEYED_LOAD_IC);
01091
01092
01093 return GetCode(CONSTANT_FUNCTION);
01094 }
01095
01096
01097 Object* KeyedLoadStubCompiler::CompileLoadInterceptor(JSObject* receiver,
01098 JSObject* holder,
01099 String* name) {
01100
01101
01102
01103
01104
01105 HandleScope scope;
01106 Label miss;
01107
01108 __ mov(eax, (Operand(esp, kPointerSize)));
01109 __ mov(ecx, (Operand(esp, 2 * kPointerSize)));
01110 __ IncrementCounter(&Counters::keyed_load_interceptor, 1);
01111
01112
01113 __ cmp(Operand(eax), Immediate(Handle<String>(name)));
01114 __ j(not_equal, &miss, not_taken);
01115
01116 GenerateLoadInterceptor(masm(), receiver, holder, ecx, eax, edx, ebx, &miss);
01117 __ bind(&miss);
01118 __ DecrementCounter(&Counters::keyed_load_interceptor, 1);
01119 GenerateLoadMiss(masm(), Code::KEYED_LOAD_IC);
01120
01121
01122 return GetCode(INTERCEPTOR);
01123 }
01124
01125
01126
01127
01128 Object* KeyedLoadStubCompiler::CompileLoadArrayLength(String* name) {
01129
01130
01131
01132
01133
01134 HandleScope scope;
01135 Label miss;
01136
01137 __ mov(eax, (Operand(esp, kPointerSize)));
01138 __ mov(ecx, (Operand(esp, 2 * kPointerSize)));
01139 __ IncrementCounter(&Counters::keyed_load_array_length, 1);
01140
01141
01142 __ cmp(Operand(eax), Immediate(Handle<String>(name)));
01143 __ j(not_equal, &miss, not_taken);
01144
01145 GenerateLoadArrayLength(masm(), ecx, edx, &miss);
01146 __ bind(&miss);
01147 __ DecrementCounter(&Counters::keyed_load_array_length, 1);
01148 GenerateLoadMiss(masm(), Code::KEYED_LOAD_IC);
01149
01150
01151 return GetCode(CALLBACKS);
01152 }
01153
01154
01155 Object* KeyedLoadStubCompiler::CompileLoadStringLength(String* name) {
01156
01157
01158
01159
01160
01161 HandleScope scope;
01162 Label miss;
01163
01164 __ mov(eax, (Operand(esp, kPointerSize)));
01165 __ mov(ecx, (Operand(esp, 2 * kPointerSize)));
01166 __ IncrementCounter(&Counters::keyed_load_string_length, 1);
01167
01168
01169 __ cmp(Operand(eax), Immediate(Handle<String>(name)));
01170 __ j(not_equal, &miss, not_taken);
01171
01172 GenerateLoadStringLength(masm(), ecx, edx, &miss);
01173 __ bind(&miss);
01174 __ DecrementCounter(&Counters::keyed_load_string_length, 1);
01175 GenerateLoadMiss(masm(), Code::KEYED_LOAD_IC);
01176
01177
01178 return GetCode(CALLBACKS);
01179 }
01180
01181
01182 Object* KeyedLoadStubCompiler::CompileLoadFunctionPrototype(String* name) {
01183
01184
01185
01186
01187
01188 HandleScope scope;
01189 Label miss;
01190
01191 __ mov(eax, (Operand(esp, kPointerSize)));
01192 __ mov(ecx, (Operand(esp, 2 * kPointerSize)));
01193 __ IncrementCounter(&Counters::keyed_load_function_prototype, 1);
01194
01195
01196 __ cmp(Operand(eax), Immediate(Handle<String>(name)));
01197 __ j(not_equal, &miss, not_taken);
01198
01199 GenerateLoadFunctionPrototype(masm(), ecx, edx, ebx, &miss);
01200 __ bind(&miss);
01201 __ DecrementCounter(&Counters::keyed_load_function_prototype, 1);
01202 GenerateLoadMiss(masm(), Code::KEYED_LOAD_IC);
01203
01204
01205 return GetCode(CALLBACKS);
01206 }
01207
01208
01209 #undef __
01210
01211 } }