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
00042 #define __ masm->
00043
00044
00045
00046 static void GenerateDictionaryLoad(MacroAssembler* masm,
00047 Label* miss,
00048 Register t0,
00049 Register t1) {
00050
00051
00052
00053
00054
00055
00056
00057
00058
00059
00060
00061
00062
00063 Label done;
00064
00065
00066
00067 __ ldr(t0, FieldMemOperand(t1, JSObject::kMapOffset));
00068
00069 __ ldr(t0, FieldMemOperand(t1, Map::kInstanceAttributesOffset));
00070 __ tst(t0, Operand(1 << (Map::kHasNamedInterceptor + (3 * 8))));
00071
00072 __ b(ne, miss);
00073
00074
00075
00076 __ ldr(t0, FieldMemOperand(t1, JSObject::kPropertiesOffset));
00077 __ ldr(r3, FieldMemOperand(t0, HeapObject::kMapOffset));
00078 __ cmp(r3, Operand(Factory::hash_table_map()));
00079 __ b(ne, miss);
00080
00081
00082 const int kCapacityOffset =
00083 Array::kHeaderSize + Dictionary::kCapacityIndex * kPointerSize;
00084 __ ldr(r3, FieldMemOperand(t0, kCapacityOffset));
00085 __ mov(r3, Operand(r3, ASR, kSmiTagSize));
00086 __ sub(r3, r3, Operand(1));
00087
00088 const int kElementsStartOffset =
00089 Array::kHeaderSize + Dictionary::kElementsStartIndex * kPointerSize;
00090
00091
00092
00093
00094 static const int kProbes = 4;
00095 for (int i = 0; i < kProbes; i++) {
00096
00097 __ ldr(t1, FieldMemOperand(r2, String::kLengthOffset));
00098 __ mov(t1, Operand(t1, LSR, String::kHashShift));
00099 if (i > 0) __ add(t1, t1, Operand(Dictionary::GetProbeOffset(i)));
00100 __ and_(t1, t1, Operand(r3));
00101
00102
00103 ASSERT(Dictionary::kElementSize == 3);
00104 __ add(t1, t1, Operand(t1, LSL, 1));
00105
00106
00107 __ add(t1, t0, Operand(t1, LSL, 2));
00108 __ ldr(ip, FieldMemOperand(t1, kElementsStartOffset));
00109 __ cmp(r2, Operand(ip));
00110 if (i != kProbes - 1) {
00111 __ b(eq, &done);
00112 } else {
00113 __ b(ne, miss);
00114 }
00115 }
00116
00117
00118 __ bind(&done);
00119 __ ldr(r3, FieldMemOperand(t1, kElementsStartOffset + 2 * kPointerSize));
00120 __ tst(r3, Operand(PropertyDetails::TypeField::mask() << kSmiTagSize));
00121 __ b(ne, miss);
00122
00123
00124 __ ldr(t1, FieldMemOperand(t1, kElementsStartOffset + 1 * kPointerSize));
00125 }
00126
00127
00128 void LoadIC::GenerateArrayLength(MacroAssembler* masm) {
00129
00130
00131
00132
00133
00134
00135 Label miss;
00136
00137 __ ldr(r0, MemOperand(sp, 0));
00138
00139
00140 __ tst(r0, Operand(kSmiTagMask));
00141 __ b(eq, &miss);
00142
00143
00144 __ ldr(r1, FieldMemOperand(r0, HeapObject::kMapOffset));
00145 __ ldrb(r1, FieldMemOperand(r1, Map::kInstanceTypeOffset));
00146 __ cmp(r1, Operand(JS_ARRAY_TYPE));
00147 __ b(ne, &miss);
00148
00149
00150 __ ldr(r0, FieldMemOperand(r0, JSArray::kLengthOffset));
00151 __ Ret();
00152
00153
00154 __ bind(&miss);
00155 Handle<Code> ic(Builtins::builtin(Builtins::LoadIC_Miss));
00156 __ Jump(ic, RelocInfo::CODE_TARGET);
00157 }
00158
00159
00160
00161
00162 static void GenerateStringCheck(MacroAssembler* masm,
00163 Register receiver,
00164 Register scratch1,
00165 Register scratch2,
00166 Label* smi,
00167 Label* non_string_object) {
00168
00169 __ tst(receiver, Operand(kSmiTagMask));
00170 __ b(eq, smi);
00171
00172
00173 __ ldr(scratch1, FieldMemOperand(receiver, HeapObject::kMapOffset));
00174 __ ldrb(scratch1, FieldMemOperand(scratch1, Map::kInstanceTypeOffset));
00175 __ and_(scratch2, scratch1, Operand(kIsNotStringMask));
00176
00177 __ cmp(scratch2, Operand(static_cast<int32_t>(kStringTag)));
00178 __ b(ne, non_string_object);
00179 }
00180
00181
00182 void LoadIC::GenerateStringLength(MacroAssembler* masm) {
00183
00184
00185
00186
00187
00188
00189 Label miss, load_length, check_wrapper;
00190
00191 __ ldr(r0, MemOperand(sp, 0));
00192
00193
00194
00195 GenerateStringCheck(masm, r0, r1, r3, &miss, &check_wrapper);
00196
00197
00198 __ bind(&load_length);
00199 __ and_(r1, r1, Operand(kStringSizeMask));
00200 __ add(r1, r1, Operand(String::kHashShift));
00201 __ ldr(r0, FieldMemOperand(r0, String::kLengthOffset));
00202 __ mov(r0, Operand(r0, LSR, r1));
00203 __ mov(r0, Operand(r0, LSL, kSmiTagSize));
00204 __ Ret();
00205
00206
00207 __ bind(&check_wrapper);
00208 __ cmp(r1, Operand(JS_VALUE_TYPE));
00209 __ b(ne, &miss);
00210
00211
00212
00213 __ ldr(r0, FieldMemOperand(r0, JSValue::kValueOffset));
00214 GenerateStringCheck(masm, r0, r1, r3, &miss, &miss);
00215 __ b(&load_length);
00216
00217
00218 __ bind(&miss);
00219 Handle<Code> ic(Builtins::builtin(Builtins::LoadIC_Miss));
00220 __ Jump(ic, RelocInfo::CODE_TARGET);
00221 }
00222
00223
00224 void LoadIC::GenerateFunctionPrototype(MacroAssembler* masm) {
00225
00226
00227
00228
00229
00230
00231
00232
00233
00234 Handle<Code> ic(Builtins::builtin(Builtins::LoadIC_Miss));
00235 __ Jump(ic, RelocInfo::CODE_TARGET);
00236 }
00237
00238
00239
00240 Object* CallIC_Miss(Arguments args);
00241
00242 void CallIC::GenerateMegamorphic(MacroAssembler* masm, int argc) {
00243
00244
00245
00246 Label number, non_number, non_string, boolean, probe, miss;
00247
00248
00249 __ ldr(r1, MemOperand(sp, argc * kPointerSize));
00250
00251 __ ldr(r2, MemOperand(sp, (argc + 1) * kPointerSize));
00252
00253
00254 Code::Flags flags =
00255 Code::ComputeFlags(Code::CALL_IC, MONOMORPHIC, NORMAL, argc);
00256 StubCache::GenerateProbe(masm, flags, r1, r2, r3);
00257
00258
00259
00260
00261
00262
00263
00264 __ tst(r1, Operand(kSmiTagMask));
00265 __ b(eq, &number);
00266 __ ldr(r3, FieldMemOperand(r1, HeapObject::kMapOffset));
00267 __ ldrb(r3, FieldMemOperand(r3, Map::kInstanceTypeOffset));
00268 __ cmp(r3, Operand(HEAP_NUMBER_TYPE));
00269 __ b(ne, &non_number);
00270 __ bind(&number);
00271 StubCompiler::GenerateLoadGlobalFunctionPrototype(
00272 masm, Context::NUMBER_FUNCTION_INDEX, r1);
00273 __ b(&probe);
00274
00275
00276 __ bind(&non_number);
00277 __ cmp(r3, Operand(FIRST_NONSTRING_TYPE));
00278 __ b(hs, &non_string);
00279 StubCompiler::GenerateLoadGlobalFunctionPrototype(
00280 masm, Context::STRING_FUNCTION_INDEX, r1);
00281 __ b(&probe);
00282
00283
00284 __ bind(&non_string);
00285 __ cmp(r1, Operand(Factory::true_value()));
00286 __ b(eq, &boolean);
00287 __ cmp(r1, Operand(Factory::false_value()));
00288 __ b(ne, &miss);
00289 __ bind(&boolean);
00290 StubCompiler::GenerateLoadGlobalFunctionPrototype(
00291 masm, Context::BOOLEAN_FUNCTION_INDEX, r1);
00292
00293
00294 __ bind(&probe);
00295 StubCache::GenerateProbe(masm, flags, r1, r2, r3);
00296
00297
00298 __ bind(&miss);
00299 Generate(masm, argc, ExternalReference(IC_Utility(kCallIC_Miss)));
00300 }
00301
00302
00303 static void GenerateNormalHelper(MacroAssembler* masm,
00304 int argc,
00305 bool is_global_object,
00306 Label* miss) {
00307
00308 GenerateDictionaryLoad(masm, miss, r0, r1);
00309
00310
00311 __ tst(r1, Operand(kSmiTagMask));
00312 __ b(eq, miss);
00313
00314
00315 __ ldr(r0, FieldMemOperand(r1, HeapObject::kMapOffset));
00316 __ ldrb(r0, FieldMemOperand(r0, Map::kInstanceTypeOffset));
00317 __ cmp(r0, Operand(JS_FUNCTION_TYPE));
00318 __ b(ne, miss);
00319
00320
00321 if (is_global_object) {
00322 __ ldr(r2, MemOperand(sp, argc * kPointerSize));
00323 __ ldr(r2, FieldMemOperand(r2, GlobalObject::kGlobalReceiverOffset));
00324 __ str(r2, MemOperand(sp, argc * kPointerSize));
00325 }
00326
00327
00328 ParameterCount actual(argc);
00329 __ InvokeFunction(r1, actual, JUMP_FUNCTION);
00330 }
00331
00332
00333 void CallIC::GenerateNormal(MacroAssembler* masm, int argc) {
00334
00335
00336
00337
00338 Label miss, global_object, non_global_object;
00339
00340
00341 __ ldr(r1, MemOperand(sp, argc * kPointerSize));
00342
00343 __ ldr(r2, MemOperand(sp, (argc + 1) * kPointerSize));
00344
00345
00346 __ tst(r1, Operand(kSmiTagMask));
00347 __ b(eq, &miss);
00348
00349
00350 __ ldr(r0, FieldMemOperand(r1, HeapObject::kMapOffset));
00351 __ ldrb(r0, FieldMemOperand(r0, Map::kInstanceTypeOffset));
00352 __ cmp(r0, Operand(FIRST_JS_OBJECT_TYPE));
00353 __ b(lt, &miss);
00354
00355
00356 ASSERT(LAST_TYPE == JS_FUNCTION_TYPE);
00357
00358
00359 __ cmp(r0, Operand(JS_GLOBAL_OBJECT_TYPE));
00360 __ b(eq, &global_object);
00361 __ cmp(r0, Operand(JS_BUILTINS_OBJECT_TYPE));
00362 __ b(ne, &non_global_object);
00363
00364
00365 __ bind(&global_object);
00366 GenerateNormalHelper(masm, argc, true, &miss);
00367
00368
00369 Label global_proxy, invoke;
00370 __ bind(&non_global_object);
00371 __ cmp(r0, Operand(JS_GLOBAL_PROXY_TYPE));
00372 __ b(eq, &global_proxy);
00373 __ bind(&invoke);
00374 GenerateNormalHelper(masm, argc, false, &miss);
00375
00376
00377 __ bind(&global_proxy);
00378 __ CheckAccessGlobalProxy(r1, r0, &miss);
00379 __ b(&invoke);
00380
00381
00382 __ bind(&miss);
00383 Generate(masm, argc, ExternalReference(IC_Utility(kCallIC_Miss)));
00384 }
00385
00386
00387 void CallIC::Generate(MacroAssembler* masm,
00388 int argc,
00389 const ExternalReference& f) {
00390
00391
00392
00393
00394
00395 __ ldr(r2, MemOperand(sp, argc * kPointerSize));
00396
00397 __ ldr(r1, MemOperand(sp, (argc + 1) * kPointerSize));
00398
00399 __ EnterInternalFrame();
00400
00401
00402 __ stm(db_w, sp, r1.bit() | r2.bit());
00403
00404
00405 __ mov(r0, Operand(2));
00406 __ mov(r1, Operand(f));
00407
00408 CEntryStub stub;
00409 __ CallStub(&stub);
00410
00411
00412 __ mov(r1, Operand(r0));
00413 __ LeaveInternalFrame();
00414
00415
00416 Label invoke, global;
00417 __ ldr(r2, MemOperand(sp, argc * kPointerSize));
00418 __ tst(r2, Operand(kSmiTagMask));
00419 __ b(eq, &invoke);
00420 __ ldr(r3, FieldMemOperand(r2, HeapObject::kMapOffset));
00421 __ ldrb(r3, FieldMemOperand(r3, Map::kInstanceTypeOffset));
00422 __ cmp(r3, Operand(JS_GLOBAL_OBJECT_TYPE));
00423 __ b(eq, &global);
00424 __ cmp(r3, Operand(JS_BUILTINS_OBJECT_TYPE));
00425 __ b(ne, &invoke);
00426
00427
00428 __ bind(&global);
00429 __ ldr(r2, FieldMemOperand(r2, GlobalObject::kGlobalReceiverOffset));
00430 __ str(r2, MemOperand(sp, argc * kPointerSize));
00431
00432
00433 ParameterCount actual(argc);
00434 __ bind(&invoke);
00435 __ InvokeFunction(r1, actual, JUMP_FUNCTION);
00436 }
00437
00438
00439
00440 Object* LoadIC_Miss(Arguments args);
00441
00442 void LoadIC::GenerateMegamorphic(MacroAssembler* masm) {
00443
00444
00445
00446
00447
00448
00449 __ ldr(r0, MemOperand(sp, 0));
00450
00451 Code::Flags flags = Code::ComputeFlags(Code::LOAD_IC, MONOMORPHIC);
00452 StubCache::GenerateProbe(masm, flags, r0, r2, r3);
00453
00454
00455 Generate(masm, ExternalReference(IC_Utility(kLoadIC_Miss)));
00456 }
00457
00458
00459 void LoadIC::GenerateNormal(MacroAssembler* masm) {
00460
00461
00462
00463
00464
00465
00466 Label miss, probe, global;
00467
00468 __ ldr(r0, MemOperand(sp, 0));
00469
00470 __ tst(r0, Operand(kSmiTagMask));
00471 __ b(eq, &miss);
00472
00473
00474 __ ldr(r1, FieldMemOperand(r0, HeapObject::kMapOffset));
00475 __ ldrb(r1, FieldMemOperand(r1, Map::kInstanceTypeOffset));
00476 __ cmp(r1, Operand(FIRST_JS_OBJECT_TYPE));
00477 __ b(lt, &miss);
00478
00479 ASSERT(LAST_TYPE == JS_FUNCTION_TYPE);
00480
00481
00482 __ cmp(r1, Operand(JS_GLOBAL_PROXY_TYPE));
00483 __ b(eq, &global);
00484
00485 __ bind(&probe);
00486 GenerateDictionaryLoad(masm, &miss, r1, r0);
00487 __ Ret();
00488
00489
00490 __ bind(&global);
00491 __ CheckAccessGlobalProxy(r0, r1, &miss);
00492 __ b(&probe);
00493
00494
00495 __ bind(&miss);
00496 Generate(masm, ExternalReference(IC_Utility(kLoadIC_Miss)));
00497 }
00498
00499
00500 void LoadIC::GenerateMiss(MacroAssembler* masm) {
00501 Generate(masm, ExternalReference(IC_Utility(kLoadIC_Miss)));
00502 }
00503
00504
00505 void LoadIC::Generate(MacroAssembler* masm, const ExternalReference& f) {
00506
00507
00508
00509
00510
00511
00512 __ ldr(r0, MemOperand(sp, 0));
00513 __ push(r0);
00514 __ push(r2);
00515
00516
00517 __ TailCallRuntime(f, 2);
00518 }
00519
00520
00521
00522 void KeyedLoadIC::GenerateMiss(MacroAssembler* masm) {
00523 }
00524
00525 void KeyedLoadIC::Generate(MacroAssembler* masm, const ExternalReference& f) {
00526 }
00527
00528 void KeyedLoadIC::GenerateGeneric(MacroAssembler* masm) {
00529 }
00530
00531 void KeyedStoreIC::Generate(MacroAssembler* masm,
00532 const ExternalReference& f) {
00533 }
00534
00535 void KeyedStoreIC::GenerateGeneric(MacroAssembler* masm) {
00536 }
00537
00538 void KeyedStoreIC::GenerateExtendStorage(MacroAssembler* masm) {
00539 }
00540
00541
00542 void StoreIC::GenerateMegamorphic(MacroAssembler* masm) {
00543
00544
00545
00546
00547
00548
00549
00550
00551 __ ldr(r1, MemOperand(sp));
00552 Code::Flags flags = Code::ComputeFlags(Code::STORE_IC, MONOMORPHIC);
00553 StubCache::GenerateProbe(masm, flags, r1, r2, r3);
00554
00555
00556 Generate(masm, ExternalReference(IC_Utility(kStoreIC_Miss)));
00557 }
00558
00559
00560 void StoreIC::GenerateExtendStorage(MacroAssembler* masm) {
00561
00562
00563
00564
00565
00566
00567
00568 __ ldr(r3, MemOperand(sp));
00569 __ stm(db_w, sp, r0.bit() | r2.bit() | r3.bit());
00570
00571
00572 __ TailCallRuntime(
00573 ExternalReference(IC_Utility(kSharedStoreIC_ExtendStorage)), 3);
00574 }
00575
00576
00577 void StoreIC::Generate(MacroAssembler* masm, const ExternalReference& f) {
00578
00579
00580
00581
00582
00583
00584
00585 __ ldr(r3, MemOperand(sp));
00586 __ stm(db_w, sp, r0.bit() | r2.bit() | r3.bit());
00587
00588
00589 __ TailCallRuntime(f, 3);
00590 }
00591
00592
00593 #undef __
00594
00595
00596 } }