blob: 3513c4037d55cb1a43081bddf028c6d327d88ee9 [file] [log] [blame]
ager@chromium.org9258b6b2008-09-11 09:11:10 +00001// Copyright 2006-2008 the V8 project authors. All rights reserved.
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002// 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) {
kasperl@chromium.orgb9123622008-09-17 14:05:56 +0000157 // ----------- S t a t e -------------
158 // -- r1: function
159 // -- lr: return address
160 // -----------------------------------
161
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000162 HandleScope scope;
163
kasperl@chromium.orgb9123622008-09-17 14:05:56 +0000164 // Enter an internal frame.
165 __ EnterInternalFrame();
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000166
kasperl@chromium.orgb9123622008-09-17 14:05:56 +0000167 // Preserve the function.
168 __ push(r1);
169
170 // Push the function on the stack as the argument to the runtime function.
171 __ push(r1);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000172 __ CallRuntime(Runtime::kLazyCompile, 1);
173
kasperl@chromium.orgb9123622008-09-17 14:05:56 +0000174 // Calculate the entry point.
175 __ add(r2, r0, Operand(Code::kHeaderSize - kHeapObjectTag));
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000176
kasperl@chromium.orgb9123622008-09-17 14:05:56 +0000177 // Restore saved function.
178 __ pop(r1);
179
180 // Tear down temporary frame.
ager@chromium.org236ad962008-09-25 09:45:57 +0000181 __ LeaveInternalFrame();
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000182
183 // Do a tail-call of the compiled function.
kasperl@chromium.orgb9123622008-09-17 14:05:56 +0000184 __ Jump(r2);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000185
186 return GetCodeWithFlags(flags);
187}
188
189
190Object* CallStubCompiler::CompileCallField(Object* object,
191 JSObject* holder,
192 int index) {
193 // ----------- S t a t e -------------
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000194 // -- lr: return address
195 // -----------------------------------
196
197 HandleScope scope;
198 Label miss;
199
mads.s.ager31e71382008-08-13 09:32:07 +0000200 const int argc = arguments().immediate();
201
202 // Get the receiver of the function from the stack into r1.
203 __ ldr(r1, MemOperand(sp, argc * kPointerSize));
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000204 // Check that the receiver isn't a smi.
205 __ tst(r1, Operand(kSmiTagMask));
206 __ b(eq, &miss);
207
208 // Do the right check and compute the holder register.
209 Register reg =
210 __ CheckMaps(JSObject::cast(object), r1, holder, r3, r2, &miss);
211
212 // Get the properties array of the holder and get the function from the field.
213 int offset = index * kPointerSize + Array::kHeaderSize;
kasperl@chromium.orgb9123622008-09-17 14:05:56 +0000214 __ ldr(r1, FieldMemOperand(reg, JSObject::kPropertiesOffset));
215 __ ldr(r1, FieldMemOperand(r1, offset));
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000216
217 // Check that the function really is a function.
kasperl@chromium.orgb9123622008-09-17 14:05:56 +0000218 __ tst(r1, Operand(kSmiTagMask));
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000219 __ b(eq, &miss);
220 // Get the map.
kasperl@chromium.orgb9123622008-09-17 14:05:56 +0000221 __ ldr(r2, FieldMemOperand(r1, HeapObject::kMapOffset));
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000222 __ ldrb(r2, FieldMemOperand(r2, Map::kInstanceTypeOffset));
223 __ cmp(r2, Operand(JS_FUNCTION_TYPE));
224 __ b(ne, &miss);
225
226 // Patch the function on the stack; 1 ~ receiver.
kasperl@chromium.orgb9123622008-09-17 14:05:56 +0000227 __ str(r1, MemOperand(sp, (argc + 1) * kPointerSize));
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000228
kasperl@chromium.orgb9123622008-09-17 14:05:56 +0000229 // Invoke the function.
230 __ InvokeFunction(r1, arguments(), JUMP_FUNCTION);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000231
232 // Handle call cache miss.
233 __ bind(&miss);
234 Handle<Code> ic = ComputeCallMiss(arguments().immediate());
ager@chromium.org236ad962008-09-25 09:45:57 +0000235 __ Jump(ic, RelocInfo::CODE_TARGET);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000236
237 // Return the generated code.
238 return GetCode(FIELD);
239}
240
241
242Object* CallStubCompiler::CompileCallConstant(Object* object,
243 JSObject* holder,
244 JSFunction* function,
245 CheckType check) {
246 // ----------- S t a t e -------------
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000247 // -- lr: return address
248 // -----------------------------------
249
250 HandleScope scope;
251 Label miss;
252
mads.s.ager31e71382008-08-13 09:32:07 +0000253 // Get the receiver from the stack
254 const int argc = arguments().immediate();
255 __ ldr(r1, MemOperand(sp, argc * kPointerSize));
256
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000257 // Check that the receiver isn't a smi.
258 if (check != NUMBER_CHECK) {
259 __ tst(r1, Operand(kSmiTagMask));
260 __ b(eq, &miss);
261 }
262
263 switch (check) {
264 case RECEIVER_MAP_CHECK:
265 // Check that the maps haven't changed.
266 __ CheckMaps(JSObject::cast(object), r1, holder, r3, r2, &miss);
267 break;
268
269 case STRING_CHECK:
270 // Check that the object is a two-byte string or a symbol.
271 __ ldr(r2, FieldMemOperand(r1, HeapObject::kMapOffset));
272 __ ldrb(r2, FieldMemOperand(r2, Map::kInstanceTypeOffset));
273 __ cmp(r2, Operand(FIRST_NONSTRING_TYPE));
274 __ b(hs, &miss);
275 // Check that the maps starting from the prototype haven't changed.
276 GenerateLoadGlobalFunctionPrototype(masm(),
277 Context::STRING_FUNCTION_INDEX,
278 r2);
279 __ CheckMaps(JSObject::cast(object->GetPrototype()),
280 r2, holder, r3, r1, &miss);
281 break;
282
283 case NUMBER_CHECK: {
284 Label fast;
285 // Check that the object is a smi or a heap number.
286 __ tst(r1, Operand(kSmiTagMask));
287 __ b(eq, &fast);
288 __ ldr(r2, FieldMemOperand(r1, HeapObject::kMapOffset));
289 __ ldrb(r2, FieldMemOperand(r2, Map::kInstanceTypeOffset));
290 __ cmp(r2, Operand(HEAP_NUMBER_TYPE));
291 __ b(ne, &miss);
292 __ bind(&fast);
293 // Check that the maps starting from the prototype haven't changed.
294 GenerateLoadGlobalFunctionPrototype(masm(),
295 Context::NUMBER_FUNCTION_INDEX,
296 r2);
297 __ CheckMaps(JSObject::cast(object->GetPrototype()),
298 r2, holder, r3, r1, &miss);
299 break;
300 }
301
302 case BOOLEAN_CHECK: {
303 Label fast;
304 // Check that the object is a boolean.
305 __ cmp(r1, Operand(Factory::true_value()));
306 __ b(eq, &fast);
307 __ cmp(r1, Operand(Factory::false_value()));
308 __ b(ne, &miss);
309 __ bind(&fast);
310 // Check that the maps starting from the prototype haven't changed.
311 GenerateLoadGlobalFunctionPrototype(masm(),
312 Context::BOOLEAN_FUNCTION_INDEX,
313 r2);
314 __ CheckMaps(JSObject::cast(object->GetPrototype()),
315 r2, holder, r3, r1, &miss);
316 break;
317 }
318
319 case JSARRAY_HAS_FAST_ELEMENTS_CHECK:
320 __ CheckMaps(JSObject::cast(object), r1, holder, r3, r2, &miss);
321 // Make sure object->elements()->map() != Heap::hash_table_map()
322 // Get the elements array of the object.
323 __ ldr(r3, FieldMemOperand(r1, JSObject::kElementsOffset));
324 // Check that the object is in fast mode (not dictionary).
325 __ ldr(r2, FieldMemOperand(r3, HeapObject::kMapOffset));
326 __ cmp(r2, Operand(Factory::hash_table_map()));
327 __ b(eq, &miss);
328 break;
329
330 default:
331 UNREACHABLE();
332 }
333
334 // Get the function and setup the context.
kasperl@chromium.orgb9123622008-09-17 14:05:56 +0000335 __ mov(r1, Operand(Handle<JSFunction>(function)));
336 __ ldr(cp, FieldMemOperand(r1, JSFunction::kContextOffset));
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000337
338 // Patch the function on the stack; 1 ~ receiver.
kasperl@chromium.orgb9123622008-09-17 14:05:56 +0000339 __ str(r1, MemOperand(sp, (argc + 1) * kPointerSize));
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000340
341 // Jump to the cached code (tail call).
342 Handle<Code> code(function->code());
mads.s.ager@gmail.com769cc962008-08-06 10:02:49 +0000343 ParameterCount expected(function->shared()->formal_parameter_count());
ager@chromium.org236ad962008-09-25 09:45:57 +0000344 __ InvokeCode(code, expected, arguments(),
345 RelocInfo::CODE_TARGET, JUMP_FUNCTION);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000346
347 // Handle call cache miss.
348 __ bind(&miss);
349 Handle<Code> ic = ComputeCallMiss(arguments().immediate());
ager@chromium.org236ad962008-09-25 09:45:57 +0000350 __ Jump(ic, RelocInfo::CODE_TARGET);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000351
352 // Return the generated code.
353 return GetCode(CONSTANT_FUNCTION);
354}
355
356
357Object* CallStubCompiler::CompileCallInterceptor(Object* object,
358 JSObject* holder,
359 String* name) {
360 // ----------- S t a t e -------------
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000361 // -- lr: return address
362 // -----------------------------------
363
364 HandleScope scope;
365 Label miss;
366
367 // TODO(1224669): Implement.
368
369 // Handle call cache miss.
370 __ bind(&miss);
371 Handle<Code> ic = ComputeCallMiss(arguments().immediate());
ager@chromium.org236ad962008-09-25 09:45:57 +0000372 __ Jump(ic, RelocInfo::CODE_TARGET);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000373
374 // Return the generated code.
375 return GetCode(INTERCEPTOR);
376}
377
378
379Object* StoreStubCompiler::CompileStoreField(JSObject* object,
380 int index,
381 Map* transition,
382 String* name) {
383 // ----------- S t a t e -------------
384 // -- r0 : value
385 // -- r2 : name
386 // -- lr : return address
387 // -- [sp] : receiver
388 // -----------------------------------
389
390 HandleScope scope;
391 Label miss, exit;
392
393 // Get the receiver from the stack.
394 __ ldr(r3, MemOperand(sp, 0 * kPointerSize));
395
396 // Check that the receiver isn't a smi.
397 __ tst(r3, Operand(kSmiTagMask));
398 __ b(eq, &miss);
399
400 // Check that the map of the receiver hasn't changed.
401 __ ldr(r1, FieldMemOperand(r3, HeapObject::kMapOffset));
402 __ cmp(r1, Operand(Handle<Map>(object->map())));
403 __ b(ne, &miss);
404
405 // Perform global security token check if needed.
406 if (object->IsJSGlobalObject()) {
407 __ CheckAccessGlobal(r3, r1, &miss);
408 }
409
410 // Stub never generated for non-global objects that require access
411 // checks.
412 ASSERT(object->IsJSGlobalObject() || !object->IsAccessCheckNeeded());
413
414 // Get the properties array
415 __ ldr(r1, FieldMemOperand(r3, JSObject::kPropertiesOffset));
416
417 // Perform map transition for the receiver if necessary.
418 if (transition != NULL) {
419 // Update the map of the object; no write barrier updating is
420 // needed because the map is never in new space.
421 __ mov(ip, Operand(Handle<Map>(transition)));
422 __ str(ip, FieldMemOperand(r3, HeapObject::kMapOffset));
423 }
424
425 // Write to the properties array.
426 int offset = index * kPointerSize + Array::kHeaderSize;
427 __ str(r0, FieldMemOperand(r1, offset));
428
429 // Skip updating write barrier if storing a smi.
430 __ tst(r0, Operand(kSmiTagMask));
431 __ b(eq, &exit);
432
433 // Update the write barrier for the array address.
434 __ mov(r3, Operand(offset));
435 __ RecordWrite(r1, r3, r2); // OK to clobber r2, since we return
436
437 // Return the value (register r0).
438 __ bind(&exit);
439 __ Ret();
440
441 // Handle store cache miss.
442 __ bind(&miss);
443 __ mov(r2, Operand(Handle<String>(name))); // restore name
444 Handle<Code> ic(Builtins::builtin(Builtins::StoreIC_Miss));
ager@chromium.org236ad962008-09-25 09:45:57 +0000445 __ Jump(ic, RelocInfo::CODE_TARGET);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000446
447 // Return the generated code.
448 return GetCode(transition == NULL ? FIELD : MAP_TRANSITION);
449}
450
451
452Object* StoreStubCompiler::CompileStoreCallback(JSObject* object,
453 AccessorInfo* callback,
454 String* name) {
455 // ----------- S t a t e -------------
456 // -- r0 : value
457 // -- r2 : name
458 // -- lr : return address
459 // -- [sp] : receiver
460 // -----------------------------------
461
462 HandleScope scope;
463 Label miss;
464
465 // Get the object from the stack.
466 __ ldr(r3, MemOperand(sp, 0 * kPointerSize));
467
468 // Check that the object isn't a smi.
469 __ tst(r3, Operand(kSmiTagMask));
470 __ b(eq, &miss);
471
472 // Check that the map of the object hasn't changed.
473 __ ldr(r1, FieldMemOperand(r3, HeapObject::kMapOffset));
474 __ cmp(r1, Operand(Handle<Map>(object->map())));
475 __ b(ne, &miss);
476
477 // Perform global security token check if needed.
478 if (object->IsJSGlobalObject()) {
479 __ CheckAccessGlobal(r3, r1, &miss);
480 }
481
482 // Stub never generated for non-global objects that require access
483 // checks.
484 ASSERT(object->IsJSGlobalObject() || !object->IsAccessCheckNeeded());
485
486 __ ldr(ip, MemOperand(sp)); // receiver
487 __ push(ip);
488 __ mov(ip, Operand(Handle<AccessorInfo>(callback))); // callback info
489 __ push(ip);
490 __ push(r2); // name
491 __ push(r0); // value
492
mads.s.ager31e71382008-08-13 09:32:07 +0000493 // Do tail-call to the runtime system.
494 ExternalReference store_callback_property =
495 ExternalReference(IC_Utility(IC::kStoreCallbackProperty));
496 __ TailCallRuntime(store_callback_property, 4);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000497
498 // Handle store cache miss.
499 __ bind(&miss);
500 __ mov(r2, Operand(Handle<String>(name))); // restore name
501 Handle<Code> ic(Builtins::builtin(Builtins::StoreIC_Miss));
ager@chromium.org236ad962008-09-25 09:45:57 +0000502 __ Jump(ic, RelocInfo::CODE_TARGET);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000503
504 // Return the generated code.
505 return GetCode(CALLBACKS);
506}
507
508
509Object* StoreStubCompiler::CompileStoreInterceptor(JSObject* receiver,
510 String* name) {
511 // ----------- S t a t e -------------
512 // -- r0 : value
513 // -- r2 : name
514 // -- lr : return address
515 // -- [sp] : receiver
516 // -----------------------------------
517
518 HandleScope scope;
519 Label miss;
520
521 // Get the object from the stack.
522 __ ldr(r3, MemOperand(sp, 0 * kPointerSize));
523
524 // Check that the object isn't a smi.
525 __ tst(r3, Operand(kSmiTagMask));
526 __ b(eq, &miss);
527
528 // Check that the map of the object hasn't changed.
529 __ ldr(r1, FieldMemOperand(r3, HeapObject::kMapOffset));
530 __ cmp(r1, Operand(Handle<Map>(receiver->map())));
531 __ b(ne, &miss);
532
533 // Perform global security token check if needed.
534 if (receiver->IsJSGlobalObject()) {
535 __ CheckAccessGlobal(r3, r1, &miss);
536 }
537
538 // Stub never generated for non-global objects that require access
539 // checks.
540 ASSERT(receiver->IsJSGlobalObject() || !receiver->IsAccessCheckNeeded());
541
542 __ ldr(ip, MemOperand(sp)); // receiver
543 __ push(ip);
544 __ push(r2); // name
545 __ push(r0); // value
546
mads.s.ager31e71382008-08-13 09:32:07 +0000547 // Do tail-call to the runtime system.
548 ExternalReference store_ic_property =
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000549 ExternalReference(IC_Utility(IC::kStoreInterceptorProperty));
mads.s.ager31e71382008-08-13 09:32:07 +0000550 __ TailCallRuntime(store_ic_property, 3);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000551
552 // Handle store cache miss.
553 __ bind(&miss);
554 __ mov(r2, Operand(Handle<String>(name))); // restore name
555 Handle<Code> ic(Builtins::builtin(Builtins::StoreIC_Miss));
ager@chromium.org236ad962008-09-25 09:45:57 +0000556 __ Jump(ic, RelocInfo::CODE_TARGET);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000557
558 // Return the generated code.
559 return GetCode(INTERCEPTOR);
560}
561
562
563Object* LoadStubCompiler::CompileLoadField(JSObject* object,
564 JSObject* holder,
565 int index) {
566 // ----------- S t a t e -------------
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000567 // -- r2 : name
568 // -- lr : return address
569 // -- [sp] : receiver
570 // -----------------------------------
571
572 HandleScope scope;
573 Label miss;
574
mads.s.ager31e71382008-08-13 09:32:07 +0000575 __ ldr(r0, MemOperand(sp, 0));
576
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000577 // Check that the receiver isn't a smi.
578 __ tst(r0, Operand(kSmiTagMask));
579 __ b(eq, &miss);
580
581 // Check that the maps haven't changed.
582 Register reg = __ CheckMaps(object, r0, holder, r3, r1, &miss);
583
584 // Get the properties array of the holder.
585 __ ldr(r3, FieldMemOperand(reg, JSObject::kPropertiesOffset));
586
587 // Return the value from the properties array.
588 int offset = index * kPointerSize + Array::kHeaderSize;
589 __ ldr(r0, FieldMemOperand(r3, offset));
590 __ Ret();
591
592 // Handle load cache miss.
593 __ bind(&miss);
594 __ ldr(r0, MemOperand(sp)); // restore receiver
595 Handle<Code> ic(Builtins::builtin(Builtins::LoadIC_Miss));
ager@chromium.org236ad962008-09-25 09:45:57 +0000596 __ Jump(ic, RelocInfo::CODE_TARGET);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000597
598 // Return the generated code.
599 return GetCode(FIELD);
600}
601
602
603Object* LoadStubCompiler::CompileLoadCallback(JSObject* object,
604 JSObject* holder,
605 AccessorInfo* callback) {
606 // ----------- S t a t e -------------
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000607 // -- r2 : name
608 // -- lr : return address
609 // -- [sp] : receiver
610 // -----------------------------------
611
612 HandleScope scope;
613 Label miss;
614
mads.s.ager31e71382008-08-13 09:32:07 +0000615 __ ldr(r0, MemOperand(sp, 0));
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000616 // Check that the receiver isn't a smi.
617 __ tst(r0, Operand(kSmiTagMask));
618 __ b(eq, &miss);
619
620 // Check that the maps haven't changed.
621 Register reg = __ CheckMaps(object, r0, holder, r3, r1, &miss);
622
623 // Push the arguments on the JS stack of the caller.
624 __ push(r0); // receiver
625 __ mov(ip, Operand(Handle<AccessorInfo>(callback))); // callback data
626 __ push(ip);
627 __ push(r2); // name
628 __ push(reg); // holder
629
mads.s.ager31e71382008-08-13 09:32:07 +0000630 // Do tail-call to the runtime system.
631 ExternalReference load_callback_property =
632 ExternalReference(IC_Utility(IC::kLoadCallbackProperty));
633 __ TailCallRuntime(load_callback_property, 4);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000634
635 // Handle load cache miss.
636 __ bind(&miss);
637 Handle<Code> ic(Builtins::builtin(Builtins::LoadIC_Miss));
ager@chromium.org236ad962008-09-25 09:45:57 +0000638 __ Jump(ic, RelocInfo::CODE_TARGET);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000639
640 // Return the generated code.
641 return GetCode(CALLBACKS);
642}
643
644
645Object* LoadStubCompiler::CompileLoadConstant(JSObject* object,
646 JSObject* holder,
647 Object* value) {
648 // ----------- S t a t e -------------
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000649 // -- r2 : name
650 // -- lr : return address
651 // -- [sp] : receiver
652 // -----------------------------------
653
654 HandleScope scope;
655 Label miss;
656
mads.s.ager31e71382008-08-13 09:32:07 +0000657 __ ldr(r0, MemOperand(sp, 0));
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000658 // Check that the receiver isn't a smi.
659 __ tst(r0, Operand(kSmiTagMask));
660 __ b(eq, &miss);
661
662 // Check that the maps haven't changed.
663 Register reg = __ CheckMaps(object, r0, holder, r3, r1, &miss);
664
665 // Return the constant value.
666 __ mov(r0, Operand(Handle<Object>(value)));
667 __ Ret();
668
669 // Handle load cache miss.
670 __ bind(&miss);
671 Handle<Code> ic(Builtins::builtin(Builtins::LoadIC_Miss));
ager@chromium.org236ad962008-09-25 09:45:57 +0000672 __ Jump(ic, RelocInfo::CODE_TARGET);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000673
674 // Return the generated code.
675 return GetCode(CONSTANT_FUNCTION);
676}
677
678
679Object* LoadStubCompiler::CompileLoadInterceptor(JSObject* object,
680 JSObject* holder,
681 String* name) {
682 // ----------- S t a t e -------------
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000683 // -- r2 : name
684 // -- lr : return address
685 // -- [sp] : receiver
686 // -----------------------------------
687
688 HandleScope scope;
689 Label miss;
690
mads.s.ager31e71382008-08-13 09:32:07 +0000691 __ ldr(r0, MemOperand(sp, 0));
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000692 // Check that the receiver isn't a smi.
693 __ tst(r0, Operand(kSmiTagMask));
694 __ b(eq, &miss);
695
696 // Check that the maps haven't changed.
697 Register reg = __ CheckMaps(object, r0, holder, r3, r1, &miss);
698
699 // Push the arguments on the JS stack of the caller.
700 __ push(r0); // receiver
701 __ push(reg); // holder
702 __ push(r2); // name
703
mads.s.ager31e71382008-08-13 09:32:07 +0000704 // Do tail-call to the runtime system.
705 ExternalReference load_ic_property =
706 ExternalReference(IC_Utility(IC::kLoadInterceptorProperty));
707 __ TailCallRuntime(load_ic_property, 3);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000708
709 // Handle load cache miss.
710 __ bind(&miss);
711 Handle<Code> ic(Builtins::builtin(Builtins::LoadIC_Miss));
ager@chromium.org236ad962008-09-25 09:45:57 +0000712 __ Jump(ic, RelocInfo::CODE_TARGET);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000713
714 // Return the generated code.
715 return GetCode(INTERCEPTOR);
716}
717
718
719// TODO(1224671): IC stubs for keyed loads have not been implemented
720// for ARM.
721Object* KeyedLoadStubCompiler::CompileLoadField(String* name,
722 JSObject* receiver,
723 JSObject* holder,
724 int index) {
725 UNIMPLEMENTED();
726 return Heap::undefined_value();
727}
728
729
730Object* KeyedLoadStubCompiler::CompileLoadCallback(String* name,
731 JSObject* receiver,
732 JSObject* holder,
733 AccessorInfo* callback) {
734 UNIMPLEMENTED();
735 return Heap::undefined_value();
736}
737
738
739Object* KeyedLoadStubCompiler::CompileLoadConstant(String* name,
740 JSObject* receiver,
741 JSObject* holder,
742 Object* value) {
743 UNIMPLEMENTED();
744 return Heap::undefined_value();
745}
746
747
748Object* KeyedLoadStubCompiler::CompileLoadInterceptor(JSObject* receiver,
749 JSObject* holder,
750 String* name) {
751 UNIMPLEMENTED();
752 return Heap::undefined_value();
753}
754
755
756Object* KeyedLoadStubCompiler::CompileLoadArrayLength(String* name) {
757 UNIMPLEMENTED();
758 return Heap::undefined_value();
759}
760
761
762Object* KeyedLoadStubCompiler::CompileLoadShortStringLength(String* name) {
763 UNIMPLEMENTED();
764 return Heap::undefined_value();
765}
766
767
768Object* KeyedLoadStubCompiler::CompileLoadMediumStringLength(String* name) {
769 UNIMPLEMENTED();
770 return Heap::undefined_value();
771}
772
773
774Object* KeyedLoadStubCompiler::CompileLoadLongStringLength(String* name) {
775 UNIMPLEMENTED();
776 return Heap::undefined_value();
777}
778
779
780Object* KeyedLoadStubCompiler::CompileLoadFunctionPrototype(String* name) {
781 UNIMPLEMENTED();
782 return Heap::undefined_value();
783}
784
785
786Object* KeyedStoreStubCompiler::CompileStoreField(JSObject* object,
787 int index,
788 Map* transition,
789 String* name) {
790 UNIMPLEMENTED();
791 return Heap::undefined_value();
792}
793
794
795
796#undef __
797
798} } // namespace v8::internal