blob: 91d9140ec683d8898d905b577a25cb6970eac0cc [file] [log] [blame]
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001// Copyright 2006-2008 Google Inc. All Rights Reserved.
2// Redistribution and use in source and binary forms, with or without
3// modification, are permitted provided that the following conditions are
4// met:
5//
6// * Redistributions of source code must retain the above copyright
7// notice, this list of conditions and the following disclaimer.
8// * Redistributions in binary form must reproduce the above
9// copyright notice, this list of conditions and the following
10// disclaimer in the documentation and/or other materials provided
11// with the distribution.
12// * Neither the name of Google Inc. nor the names of its
13// contributors may be used to endorse or promote products derived
14// from this software without specific prior written permission.
15//
16// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
17// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
18// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
19// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
20// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
21// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
22// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
23// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
24// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
25// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
26// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27
28#include "v8.h"
29
30#include "ic-inl.h"
31#include "codegen-inl.h"
32#include "stub-cache.h"
33
34namespace v8 { namespace internal {
35
36#define __ masm->
37
38
39static void ProbeTable(MacroAssembler* masm,
40 Code::Flags flags,
41 StubCache::Table table,
42 Register name,
43 Register offset) {
44 ExternalReference key_offset(SCTableReference::keyReference(table));
45 ExternalReference value_offset(SCTableReference::valueReference(table));
46
47 Label miss;
48
49 // Save the offset on the stack.
50 __ push(offset);
51
52 // Check that the key in the entry matches the name.
53 __ mov(ip, Operand(key_offset));
54 __ ldr(ip, MemOperand(ip, offset, LSL, 1));
55 __ cmp(name, Operand(ip));
56 __ b(ne, &miss);
57
58 // Get the code entry from the cache.
59 __ mov(ip, Operand(value_offset));
60 __ ldr(offset, MemOperand(ip, offset, LSL, 1));
61
62 // Check that the flags match what we're looking for.
63 __ ldr(offset, FieldMemOperand(offset, Code::kFlagsOffset));
64 __ and_(offset, offset, Operand(~Code::kFlagsTypeMask));
65 __ cmp(offset, Operand(flags));
66 __ b(ne, &miss);
67
68 // Restore offset and re-load code entry from cache.
69 __ pop(offset);
70 __ mov(ip, Operand(value_offset));
71 __ ldr(offset, MemOperand(ip, offset, LSL, 1));
72
73 // Jump to the first instruction in the code stub.
74 __ add(offset, offset, Operand(Code::kHeaderSize - kHeapObjectTag));
75 __ Jump(offset);
76
77 // Miss: Restore offset and fall through.
78 __ bind(&miss);
79 __ pop(offset);
80}
81
82
83void StubCache::GenerateProbe(MacroAssembler* masm,
84 Code::Flags flags,
85 Register receiver,
86 Register name,
87 Register scratch) {
88 Label miss;
89
90 // Make sure that code is valid. The shifting code relies on the
91 // entry size being 8.
92 ASSERT(sizeof(Entry) == 8);
93
94 // Make sure the flags does not name a specific type.
95 ASSERT(Code::ExtractTypeFromFlags(flags) == 0);
96
97 // Make sure that there are no register conflicts.
98 ASSERT(!scratch.is(receiver));
99 ASSERT(!scratch.is(name));
100
101 // Check that the receiver isn't a smi.
102 __ tst(receiver, Operand(kSmiTagMask));
103 __ b(eq, &miss);
104
105 // Get the map of the receiver and compute the hash.
106 __ ldr(scratch, FieldMemOperand(receiver, HeapObject::kMapOffset));
107 __ ldr(ip, FieldMemOperand(name, String::kLengthOffset));
108 __ add(scratch, scratch, Operand(ip));
109 __ eor(scratch, scratch, Operand(flags));
110 __ and_(scratch,
111 scratch,
112 Operand((kPrimaryTableSize - 1) << kHeapObjectTagSize));
113
114 // Probe the primary table.
115 ProbeTable(masm, flags, kPrimary, name, scratch);
116
117 // Primary miss: Compute hash for secondary probe.
118 __ sub(scratch, scratch, Operand(name));
119 __ add(scratch, scratch, Operand(flags));
120 __ and_(scratch,
121 scratch,
122 Operand((kSecondaryTableSize - 1) << kHeapObjectTagSize));
123
124 // Probe the secondary table.
125 ProbeTable(masm, flags, kSecondary, name, scratch);
126
127 // Cache miss: Fall-through and let caller handle the miss by
128 // entering the runtime system.
129 __ bind(&miss);
130}
131
132
133void StubCompiler::GenerateLoadGlobalFunctionPrototype(MacroAssembler* masm,
134 int index,
135 Register prototype) {
136 // Load the global or builtins object from the current context.
137 __ ldr(prototype, MemOperand(cp, Context::SlotOffset(Context::GLOBAL_INDEX)));
138 // Load the global context from the global or builtins object.
139 __ ldr(prototype,
140 FieldMemOperand(prototype, GlobalObject::kGlobalContextOffset));
141 // Load the function from the global context.
142 __ ldr(prototype, MemOperand(prototype, Context::SlotOffset(index)));
143 // Load the initial map. The global functions all have initial maps.
144 __ ldr(prototype,
145 FieldMemOperand(prototype, JSFunction::kPrototypeOrInitialMapOffset));
146 // Load the prototype from the initial map.
147 __ ldr(prototype, FieldMemOperand(prototype, Map::kPrototypeOffset));
148}
149
150
151#undef __
152
153#define __ masm()->
154
155
156Object* StubCompiler::CompileLazyCompile(Code::Flags flags) {
157 HandleScope scope;
158
159 // Enter the JS frame but don't add additional arguments.
kasper.lund7276f142008-07-30 08:49:36 +0000160 __ EnterJSFrame(0);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000161
162 // Push the function on the stack and call the runtime function.
mads.s.ager31e71382008-08-13 09:32:07 +0000163 __ ldr(r0, MemOperand(pp, 0));
164 __ push(r0);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000165 __ CallRuntime(Runtime::kLazyCompile, 1);
166
167 // Move result to r1 and restore number of arguments.
168 __ mov(r1, Operand(r0));
169 __ ldr(r0, MemOperand(fp, JavaScriptFrameConstants::kArgsLengthOffset));
170
kasper.lund7276f142008-07-30 08:49:36 +0000171 __ ExitJSFrame(DO_NOT_RETURN);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000172
173 // Do a tail-call of the compiled function.
174 __ add(r1, r1, Operand(Code::kHeaderSize - kHeapObjectTag));
175 __ Jump(r1);
176
177 return GetCodeWithFlags(flags);
178}
179
180
181Object* CallStubCompiler::CompileCallField(Object* object,
182 JSObject* holder,
183 int index) {
184 // ----------- S t a t e -------------
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000185 // -- lr: return address
186 // -----------------------------------
187
188 HandleScope scope;
189 Label miss;
190
mads.s.ager31e71382008-08-13 09:32:07 +0000191 const int argc = arguments().immediate();
192
193 // Get the receiver of the function from the stack into r1.
194 __ ldr(r1, MemOperand(sp, argc * kPointerSize));
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000195 // Check that the receiver isn't a smi.
196 __ tst(r1, Operand(kSmiTagMask));
197 __ b(eq, &miss);
198
199 // Do the right check and compute the holder register.
200 Register reg =
201 __ CheckMaps(JSObject::cast(object), r1, holder, r3, r2, &miss);
202
203 // Get the properties array of the holder and get the function from the field.
204 int offset = index * kPointerSize + Array::kHeaderSize;
205 __ ldr(r3, FieldMemOperand(reg, JSObject::kPropertiesOffset));
206 __ ldr(r3, FieldMemOperand(r3, offset));
207
208 // Check that the function really is a function.
209 __ tst(r3, Operand(kSmiTagMask));
210 __ b(eq, &miss);
211 // Get the map.
212 __ ldr(r2, FieldMemOperand(r3, HeapObject::kMapOffset));
213 __ ldrb(r2, FieldMemOperand(r2, Map::kInstanceTypeOffset));
214 __ cmp(r2, Operand(JS_FUNCTION_TYPE));
215 __ b(ne, &miss);
216
mads.s.ager31e71382008-08-13 09:32:07 +0000217 // TODO(1233523): remove r0 after changing Jump to InvokeCode
218 // Setup argument length register.
219 __ mov(r0, Operand(argc));
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000220 // Patch the function on the stack; 1 ~ receiver.
mads.s.ager31e71382008-08-13 09:32:07 +0000221 __ str(r3, MemOperand(sp, (argc + 1) * kPointerSize));
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000222
223 // Setup the context and jump to the call code of the function (tail call).
224 __ ldr(cp, FieldMemOperand(r3, JSFunction::kContextOffset));
225 __ ldr(r2, FieldMemOperand(r3, JSFunction::kSharedFunctionInfoOffset));
226 __ ldr(r2, FieldMemOperand(r2, SharedFunctionInfo::kCodeOffset));
227 __ add(r2, r2, Operand(Code::kHeaderSize - kHeapObjectTag));
228 __ Jump(r2);
229
230 // Handle call cache miss.
231 __ bind(&miss);
232 Handle<Code> ic = ComputeCallMiss(arguments().immediate());
233 __ Jump(ic, code_target);
234
235 // Return the generated code.
236 return GetCode(FIELD);
237}
238
239
240Object* CallStubCompiler::CompileCallConstant(Object* object,
241 JSObject* holder,
242 JSFunction* function,
243 CheckType check) {
244 // ----------- S t a t e -------------
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000245 // -- lr: return address
246 // -----------------------------------
247
248 HandleScope scope;
249 Label miss;
250
mads.s.ager31e71382008-08-13 09:32:07 +0000251 // Get the receiver from the stack
252 const int argc = arguments().immediate();
253 __ ldr(r1, MemOperand(sp, argc * kPointerSize));
254
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000255 // Check that the receiver isn't a smi.
256 if (check != NUMBER_CHECK) {
257 __ tst(r1, Operand(kSmiTagMask));
258 __ b(eq, &miss);
259 }
260
261 switch (check) {
262 case RECEIVER_MAP_CHECK:
263 // Check that the maps haven't changed.
264 __ CheckMaps(JSObject::cast(object), r1, holder, r3, r2, &miss);
265 break;
266
267 case STRING_CHECK:
268 // Check that the object is a two-byte string or a symbol.
269 __ ldr(r2, FieldMemOperand(r1, HeapObject::kMapOffset));
270 __ ldrb(r2, FieldMemOperand(r2, Map::kInstanceTypeOffset));
271 __ cmp(r2, Operand(FIRST_NONSTRING_TYPE));
272 __ b(hs, &miss);
273 // Check that the maps starting from the prototype haven't changed.
274 GenerateLoadGlobalFunctionPrototype(masm(),
275 Context::STRING_FUNCTION_INDEX,
276 r2);
277 __ CheckMaps(JSObject::cast(object->GetPrototype()),
278 r2, holder, r3, r1, &miss);
279 break;
280
281 case NUMBER_CHECK: {
282 Label fast;
283 // Check that the object is a smi or a heap number.
284 __ tst(r1, Operand(kSmiTagMask));
285 __ b(eq, &fast);
286 __ ldr(r2, FieldMemOperand(r1, HeapObject::kMapOffset));
287 __ ldrb(r2, FieldMemOperand(r2, Map::kInstanceTypeOffset));
288 __ cmp(r2, Operand(HEAP_NUMBER_TYPE));
289 __ b(ne, &miss);
290 __ bind(&fast);
291 // Check that the maps starting from the prototype haven't changed.
292 GenerateLoadGlobalFunctionPrototype(masm(),
293 Context::NUMBER_FUNCTION_INDEX,
294 r2);
295 __ CheckMaps(JSObject::cast(object->GetPrototype()),
296 r2, holder, r3, r1, &miss);
297 break;
298 }
299
300 case BOOLEAN_CHECK: {
301 Label fast;
302 // Check that the object is a boolean.
303 __ cmp(r1, Operand(Factory::true_value()));
304 __ b(eq, &fast);
305 __ cmp(r1, Operand(Factory::false_value()));
306 __ b(ne, &miss);
307 __ bind(&fast);
308 // Check that the maps starting from the prototype haven't changed.
309 GenerateLoadGlobalFunctionPrototype(masm(),
310 Context::BOOLEAN_FUNCTION_INDEX,
311 r2);
312 __ CheckMaps(JSObject::cast(object->GetPrototype()),
313 r2, holder, r3, r1, &miss);
314 break;
315 }
316
317 case JSARRAY_HAS_FAST_ELEMENTS_CHECK:
318 __ CheckMaps(JSObject::cast(object), r1, holder, r3, r2, &miss);
319 // Make sure object->elements()->map() != Heap::hash_table_map()
320 // Get the elements array of the object.
321 __ ldr(r3, FieldMemOperand(r1, JSObject::kElementsOffset));
322 // Check that the object is in fast mode (not dictionary).
323 __ ldr(r2, FieldMemOperand(r3, HeapObject::kMapOffset));
324 __ cmp(r2, Operand(Factory::hash_table_map()));
325 __ b(eq, &miss);
326 break;
327
328 default:
329 UNREACHABLE();
330 }
331
332 // Get the function and setup the context.
333 __ mov(r3, Operand(Handle<JSFunction>(function)));
334 __ ldr(cp, FieldMemOperand(r3, JSFunction::kContextOffset));
335
336 // Patch the function on the stack; 1 ~ receiver.
mads.s.ager@gmail.com769cc962008-08-06 10:02:49 +0000337 __ str(r3, MemOperand(sp, (argc + 1) * kPointerSize));
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000338
339 // Jump to the cached code (tail call).
340 Handle<Code> code(function->code());
mads.s.ager@gmail.com769cc962008-08-06 10:02:49 +0000341 ParameterCount expected(function->shared()->formal_parameter_count());
342 __ InvokeCode(code, expected, arguments(), code_target, JUMP_FUNCTION);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000343
344 // Handle call cache miss.
345 __ bind(&miss);
346 Handle<Code> ic = ComputeCallMiss(arguments().immediate());
347 __ Jump(ic, code_target);
348
349 // Return the generated code.
350 return GetCode(CONSTANT_FUNCTION);
351}
352
353
354Object* CallStubCompiler::CompileCallInterceptor(Object* object,
355 JSObject* holder,
356 String* name) {
357 // ----------- S t a t e -------------
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000358 // -- lr: return address
359 // -----------------------------------
360
361 HandleScope scope;
362 Label miss;
363
364 // TODO(1224669): Implement.
365
366 // Handle call cache miss.
367 __ bind(&miss);
368 Handle<Code> ic = ComputeCallMiss(arguments().immediate());
369 __ Jump(ic, code_target);
370
371 // Return the generated code.
372 return GetCode(INTERCEPTOR);
373}
374
375
376Object* StoreStubCompiler::CompileStoreField(JSObject* object,
377 int index,
378 Map* transition,
379 String* name) {
380 // ----------- S t a t e -------------
381 // -- r0 : value
382 // -- r2 : name
383 // -- lr : return address
384 // -- [sp] : receiver
385 // -----------------------------------
386
387 HandleScope scope;
388 Label miss, exit;
389
390 // Get the receiver from the stack.
391 __ ldr(r3, MemOperand(sp, 0 * kPointerSize));
392
393 // Check that the receiver isn't a smi.
394 __ tst(r3, Operand(kSmiTagMask));
395 __ b(eq, &miss);
396
397 // Check that the map of the receiver hasn't changed.
398 __ ldr(r1, FieldMemOperand(r3, HeapObject::kMapOffset));
399 __ cmp(r1, Operand(Handle<Map>(object->map())));
400 __ b(ne, &miss);
401
402 // Perform global security token check if needed.
403 if (object->IsJSGlobalObject()) {
404 __ CheckAccessGlobal(r3, r1, &miss);
405 }
406
407 // Stub never generated for non-global objects that require access
408 // checks.
409 ASSERT(object->IsJSGlobalObject() || !object->IsAccessCheckNeeded());
410
411 // Get the properties array
412 __ ldr(r1, FieldMemOperand(r3, JSObject::kPropertiesOffset));
413
414 // Perform map transition for the receiver if necessary.
415 if (transition != NULL) {
416 // Update the map of the object; no write barrier updating is
417 // needed because the map is never in new space.
418 __ mov(ip, Operand(Handle<Map>(transition)));
419 __ str(ip, FieldMemOperand(r3, HeapObject::kMapOffset));
420 }
421
422 // Write to the properties array.
423 int offset = index * kPointerSize + Array::kHeaderSize;
424 __ str(r0, FieldMemOperand(r1, offset));
425
426 // Skip updating write barrier if storing a smi.
427 __ tst(r0, Operand(kSmiTagMask));
428 __ b(eq, &exit);
429
430 // Update the write barrier for the array address.
431 __ mov(r3, Operand(offset));
432 __ RecordWrite(r1, r3, r2); // OK to clobber r2, since we return
433
434 // Return the value (register r0).
435 __ bind(&exit);
436 __ Ret();
437
438 // Handle store cache miss.
439 __ bind(&miss);
440 __ mov(r2, Operand(Handle<String>(name))); // restore name
441 Handle<Code> ic(Builtins::builtin(Builtins::StoreIC_Miss));
442 __ Jump(ic, code_target);
443
444 // Return the generated code.
445 return GetCode(transition == NULL ? FIELD : MAP_TRANSITION);
446}
447
448
449Object* StoreStubCompiler::CompileStoreCallback(JSObject* object,
450 AccessorInfo* callback,
451 String* name) {
452 // ----------- S t a t e -------------
453 // -- r0 : value
454 // -- r2 : name
455 // -- lr : return address
456 // -- [sp] : receiver
457 // -----------------------------------
458
459 HandleScope scope;
460 Label miss;
461
462 // Get the object from the stack.
463 __ ldr(r3, MemOperand(sp, 0 * kPointerSize));
464
465 // Check that the object isn't a smi.
466 __ tst(r3, Operand(kSmiTagMask));
467 __ b(eq, &miss);
468
469 // Check that the map of the object hasn't changed.
470 __ ldr(r1, FieldMemOperand(r3, HeapObject::kMapOffset));
471 __ cmp(r1, Operand(Handle<Map>(object->map())));
472 __ b(ne, &miss);
473
474 // Perform global security token check if needed.
475 if (object->IsJSGlobalObject()) {
476 __ CheckAccessGlobal(r3, r1, &miss);
477 }
478
479 // Stub never generated for non-global objects that require access
480 // checks.
481 ASSERT(object->IsJSGlobalObject() || !object->IsAccessCheckNeeded());
482
483 __ ldr(ip, MemOperand(sp)); // receiver
484 __ push(ip);
485 __ mov(ip, Operand(Handle<AccessorInfo>(callback))); // callback info
486 __ push(ip);
487 __ push(r2); // name
488 __ push(r0); // value
489
mads.s.ager31e71382008-08-13 09:32:07 +0000490 // Do tail-call to the runtime system.
491 ExternalReference store_callback_property =
492 ExternalReference(IC_Utility(IC::kStoreCallbackProperty));
493 __ TailCallRuntime(store_callback_property, 4);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000494
495 // Handle store cache miss.
496 __ bind(&miss);
497 __ mov(r2, Operand(Handle<String>(name))); // restore name
498 Handle<Code> ic(Builtins::builtin(Builtins::StoreIC_Miss));
499 __ Jump(ic, code_target);
500
501 // Return the generated code.
502 return GetCode(CALLBACKS);
503}
504
505
506Object* StoreStubCompiler::CompileStoreInterceptor(JSObject* receiver,
507 String* name) {
508 // ----------- S t a t e -------------
509 // -- r0 : value
510 // -- r2 : name
511 // -- lr : return address
512 // -- [sp] : receiver
513 // -----------------------------------
514
515 HandleScope scope;
516 Label miss;
517
518 // Get the object from the stack.
519 __ ldr(r3, MemOperand(sp, 0 * kPointerSize));
520
521 // Check that the object isn't a smi.
522 __ tst(r3, Operand(kSmiTagMask));
523 __ b(eq, &miss);
524
525 // Check that the map of the object hasn't changed.
526 __ ldr(r1, FieldMemOperand(r3, HeapObject::kMapOffset));
527 __ cmp(r1, Operand(Handle<Map>(receiver->map())));
528 __ b(ne, &miss);
529
530 // Perform global security token check if needed.
531 if (receiver->IsJSGlobalObject()) {
532 __ CheckAccessGlobal(r3, r1, &miss);
533 }
534
535 // Stub never generated for non-global objects that require access
536 // checks.
537 ASSERT(receiver->IsJSGlobalObject() || !receiver->IsAccessCheckNeeded());
538
539 __ ldr(ip, MemOperand(sp)); // receiver
540 __ push(ip);
541 __ push(r2); // name
542 __ push(r0); // value
543
mads.s.ager31e71382008-08-13 09:32:07 +0000544 // Do tail-call to the runtime system.
545 ExternalReference store_ic_property =
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000546 ExternalReference(IC_Utility(IC::kStoreInterceptorProperty));
mads.s.ager31e71382008-08-13 09:32:07 +0000547 __ TailCallRuntime(store_ic_property, 3);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000548
549 // Handle store cache miss.
550 __ bind(&miss);
551 __ mov(r2, Operand(Handle<String>(name))); // restore name
552 Handle<Code> ic(Builtins::builtin(Builtins::StoreIC_Miss));
553 __ Jump(ic, code_target);
554
555 // Return the generated code.
556 return GetCode(INTERCEPTOR);
557}
558
559
560Object* LoadStubCompiler::CompileLoadField(JSObject* object,
561 JSObject* holder,
562 int index) {
563 // ----------- S t a t e -------------
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000564 // -- r2 : name
565 // -- lr : return address
566 // -- [sp] : receiver
567 // -----------------------------------
568
569 HandleScope scope;
570 Label miss;
571
mads.s.ager31e71382008-08-13 09:32:07 +0000572 __ ldr(r0, MemOperand(sp, 0));
573
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000574 // Check that the receiver isn't a smi.
575 __ tst(r0, Operand(kSmiTagMask));
576 __ b(eq, &miss);
577
578 // Check that the maps haven't changed.
579 Register reg = __ CheckMaps(object, r0, holder, r3, r1, &miss);
580
581 // Get the properties array of the holder.
582 __ ldr(r3, FieldMemOperand(reg, JSObject::kPropertiesOffset));
583
584 // Return the value from the properties array.
585 int offset = index * kPointerSize + Array::kHeaderSize;
586 __ ldr(r0, FieldMemOperand(r3, offset));
587 __ Ret();
588
589 // Handle load cache miss.
590 __ bind(&miss);
591 __ ldr(r0, MemOperand(sp)); // restore receiver
592 Handle<Code> ic(Builtins::builtin(Builtins::LoadIC_Miss));
593 __ Jump(ic, code_target);
594
595 // Return the generated code.
596 return GetCode(FIELD);
597}
598
599
600Object* LoadStubCompiler::CompileLoadCallback(JSObject* object,
601 JSObject* holder,
602 AccessorInfo* callback) {
603 // ----------- S t a t e -------------
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000604 // -- r2 : name
605 // -- lr : return address
606 // -- [sp] : receiver
607 // -----------------------------------
608
609 HandleScope scope;
610 Label miss;
611
mads.s.ager31e71382008-08-13 09:32:07 +0000612 __ ldr(r0, MemOperand(sp, 0));
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000613 // Check that the receiver isn't a smi.
614 __ tst(r0, Operand(kSmiTagMask));
615 __ b(eq, &miss);
616
617 // Check that the maps haven't changed.
618 Register reg = __ CheckMaps(object, r0, holder, r3, r1, &miss);
619
620 // Push the arguments on the JS stack of the caller.
621 __ push(r0); // receiver
622 __ mov(ip, Operand(Handle<AccessorInfo>(callback))); // callback data
623 __ push(ip);
624 __ push(r2); // name
625 __ push(reg); // holder
626
mads.s.ager31e71382008-08-13 09:32:07 +0000627 // Do tail-call to the runtime system.
628 ExternalReference load_callback_property =
629 ExternalReference(IC_Utility(IC::kLoadCallbackProperty));
630 __ TailCallRuntime(load_callback_property, 4);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000631
632 // Handle load cache miss.
633 __ bind(&miss);
634 Handle<Code> ic(Builtins::builtin(Builtins::LoadIC_Miss));
635 __ Jump(ic, code_target);
636
637 // Return the generated code.
638 return GetCode(CALLBACKS);
639}
640
641
642Object* LoadStubCompiler::CompileLoadConstant(JSObject* object,
643 JSObject* holder,
644 Object* value) {
645 // ----------- S t a t e -------------
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000646 // -- r2 : name
647 // -- lr : return address
648 // -- [sp] : receiver
649 // -----------------------------------
650
651 HandleScope scope;
652 Label miss;
653
mads.s.ager31e71382008-08-13 09:32:07 +0000654 __ ldr(r0, MemOperand(sp, 0));
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000655 // Check that the receiver isn't a smi.
656 __ tst(r0, Operand(kSmiTagMask));
657 __ b(eq, &miss);
658
659 // Check that the maps haven't changed.
660 Register reg = __ CheckMaps(object, r0, holder, r3, r1, &miss);
661
662 // Return the constant value.
663 __ mov(r0, Operand(Handle<Object>(value)));
664 __ Ret();
665
666 // Handle load cache miss.
667 __ bind(&miss);
668 Handle<Code> ic(Builtins::builtin(Builtins::LoadIC_Miss));
669 __ Jump(ic, code_target);
670
671 // Return the generated code.
672 return GetCode(CONSTANT_FUNCTION);
673}
674
675
676Object* LoadStubCompiler::CompileLoadInterceptor(JSObject* object,
677 JSObject* holder,
678 String* name) {
679 // ----------- S t a t e -------------
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000680 // -- r2 : name
681 // -- lr : return address
682 // -- [sp] : receiver
683 // -----------------------------------
684
685 HandleScope scope;
686 Label miss;
687
mads.s.ager31e71382008-08-13 09:32:07 +0000688 __ ldr(r0, MemOperand(sp, 0));
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000689 // Check that the receiver isn't a smi.
690 __ tst(r0, Operand(kSmiTagMask));
691 __ b(eq, &miss);
692
693 // Check that the maps haven't changed.
694 Register reg = __ CheckMaps(object, r0, holder, r3, r1, &miss);
695
696 // Push the arguments on the JS stack of the caller.
697 __ push(r0); // receiver
698 __ push(reg); // holder
699 __ push(r2); // name
700
mads.s.ager31e71382008-08-13 09:32:07 +0000701 // Do tail-call to the runtime system.
702 ExternalReference load_ic_property =
703 ExternalReference(IC_Utility(IC::kLoadInterceptorProperty));
704 __ TailCallRuntime(load_ic_property, 3);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000705
706 // Handle load cache miss.
707 __ bind(&miss);
708 Handle<Code> ic(Builtins::builtin(Builtins::LoadIC_Miss));
709 __ Jump(ic, code_target);
710
711 // Return the generated code.
712 return GetCode(INTERCEPTOR);
713}
714
715
716// TODO(1224671): IC stubs for keyed loads have not been implemented
717// for ARM.
718Object* KeyedLoadStubCompiler::CompileLoadField(String* name,
719 JSObject* receiver,
720 JSObject* holder,
721 int index) {
722 UNIMPLEMENTED();
723 return Heap::undefined_value();
724}
725
726
727Object* KeyedLoadStubCompiler::CompileLoadCallback(String* name,
728 JSObject* receiver,
729 JSObject* holder,
730 AccessorInfo* callback) {
731 UNIMPLEMENTED();
732 return Heap::undefined_value();
733}
734
735
736Object* KeyedLoadStubCompiler::CompileLoadConstant(String* name,
737 JSObject* receiver,
738 JSObject* holder,
739 Object* value) {
740 UNIMPLEMENTED();
741 return Heap::undefined_value();
742}
743
744
745Object* KeyedLoadStubCompiler::CompileLoadInterceptor(JSObject* receiver,
746 JSObject* holder,
747 String* name) {
748 UNIMPLEMENTED();
749 return Heap::undefined_value();
750}
751
752
753Object* KeyedLoadStubCompiler::CompileLoadArrayLength(String* name) {
754 UNIMPLEMENTED();
755 return Heap::undefined_value();
756}
757
758
759Object* KeyedLoadStubCompiler::CompileLoadShortStringLength(String* name) {
760 UNIMPLEMENTED();
761 return Heap::undefined_value();
762}
763
764
765Object* KeyedLoadStubCompiler::CompileLoadMediumStringLength(String* name) {
766 UNIMPLEMENTED();
767 return Heap::undefined_value();
768}
769
770
771Object* KeyedLoadStubCompiler::CompileLoadLongStringLength(String* name) {
772 UNIMPLEMENTED();
773 return Heap::undefined_value();
774}
775
776
777Object* KeyedLoadStubCompiler::CompileLoadFunctionPrototype(String* name) {
778 UNIMPLEMENTED();
779 return Heap::undefined_value();
780}
781
782
783Object* KeyedStoreStubCompiler::CompileStoreField(JSObject* object,
784 int index,
785 Map* transition,
786 String* name) {
787 UNIMPLEMENTED();
788 return Heap::undefined_value();
789}
790
791
792
793#undef __
794
795} } // namespace v8::internal