blob: 3584a4eaf97f03aa682a4c9c006de1df38fbae40 [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.
ager@chromium.org7c537e22008-10-16 08:43:32 +0000106 __ ldr(scratch, FieldMemOperand(name, String::kLengthOffset));
107 __ ldr(ip, FieldMemOperand(receiver, HeapObject::kMapOffset));
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000108 __ 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
ager@chromium.org7c537e22008-10-16 08:43:32 +0000151// Load a fast property out of a holder object (src). In-object properties
152// are loaded directly otherwise the property is loaded from the properties
153// fixed array.
154void StubCompiler::GenerateFastPropertyLoad(MacroAssembler* masm,
155 Register dst, Register src,
156 JSObject* holder, int index) {
157 // Adjust for the number of properties stored in the holder.
158 index -= holder->map()->inobject_properties();
159 if (index < 0) {
160 // Get the property straight out of the holder.
161 int offset = holder->map()->instance_size() + (index * kPointerSize);
162 __ ldr(dst, FieldMemOperand(src, offset));
163 } else {
164 // Calculate the offset into the properties array.
165 int offset = index * kPointerSize + Array::kHeaderSize;
166 __ ldr(dst, FieldMemOperand(src, JSObject::kPropertiesOffset));
167 __ ldr(dst, FieldMemOperand(dst, offset));
168 }
169}
170
171
ager@chromium.org3bf7b912008-11-17 09:09:45 +0000172void StubCompiler::GenerateLoadField(MacroAssembler* masm,
173 JSObject* object,
174 JSObject* holder,
175 Register receiver,
176 Register scratch1,
177 Register scratch2,
178 int index,
179 Label* miss_label) {
180 // Check that the receiver isn't a smi.
181 __ tst(receiver, Operand(kSmiTagMask));
182 __ b(eq, miss_label);
183
184 // Check that the maps haven't changed.
185 Register reg =
186 __ CheckMaps(object, receiver, holder, scratch1, scratch2, miss_label);
187 GenerateFastPropertyLoad(masm, r0, reg, holder, index);
188 __ Ret();
189}
190
191
192void StubCompiler::GenerateLoadConstant(MacroAssembler* masm,
193 JSObject* object,
194 JSObject* holder,
195 Register receiver,
196 Register scratch1,
197 Register scratch2,
198 Object* value,
199 Label* miss_label) {
200 // Check that the receiver isn't a smi.
201 __ tst(receiver, Operand(kSmiTagMask));
202 __ b(eq, miss_label);
203
204 // Check that the maps haven't changed.
205 Register reg =
206 __ CheckMaps(object, receiver, holder, scratch1, scratch2, miss_label);
207
208 // Return the constant value.
209 __ mov(r0, Operand(Handle<Object>(value)));
210 __ Ret();
211}
212
213
214void StubCompiler::GenerateLoadCallback(MacroAssembler* masm,
215 JSObject* object,
216 JSObject* holder,
217 Register receiver,
218 Register name,
219 Register scratch1,
220 Register scratch2,
221 AccessorInfo* callback,
222 Label* miss_label) {
223 // Check that the receiver isn't a smi.
224 __ tst(receiver, Operand(kSmiTagMask));
225 __ b(eq, miss_label);
226
227 // Check that the maps haven't changed.
228 Register reg =
229 __ CheckMaps(object, receiver, holder, scratch1, scratch2, miss_label);
230
231 // Push the arguments on the JS stack of the caller.
232 __ push(receiver); // receiver
233 __ mov(ip, Operand(Handle<AccessorInfo>(callback))); // callback data
234 __ push(ip);
235 __ push(name); // name
236 __ push(reg); // holder
237
238 // Do tail-call to the runtime system.
239 ExternalReference load_callback_property =
240 ExternalReference(IC_Utility(IC::kLoadCallbackProperty));
241 __ TailCallRuntime(load_callback_property, 4);
242}
243
244
245void StubCompiler::GenerateLoadInterceptor(MacroAssembler* masm,
246 JSObject* object,
247 JSObject* holder,
248 Register receiver,
249 Register name,
250 Register scratch1,
251 Register scratch2,
252 Label* miss_label) {
253 // Check that the receiver isn't a smi.
254 __ tst(receiver, Operand(kSmiTagMask));
255 __ b(eq, miss_label);
256
257 // Check that the maps haven't changed.
258 Register reg =
259 __ CheckMaps(object, receiver, holder, scratch1, scratch2, miss_label);
260
261 // Push the arguments on the JS stack of the caller.
262 __ push(receiver); // receiver
263 __ push(reg); // holder
264 __ push(name); // name
265
266 // Do tail-call to the runtime system.
267 ExternalReference load_ic_property =
268 ExternalReference(IC_Utility(IC::kLoadInterceptorProperty));
269 __ TailCallRuntime(load_ic_property, 3);
270}
271
272
273void StubCompiler::GenerateLoadArrayLength(MacroAssembler* masm,
274 Register receiver,
275 Register scratch,
276 Label* miss_label) {
277 // Check that the receiver isn't a smi.
278 __ tst(receiver, Operand(kSmiTagMask));
279 __ b(eq, miss_label);
280
281 // Check that the object is a JS array.
282 __ ldr(scratch, FieldMemOperand(receiver, HeapObject::kMapOffset));
283 __ ldrb(scratch, FieldMemOperand(scratch, Map::kInstanceTypeOffset));
284 __ cmp(scratch, Operand(JS_ARRAY_TYPE));
285 __ b(ne, miss_label);
286
287 // Load length directly from the JS array.
288 __ ldr(r0, FieldMemOperand(receiver, JSArray::kLengthOffset));
289 __ Ret();
290}
291
292
ager@chromium.orga74f0da2008-12-03 16:05:52 +0000293// Generate code to check if an object is a string. If the object is
294// a string, the map's instance type is left in the scratch1 register.
295static void GenerateStringCheck(MacroAssembler* masm,
296 Register receiver,
297 Register scratch1,
298 Register scratch2,
299 Label* smi,
300 Label* non_string_object) {
301 // Check that the receiver isn't a smi.
302 __ tst(receiver, Operand(kSmiTagMask));
303 __ b(eq, smi);
304
305 // Check that the object is a string.
306 __ ldr(scratch1, FieldMemOperand(receiver, HeapObject::kMapOffset));
307 __ ldrb(scratch1, FieldMemOperand(scratch1, Map::kInstanceTypeOffset));
308 __ and_(scratch2, scratch1, Operand(kIsNotStringMask));
309 // The cast is to resolve the overload for the argument of 0x0.
310 __ cmp(scratch2, Operand(static_cast<int32_t>(kStringTag)));
311 __ b(ne, non_string_object);
312}
313
314
315void StubCompiler::GenerateLoadStringLength2(MacroAssembler* masm,
316 Register receiver,
317 Register scratch1,
318 Register scratch2,
319 Label* miss) {
320 Label load_length, check_wrapper;
321
322 // Check if the object is a string leaving the instance type in the
323 // scratch1 register.
324 GenerateStringCheck(masm, receiver, scratch1, scratch2,
325 miss, &check_wrapper);
326
327 // Load length directly from the string.
328 __ bind(&load_length);
329 __ and_(scratch1, scratch1, Operand(kStringSizeMask));
330 __ add(scratch1, scratch1, Operand(String::kHashShift));
331 __ ldr(r0, FieldMemOperand(receiver, String::kLengthOffset));
332 __ mov(r0, Operand(r0, LSR, scratch1));
333 __ mov(r0, Operand(r0, LSL, kSmiTagSize));
334 __ Ret();
335
336 // Check if the object is a JSValue wrapper.
337 __ bind(&check_wrapper);
338 __ cmp(scratch1, Operand(JS_VALUE_TYPE));
339 __ b(ne, miss);
340
341 // Check if the wrapped value is a string and load the length
342 // directly if it is.
343 __ ldr(r0, FieldMemOperand(receiver, JSValue::kValueOffset));
344 GenerateStringCheck(masm, receiver, scratch1, scratch1, miss, miss);
345 __ b(&load_length);
346}
347
348
349// Generate StoreField code, value is passed in r0 register.
350// After executing generated code, the receiver_reg and name_reg
351// may be clobbered.
352void StubCompiler::GenerateStoreField(MacroAssembler* masm,
353 Builtins::Name storage_extend,
354 JSObject* object,
355 int index,
356 Map* transition,
357 Register receiver_reg,
358 Register name_reg,
359 Register scratch,
360 Label* miss_label) {
361 // r0 : value
362 Label exit;
363
364 // Check that the receiver isn't a smi.
365 __ tst(receiver_reg, Operand(kSmiTagMask));
366 __ b(eq, miss_label);
367
368 // Check that the map of the receiver hasn't changed.
369 __ ldr(scratch, FieldMemOperand(receiver_reg, HeapObject::kMapOffset));
370 __ cmp(scratch, Operand(Handle<Map>(object->map())));
371 __ b(ne, miss_label);
372
373 // Perform global security token check if needed.
374 if (object->IsJSGlobalProxy()) {
375 __ CheckAccessGlobalProxy(receiver_reg, scratch, miss_label);
376 }
377
378 // Stub never generated for non-global objects that require access
379 // checks.
380 ASSERT(object->IsJSGlobalProxy() || !object->IsAccessCheckNeeded());
381
382 // Perform map transition for the receiver if necessary.
383 if ((transition != NULL) && (object->map()->unused_property_fields() == 0)) {
384 // The properties must be extended before we can store the value.
385 // We jump to a runtime call that extends the propeties array.
386 __ mov(r2, Operand(Handle<Map>(transition)));
387 // Please note, if we implement keyed store for arm we need
388 // to call the Builtins::KeyedStoreIC_ExtendStorage.
389 Handle<Code> ic(Builtins::builtin(Builtins::StoreIC_ExtendStorage));
390 __ Jump(ic, RelocInfo::CODE_TARGET);
391 return;
392 }
393
394 if (transition != NULL) {
395 // Update the map of the object; no write barrier updating is
396 // needed because the map is never in new space.
397 __ mov(ip, Operand(Handle<Map>(transition)));
398 __ str(ip, FieldMemOperand(receiver_reg, HeapObject::kMapOffset));
399 }
400
401 // Adjust for the number of properties stored in the object. Even in the
402 // face of a transition we can use the old map here because the size of the
403 // object and the number of in-object properties is not going to change.
404 index -= object->map()->inobject_properties();
405
406 if (index < 0) {
407 // Set the property straight into the object.
408 int offset = object->map()->instance_size() + (index * kPointerSize);
409 __ str(r0, FieldMemOperand(receiver_reg, offset));
410
411 // Skip updating write barrier if storing a smi.
412 __ tst(r0, Operand(kSmiTagMask));
413 __ b(eq, &exit);
414
415 // Update the write barrier for the array address.
416 // Pass the value being stored in the now unused name_reg.
417 __ mov(name_reg, Operand(offset));
418 __ RecordWrite(receiver_reg, name_reg, scratch);
419 } else {
420 // Write to the properties array.
421 int offset = index * kPointerSize + Array::kHeaderSize;
422 // Get the properties array
423 __ ldr(scratch, FieldMemOperand(receiver_reg, JSObject::kPropertiesOffset));
424 __ str(r0, FieldMemOperand(scratch, 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 // Ok to clobber receiver_reg and name_reg, since we return.
432 __ mov(name_reg, Operand(offset));
433 __ RecordWrite(scratch, name_reg, receiver_reg);
434 }
435
436 // Return the value (register r0).
437 __ bind(&exit);
438 __ Ret();
439}
440
441
ager@chromium.org3bf7b912008-11-17 09:09:45 +0000442void StubCompiler::GenerateLoadMiss(MacroAssembler* masm, Code::Kind kind) {
443 ASSERT(kind == Code::LOAD_IC || kind == Code::KEYED_LOAD_IC);
444 Code* code = NULL;
445 if (kind == Code::LOAD_IC) {
446 code = Builtins::builtin(Builtins::LoadIC_Miss);
447 } else {
448 code = Builtins::builtin(Builtins::KeyedLoadIC_Miss);
449 }
450
451 Handle<Code> ic(code);
452 __ Jump(ic, RelocInfo::CODE_TARGET);
453}
454
455
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000456#undef __
457
458#define __ masm()->
459
460
461Object* StubCompiler::CompileLazyCompile(Code::Flags flags) {
kasperl@chromium.orgb9123622008-09-17 14:05:56 +0000462 // ----------- S t a t e -------------
463 // -- r1: function
464 // -- lr: return address
465 // -----------------------------------
466
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000467 HandleScope scope;
468
kasperl@chromium.orgb9123622008-09-17 14:05:56 +0000469 // Enter an internal frame.
470 __ EnterInternalFrame();
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000471
kasperl@chromium.orgb9123622008-09-17 14:05:56 +0000472 // Preserve the function.
473 __ push(r1);
474
475 // Push the function on the stack as the argument to the runtime function.
476 __ push(r1);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000477 __ CallRuntime(Runtime::kLazyCompile, 1);
478
kasperl@chromium.orgb9123622008-09-17 14:05:56 +0000479 // Calculate the entry point.
480 __ add(r2, r0, Operand(Code::kHeaderSize - kHeapObjectTag));
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000481
kasperl@chromium.orgb9123622008-09-17 14:05:56 +0000482 // Restore saved function.
483 __ pop(r1);
484
485 // Tear down temporary frame.
ager@chromium.org236ad962008-09-25 09:45:57 +0000486 __ LeaveInternalFrame();
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000487
488 // Do a tail-call of the compiled function.
kasperl@chromium.orgb9123622008-09-17 14:05:56 +0000489 __ Jump(r2);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000490
491 return GetCodeWithFlags(flags);
492}
493
494
495Object* CallStubCompiler::CompileCallField(Object* object,
496 JSObject* holder,
497 int index) {
498 // ----------- S t a t e -------------
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000499 // -- lr: return address
500 // -----------------------------------
501
502 HandleScope scope;
503 Label miss;
504
mads.s.ager31e71382008-08-13 09:32:07 +0000505 const int argc = arguments().immediate();
506
kasperl@chromium.org9fe21c62008-10-28 08:53:51 +0000507 // Get the receiver of the function from the stack into r0.
508 __ ldr(r0, MemOperand(sp, argc * kPointerSize));
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000509 // Check that the receiver isn't a smi.
kasperl@chromium.org9fe21c62008-10-28 08:53:51 +0000510 __ tst(r0, Operand(kSmiTagMask));
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000511 __ b(eq, &miss);
512
513 // Do the right check and compute the holder register.
514 Register reg =
kasperl@chromium.org9fe21c62008-10-28 08:53:51 +0000515 __ CheckMaps(JSObject::cast(object), r0, holder, r3, r2, &miss);
ager@chromium.org7c537e22008-10-16 08:43:32 +0000516 GenerateFastPropertyLoad(masm(), r1, reg, holder, index);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000517
518 // Check that the function really is a function.
kasperl@chromium.orgb9123622008-09-17 14:05:56 +0000519 __ tst(r1, Operand(kSmiTagMask));
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000520 __ b(eq, &miss);
521 // Get the map.
kasperl@chromium.orgb9123622008-09-17 14:05:56 +0000522 __ ldr(r2, FieldMemOperand(r1, HeapObject::kMapOffset));
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000523 __ ldrb(r2, FieldMemOperand(r2, Map::kInstanceTypeOffset));
524 __ cmp(r2, Operand(JS_FUNCTION_TYPE));
525 __ b(ne, &miss);
526
kasperl@chromium.org9fe21c62008-10-28 08:53:51 +0000527 // Patch the receiver on the stack with the global proxy if
528 // necessary.
529 if (object->IsGlobalObject()) {
530 __ ldr(r3, FieldMemOperand(r0, GlobalObject::kGlobalReceiverOffset));
531 __ str(r3, MemOperand(sp, argc * kPointerSize));
532 }
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000533
kasperl@chromium.orgb9123622008-09-17 14:05:56 +0000534 // Invoke the function.
535 __ InvokeFunction(r1, arguments(), JUMP_FUNCTION);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000536
537 // Handle call cache miss.
538 __ bind(&miss);
539 Handle<Code> ic = ComputeCallMiss(arguments().immediate());
ager@chromium.org236ad962008-09-25 09:45:57 +0000540 __ Jump(ic, RelocInfo::CODE_TARGET);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000541
542 // Return the generated code.
543 return GetCode(FIELD);
544}
545
546
547Object* CallStubCompiler::CompileCallConstant(Object* object,
548 JSObject* holder,
549 JSFunction* function,
550 CheckType check) {
551 // ----------- S t a t e -------------
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000552 // -- lr: return address
553 // -----------------------------------
554
555 HandleScope scope;
556 Label miss;
557
mads.s.ager31e71382008-08-13 09:32:07 +0000558 // Get the receiver from the stack
559 const int argc = arguments().immediate();
560 __ ldr(r1, MemOperand(sp, argc * kPointerSize));
561
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000562 // Check that the receiver isn't a smi.
563 if (check != NUMBER_CHECK) {
564 __ tst(r1, Operand(kSmiTagMask));
565 __ b(eq, &miss);
566 }
567
kasperl@chromium.org9fe21c62008-10-28 08:53:51 +0000568 // Make sure that it's okay not to patch the on stack receiver
569 // unless we're doing a receiver map check.
570 ASSERT(!object->IsGlobalObject() || check == RECEIVER_MAP_CHECK);
571
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000572 switch (check) {
573 case RECEIVER_MAP_CHECK:
574 // Check that the maps haven't changed.
575 __ CheckMaps(JSObject::cast(object), r1, holder, r3, r2, &miss);
kasperl@chromium.org9fe21c62008-10-28 08:53:51 +0000576
577 // Patch the receiver on the stack with the global proxy if
578 // necessary.
579 if (object->IsGlobalObject()) {
580 __ ldr(r3, FieldMemOperand(r1, GlobalObject::kGlobalReceiverOffset));
581 __ str(r3, MemOperand(sp, argc * kPointerSize));
582 }
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000583 break;
584
585 case STRING_CHECK:
586 // Check that the object is a two-byte string or a symbol.
587 __ ldr(r2, FieldMemOperand(r1, HeapObject::kMapOffset));
588 __ ldrb(r2, FieldMemOperand(r2, Map::kInstanceTypeOffset));
589 __ cmp(r2, Operand(FIRST_NONSTRING_TYPE));
590 __ b(hs, &miss);
591 // Check that the maps starting from the prototype haven't changed.
592 GenerateLoadGlobalFunctionPrototype(masm(),
593 Context::STRING_FUNCTION_INDEX,
594 r2);
595 __ CheckMaps(JSObject::cast(object->GetPrototype()),
596 r2, holder, r3, r1, &miss);
597 break;
598
599 case NUMBER_CHECK: {
600 Label fast;
601 // Check that the object is a smi or a heap number.
602 __ tst(r1, Operand(kSmiTagMask));
603 __ b(eq, &fast);
604 __ ldr(r2, FieldMemOperand(r1, HeapObject::kMapOffset));
605 __ ldrb(r2, FieldMemOperand(r2, Map::kInstanceTypeOffset));
606 __ cmp(r2, Operand(HEAP_NUMBER_TYPE));
607 __ b(ne, &miss);
608 __ bind(&fast);
609 // Check that the maps starting from the prototype haven't changed.
610 GenerateLoadGlobalFunctionPrototype(masm(),
611 Context::NUMBER_FUNCTION_INDEX,
612 r2);
613 __ CheckMaps(JSObject::cast(object->GetPrototype()),
614 r2, holder, r3, r1, &miss);
615 break;
616 }
617
618 case BOOLEAN_CHECK: {
619 Label fast;
620 // Check that the object is a boolean.
621 __ cmp(r1, Operand(Factory::true_value()));
622 __ b(eq, &fast);
623 __ cmp(r1, Operand(Factory::false_value()));
624 __ b(ne, &miss);
625 __ bind(&fast);
626 // Check that the maps starting from the prototype haven't changed.
627 GenerateLoadGlobalFunctionPrototype(masm(),
628 Context::BOOLEAN_FUNCTION_INDEX,
629 r2);
630 __ CheckMaps(JSObject::cast(object->GetPrototype()),
631 r2, holder, r3, r1, &miss);
632 break;
633 }
634
635 case JSARRAY_HAS_FAST_ELEMENTS_CHECK:
636 __ CheckMaps(JSObject::cast(object), r1, holder, r3, r2, &miss);
637 // Make sure object->elements()->map() != Heap::hash_table_map()
638 // Get the elements array of the object.
639 __ ldr(r3, FieldMemOperand(r1, JSObject::kElementsOffset));
640 // Check that the object is in fast mode (not dictionary).
641 __ ldr(r2, FieldMemOperand(r3, HeapObject::kMapOffset));
642 __ cmp(r2, Operand(Factory::hash_table_map()));
643 __ b(eq, &miss);
644 break;
645
646 default:
647 UNREACHABLE();
648 }
649
650 // Get the function and setup the context.
kasperl@chromium.orgb9123622008-09-17 14:05:56 +0000651 __ mov(r1, Operand(Handle<JSFunction>(function)));
652 __ ldr(cp, FieldMemOperand(r1, JSFunction::kContextOffset));
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000653
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000654 // Jump to the cached code (tail call).
655 Handle<Code> code(function->code());
mads.s.ager@gmail.com769cc962008-08-06 10:02:49 +0000656 ParameterCount expected(function->shared()->formal_parameter_count());
ager@chromium.org236ad962008-09-25 09:45:57 +0000657 __ InvokeCode(code, expected, arguments(),
658 RelocInfo::CODE_TARGET, JUMP_FUNCTION);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000659
660 // Handle call cache miss.
661 __ bind(&miss);
662 Handle<Code> ic = ComputeCallMiss(arguments().immediate());
ager@chromium.org236ad962008-09-25 09:45:57 +0000663 __ Jump(ic, RelocInfo::CODE_TARGET);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000664
665 // Return the generated code.
666 return GetCode(CONSTANT_FUNCTION);
667}
668
669
670Object* CallStubCompiler::CompileCallInterceptor(Object* object,
671 JSObject* holder,
672 String* name) {
673 // ----------- S t a t e -------------
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000674 // -- lr: return address
675 // -----------------------------------
676
677 HandleScope scope;
678 Label miss;
679
680 // TODO(1224669): Implement.
681
682 // Handle call cache miss.
683 __ bind(&miss);
684 Handle<Code> ic = ComputeCallMiss(arguments().immediate());
ager@chromium.org236ad962008-09-25 09:45:57 +0000685 __ Jump(ic, RelocInfo::CODE_TARGET);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000686
687 // Return the generated code.
688 return GetCode(INTERCEPTOR);
689}
690
691
692Object* StoreStubCompiler::CompileStoreField(JSObject* object,
693 int index,
694 Map* transition,
695 String* name) {
696 // ----------- S t a t e -------------
697 // -- r0 : value
698 // -- r2 : name
699 // -- lr : return address
700 // -- [sp] : receiver
701 // -----------------------------------
702
703 HandleScope scope;
ager@chromium.orga74f0da2008-12-03 16:05:52 +0000704 Label miss;
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000705
706 // Get the receiver from the stack.
707 __ ldr(r3, MemOperand(sp, 0 * kPointerSize));
708
ager@chromium.orga74f0da2008-12-03 16:05:52 +0000709 // name register might be clobbered.
710 GenerateStoreField(masm(),
711 Builtins::StoreIC_ExtendStorage,
712 object,
713 index,
714 transition,
715 r3, r2, r1,
716 &miss);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000717 __ bind(&miss);
718 __ mov(r2, Operand(Handle<String>(name))); // restore name
719 Handle<Code> ic(Builtins::builtin(Builtins::StoreIC_Miss));
ager@chromium.org236ad962008-09-25 09:45:57 +0000720 __ Jump(ic, RelocInfo::CODE_TARGET);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000721
722 // Return the generated code.
723 return GetCode(transition == NULL ? FIELD : MAP_TRANSITION);
724}
725
726
727Object* StoreStubCompiler::CompileStoreCallback(JSObject* object,
728 AccessorInfo* callback,
729 String* name) {
730 // ----------- S t a t e -------------
731 // -- r0 : value
732 // -- r2 : name
733 // -- lr : return address
734 // -- [sp] : receiver
735 // -----------------------------------
736
737 HandleScope scope;
738 Label miss;
739
740 // Get the object from the stack.
741 __ ldr(r3, MemOperand(sp, 0 * kPointerSize));
742
743 // Check that the object isn't a smi.
744 __ tst(r3, Operand(kSmiTagMask));
745 __ b(eq, &miss);
746
747 // Check that the map of the object hasn't changed.
748 __ ldr(r1, FieldMemOperand(r3, HeapObject::kMapOffset));
749 __ cmp(r1, Operand(Handle<Map>(object->map())));
750 __ b(ne, &miss);
751
752 // Perform global security token check if needed.
kasperl@chromium.org5a8ca6c2008-10-23 13:57:19 +0000753 if (object->IsJSGlobalProxy()) {
754 __ CheckAccessGlobalProxy(r3, r1, &miss);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000755 }
756
757 // Stub never generated for non-global objects that require access
758 // checks.
kasperl@chromium.org5a8ca6c2008-10-23 13:57:19 +0000759 ASSERT(object->IsJSGlobalProxy() || !object->IsAccessCheckNeeded());
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000760
761 __ ldr(ip, MemOperand(sp)); // receiver
762 __ push(ip);
763 __ mov(ip, Operand(Handle<AccessorInfo>(callback))); // callback info
764 __ push(ip);
765 __ push(r2); // name
766 __ push(r0); // value
767
mads.s.ager31e71382008-08-13 09:32:07 +0000768 // Do tail-call to the runtime system.
769 ExternalReference store_callback_property =
770 ExternalReference(IC_Utility(IC::kStoreCallbackProperty));
771 __ TailCallRuntime(store_callback_property, 4);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000772
773 // Handle store cache miss.
774 __ bind(&miss);
775 __ mov(r2, Operand(Handle<String>(name))); // restore name
776 Handle<Code> ic(Builtins::builtin(Builtins::StoreIC_Miss));
ager@chromium.org236ad962008-09-25 09:45:57 +0000777 __ Jump(ic, RelocInfo::CODE_TARGET);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000778
779 // Return the generated code.
780 return GetCode(CALLBACKS);
781}
782
783
784Object* StoreStubCompiler::CompileStoreInterceptor(JSObject* receiver,
785 String* name) {
786 // ----------- S t a t e -------------
787 // -- r0 : value
788 // -- r2 : name
789 // -- lr : return address
790 // -- [sp] : receiver
791 // -----------------------------------
792
793 HandleScope scope;
794 Label miss;
795
796 // Get the object from the stack.
797 __ ldr(r3, MemOperand(sp, 0 * kPointerSize));
798
799 // Check that the object isn't a smi.
800 __ tst(r3, Operand(kSmiTagMask));
801 __ b(eq, &miss);
802
803 // Check that the map of the object hasn't changed.
804 __ ldr(r1, FieldMemOperand(r3, HeapObject::kMapOffset));
805 __ cmp(r1, Operand(Handle<Map>(receiver->map())));
806 __ b(ne, &miss);
807
808 // Perform global security token check if needed.
kasperl@chromium.org5a8ca6c2008-10-23 13:57:19 +0000809 if (receiver->IsJSGlobalProxy()) {
810 __ CheckAccessGlobalProxy(r3, r1, &miss);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000811 }
812
813 // Stub never generated for non-global objects that require access
814 // checks.
kasperl@chromium.org5a8ca6c2008-10-23 13:57:19 +0000815 ASSERT(receiver->IsJSGlobalProxy() || !receiver->IsAccessCheckNeeded());
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000816
817 __ ldr(ip, MemOperand(sp)); // receiver
818 __ push(ip);
819 __ push(r2); // name
820 __ push(r0); // value
821
mads.s.ager31e71382008-08-13 09:32:07 +0000822 // Do tail-call to the runtime system.
823 ExternalReference store_ic_property =
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000824 ExternalReference(IC_Utility(IC::kStoreInterceptorProperty));
mads.s.ager31e71382008-08-13 09:32:07 +0000825 __ TailCallRuntime(store_ic_property, 3);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000826
827 // Handle store cache miss.
828 __ bind(&miss);
829 __ mov(r2, Operand(Handle<String>(name))); // restore name
830 Handle<Code> ic(Builtins::builtin(Builtins::StoreIC_Miss));
ager@chromium.org236ad962008-09-25 09:45:57 +0000831 __ Jump(ic, RelocInfo::CODE_TARGET);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000832
833 // Return the generated code.
834 return GetCode(INTERCEPTOR);
835}
836
837
838Object* LoadStubCompiler::CompileLoadField(JSObject* object,
839 JSObject* holder,
840 int index) {
841 // ----------- S t a t e -------------
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000842 // -- r2 : name
843 // -- lr : return address
844 // -- [sp] : receiver
845 // -----------------------------------
846
847 HandleScope scope;
848 Label miss;
849
mads.s.ager31e71382008-08-13 09:32:07 +0000850 __ ldr(r0, MemOperand(sp, 0));
851
ager@chromium.org3bf7b912008-11-17 09:09:45 +0000852 GenerateLoadField(masm(), object, holder, r0, r3, r1, index, &miss);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000853 __ bind(&miss);
ager@chromium.org3bf7b912008-11-17 09:09:45 +0000854 GenerateLoadMiss(masm(), Code::LOAD_IC);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000855
856 // Return the generated code.
857 return GetCode(FIELD);
858}
859
860
861Object* LoadStubCompiler::CompileLoadCallback(JSObject* object,
862 JSObject* holder,
863 AccessorInfo* callback) {
864 // ----------- S t a t e -------------
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000865 // -- r2 : name
866 // -- lr : return address
867 // -- [sp] : receiver
868 // -----------------------------------
869
870 HandleScope scope;
871 Label miss;
872
mads.s.ager31e71382008-08-13 09:32:07 +0000873 __ ldr(r0, MemOperand(sp, 0));
ager@chromium.org3bf7b912008-11-17 09:09:45 +0000874 GenerateLoadCallback(masm(), object, holder, r0, r2, r3, r1, callback, &miss);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000875 __ bind(&miss);
ager@chromium.org3bf7b912008-11-17 09:09:45 +0000876 GenerateLoadMiss(masm(), Code::LOAD_IC);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000877
878 // Return the generated code.
879 return GetCode(CALLBACKS);
880}
881
882
883Object* LoadStubCompiler::CompileLoadConstant(JSObject* object,
884 JSObject* holder,
885 Object* value) {
886 // ----------- S t a t e -------------
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000887 // -- r2 : name
888 // -- lr : return address
889 // -- [sp] : receiver
890 // -----------------------------------
891
892 HandleScope scope;
893 Label miss;
894
mads.s.ager31e71382008-08-13 09:32:07 +0000895 __ ldr(r0, MemOperand(sp, 0));
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000896
ager@chromium.org3bf7b912008-11-17 09:09:45 +0000897 GenerateLoadConstant(masm(), object, holder, r0, r3, r1, value, &miss);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000898 __ bind(&miss);
ager@chromium.org3bf7b912008-11-17 09:09:45 +0000899 GenerateLoadMiss(masm(), Code::LOAD_IC);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000900
901 // Return the generated code.
902 return GetCode(CONSTANT_FUNCTION);
903}
904
905
906Object* LoadStubCompiler::CompileLoadInterceptor(JSObject* object,
907 JSObject* holder,
908 String* name) {
909 // ----------- S t a t e -------------
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000910 // -- r2 : name
911 // -- lr : return address
912 // -- [sp] : receiver
913 // -----------------------------------
914
915 HandleScope scope;
916 Label miss;
917
mads.s.ager31e71382008-08-13 09:32:07 +0000918 __ ldr(r0, MemOperand(sp, 0));
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000919
ager@chromium.org3bf7b912008-11-17 09:09:45 +0000920 GenerateLoadInterceptor(masm(), object, holder, r0, r2, r3, r1, &miss);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000921 __ bind(&miss);
ager@chromium.org3bf7b912008-11-17 09:09:45 +0000922 GenerateLoadMiss(masm(), Code::LOAD_IC);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000923
924 // Return the generated code.
925 return GetCode(INTERCEPTOR);
926}
927
928
929// TODO(1224671): IC stubs for keyed loads have not been implemented
930// for ARM.
931Object* KeyedLoadStubCompiler::CompileLoadField(String* name,
932 JSObject* receiver,
933 JSObject* holder,
934 int index) {
ager@chromium.org3bf7b912008-11-17 09:09:45 +0000935 // ----------- S t a t e -------------
936 // -- lr : return address
937 // -- sp[0] : key
938 // -- sp[4] : receiver
939 // -----------------------------------
940 HandleScope scope;
941 Label miss;
942
943 __ ldr(r2, MemOperand(sp, 0));
944 __ ldr(r0, MemOperand(sp, kPointerSize));
945
946 __ cmp(r2, Operand(Handle<String>(name)));
947 __ b(ne, &miss);
948
949 GenerateLoadField(masm(), receiver, holder, r0, r3, r1, index, &miss);
950 __ bind(&miss);
951 GenerateLoadMiss(masm(), Code::KEYED_LOAD_IC);
952
953 return GetCode(FIELD);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000954}
955
956
957Object* KeyedLoadStubCompiler::CompileLoadCallback(String* name,
958 JSObject* receiver,
959 JSObject* holder,
960 AccessorInfo* callback) {
ager@chromium.org3bf7b912008-11-17 09:09:45 +0000961 // ----------- S t a t e -------------
962 // -- lr : return address
963 // -- sp[0] : key
964 // -- sp[4] : receiver
965 // -----------------------------------
966 HandleScope scope;
967 Label miss;
968
969 __ ldr(r2, MemOperand(sp, 0));
970 __ ldr(r0, MemOperand(sp, kPointerSize));
971
972 __ cmp(r2, Operand(Handle<String>(name)));
973 __ b(ne, &miss);
974
975 GenerateLoadCallback(masm(), receiver, holder, r0, r2, r3,
976 r1, callback, &miss);
977 __ bind(&miss);
978 GenerateLoadMiss(masm(), Code::KEYED_LOAD_IC);
979
980 return GetCode(CALLBACKS);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000981}
982
983
984Object* KeyedLoadStubCompiler::CompileLoadConstant(String* name,
985 JSObject* receiver,
986 JSObject* holder,
987 Object* value) {
ager@chromium.org3bf7b912008-11-17 09:09:45 +0000988 // ----------- S t a t e -------------
989 // -- lr : return address
990 // -- sp[0] : key
991 // -- sp[4] : receiver
992 // -----------------------------------
993 HandleScope scope;
994 Label miss;
995
996 // Check the key is the cached one
997 __ ldr(r2, MemOperand(sp, 0));
998 __ ldr(r0, MemOperand(sp, kPointerSize));
999
1000 __ cmp(r2, Operand(Handle<String>(name)));
1001 __ b(ne, &miss);
1002
1003 GenerateLoadConstant(masm(), receiver, holder, r0, r3, r1, value, &miss);
1004 __ bind(&miss);
1005 GenerateLoadMiss(masm(), Code::KEYED_LOAD_IC);
1006
1007 // Return the generated code.
1008 return GetCode(CONSTANT_FUNCTION);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001009}
1010
1011
1012Object* KeyedLoadStubCompiler::CompileLoadInterceptor(JSObject* receiver,
1013 JSObject* holder,
1014 String* name) {
ager@chromium.org3bf7b912008-11-17 09:09:45 +00001015 // ----------- S t a t e -------------
1016 // -- lr : return address
1017 // -- sp[0] : key
1018 // -- sp[4] : receiver
1019 // -----------------------------------
1020 HandleScope scope;
1021 Label miss;
1022
1023 // Check the key is the cached one
1024 __ ldr(r2, MemOperand(sp, 0));
1025 __ ldr(r0, MemOperand(sp, kPointerSize));
1026
1027 __ cmp(r2, Operand(Handle<String>(name)));
1028 __ b(ne, &miss);
1029
1030 GenerateLoadInterceptor(masm(), receiver, holder, r0, r2, r3, r1, &miss);
1031 __ bind(&miss);
1032 GenerateLoadMiss(masm(), Code::KEYED_LOAD_IC);
1033
1034 return GetCode(INTERCEPTOR);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001035}
1036
1037
1038Object* KeyedLoadStubCompiler::CompileLoadArrayLength(String* name) {
ager@chromium.org3bf7b912008-11-17 09:09:45 +00001039 // ----------- S t a t e -------------
1040 // -- lr : return address
1041 // -- sp[0] : key
1042 // -- sp[4] : receiver
1043 // -----------------------------------
1044 HandleScope scope;
1045 Label miss;
1046
1047 // Check the key is the cached one
1048 __ ldr(r2, MemOperand(sp, 0));
1049 __ ldr(r0, MemOperand(sp, kPointerSize));
1050
1051 __ cmp(r2, Operand(Handle<String>(name)));
1052 __ b(ne, &miss);
1053
1054 GenerateLoadArrayLength(masm(), r0, r3, &miss);
1055 __ bind(&miss);
1056 GenerateLoadMiss(masm(), Code::KEYED_LOAD_IC);
1057
1058 return GetCode(CALLBACKS);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001059}
1060
1061
kasperl@chromium.org9fe21c62008-10-28 08:53:51 +00001062Object* KeyedLoadStubCompiler::CompileLoadStringLength(String* name) {
ager@chromium.org3bf7b912008-11-17 09:09:45 +00001063 // ----------- S t a t e -------------
1064 // -- lr : return address
1065 // -- sp[0] : key
1066 // -- sp[4] : receiver
1067 // -----------------------------------
1068 HandleScope scope;
ager@chromium.orga74f0da2008-12-03 16:05:52 +00001069
1070 Label miss;
1071 __ IncrementCounter(&Counters::keyed_load_string_length, 1, r1, r3);
1072
1073 __ ldr(r2, MemOperand(sp));
1074 __ ldr(r0, MemOperand(sp, kPointerSize)); // receiver
1075
1076 __ cmp(r2, Operand(Handle<String>(name)));
1077 __ b(ne, &miss);
1078
1079 GenerateLoadStringLength2(masm(), r0, r1, r3, &miss);
1080 __ bind(&miss);
1081 __ DecrementCounter(&Counters::keyed_load_string_length, 1, r1, r3);
1082
ager@chromium.org3bf7b912008-11-17 09:09:45 +00001083 GenerateLoadMiss(masm(), Code::KEYED_LOAD_IC);
1084
1085 return GetCode(CALLBACKS);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001086}
1087
1088
ager@chromium.org3bf7b912008-11-17 09:09:45 +00001089// TODO(1224671): implement the fast case.
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001090Object* KeyedLoadStubCompiler::CompileLoadFunctionPrototype(String* name) {
ager@chromium.org3bf7b912008-11-17 09:09:45 +00001091 // ----------- S t a t e -------------
1092 // -- lr : return address
1093 // -- sp[0] : key
1094 // -- sp[4] : receiver
1095 // -----------------------------------
1096 HandleScope scope;
1097 GenerateLoadMiss(masm(), Code::KEYED_LOAD_IC);
1098
1099 return GetCode(CALLBACKS);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001100}
1101
1102
1103Object* KeyedStoreStubCompiler::CompileStoreField(JSObject* object,
1104 int index,
1105 Map* transition,
1106 String* name) {
ager@chromium.org3bf7b912008-11-17 09:09:45 +00001107 // ----------- S t a t e -------------
1108 // -- r0 : value
1109 // -- r2 : name
1110 // -- lr : return address
1111 // -- [sp] : receiver
1112 // -----------------------------------
1113 HandleScope scope;
ager@chromium.orga74f0da2008-12-03 16:05:52 +00001114 Label miss;
1115
1116 __ IncrementCounter(&Counters::keyed_store_field, 1, r1, r3);
1117
1118 // Check that the name has not changed.
1119 __ cmp(r2, Operand(Handle<String>(name)));
1120 __ b(ne, &miss);
1121
1122 // Load receiver from the stack.
1123 __ ldr(r3, MemOperand(sp));
1124 // r1 is used as scratch register, r3 and r2 might be clobbered.
1125 GenerateStoreField(masm(),
1126 Builtins::StoreIC_ExtendStorage,
1127 object,
1128 index,
1129 transition,
1130 r3, r2, r1,
1131 &miss);
1132 __ bind(&miss);
1133
1134 __ DecrementCounter(&Counters::keyed_store_field, 1, r1, r3);
1135 __ mov(r2, Operand(Handle<String>(name))); // restore name register.
ager@chromium.org3bf7b912008-11-17 09:09:45 +00001136 Handle<Code> ic(Builtins::builtin(Builtins::KeyedStoreIC_Miss));
1137 __ Jump(ic, RelocInfo::CODE_TARGET);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001138
ager@chromium.org3bf7b912008-11-17 09:09:45 +00001139 // Return the generated code.
1140 return GetCode(transition == NULL ? FIELD : MAP_TRANSITION);
1141}
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001142
1143
1144#undef __
1145
1146} } // namespace v8::internal