blob: 732d2922ea9d64ae70a81bd497a71ab1208fd8ec [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
ager@chromium.org32912102009-01-16 10:38:43 +0000315// Generate code to load the length from a string object and return the length.
316// If the receiver object is not a string or a wrapped string object the
317// execution continues at the miss label. The register containing the
318// receiver is potentially clobbered.
ager@chromium.orga74f0da2008-12-03 16:05:52 +0000319void StubCompiler::GenerateLoadStringLength2(MacroAssembler* masm,
320 Register receiver,
321 Register scratch1,
322 Register scratch2,
323 Label* miss) {
ager@chromium.org32912102009-01-16 10:38:43 +0000324 Label check_string, check_wrapper;
ager@chromium.orga74f0da2008-12-03 16:05:52 +0000325
ager@chromium.org32912102009-01-16 10:38:43 +0000326 __ bind(&check_string);
ager@chromium.orga74f0da2008-12-03 16:05:52 +0000327 // Check if the object is a string leaving the instance type in the
328 // scratch1 register.
329 GenerateStringCheck(masm, receiver, scratch1, scratch2,
330 miss, &check_wrapper);
331
332 // Load length directly from the string.
ager@chromium.orga74f0da2008-12-03 16:05:52 +0000333 __ and_(scratch1, scratch1, Operand(kStringSizeMask));
334 __ add(scratch1, scratch1, Operand(String::kHashShift));
335 __ ldr(r0, FieldMemOperand(receiver, String::kLengthOffset));
336 __ mov(r0, Operand(r0, LSR, scratch1));
337 __ mov(r0, Operand(r0, LSL, kSmiTagSize));
338 __ Ret();
339
340 // Check if the object is a JSValue wrapper.
341 __ bind(&check_wrapper);
342 __ cmp(scratch1, Operand(JS_VALUE_TYPE));
343 __ b(ne, miss);
344
ager@chromium.org32912102009-01-16 10:38:43 +0000345 // Unwrap the value in place and check if the wrapped value is a string.
346 __ ldr(receiver, FieldMemOperand(receiver, JSValue::kValueOffset));
347 __ b(&check_string);
ager@chromium.orga74f0da2008-12-03 16:05:52 +0000348}
349
350
351// Generate StoreField code, value is passed in r0 register.
352// After executing generated code, the receiver_reg and name_reg
353// may be clobbered.
354void StubCompiler::GenerateStoreField(MacroAssembler* masm,
355 Builtins::Name storage_extend,
356 JSObject* object,
357 int index,
358 Map* transition,
359 Register receiver_reg,
360 Register name_reg,
361 Register scratch,
362 Label* miss_label) {
363 // r0 : value
364 Label exit;
365
366 // Check that the receiver isn't a smi.
367 __ tst(receiver_reg, Operand(kSmiTagMask));
368 __ b(eq, miss_label);
369
370 // Check that the map of the receiver hasn't changed.
371 __ ldr(scratch, FieldMemOperand(receiver_reg, HeapObject::kMapOffset));
372 __ cmp(scratch, Operand(Handle<Map>(object->map())));
373 __ b(ne, miss_label);
374
375 // Perform global security token check if needed.
376 if (object->IsJSGlobalProxy()) {
377 __ CheckAccessGlobalProxy(receiver_reg, scratch, miss_label);
378 }
379
380 // Stub never generated for non-global objects that require access
381 // checks.
382 ASSERT(object->IsJSGlobalProxy() || !object->IsAccessCheckNeeded());
383
384 // Perform map transition for the receiver if necessary.
385 if ((transition != NULL) && (object->map()->unused_property_fields() == 0)) {
386 // The properties must be extended before we can store the value.
ager@chromium.org32912102009-01-16 10:38:43 +0000387 // We jump to a runtime call that extends the properties array.
ager@chromium.orga74f0da2008-12-03 16:05:52 +0000388 __ mov(r2, Operand(Handle<Map>(transition)));
389 // Please note, if we implement keyed store for arm we need
390 // to call the Builtins::KeyedStoreIC_ExtendStorage.
391 Handle<Code> ic(Builtins::builtin(Builtins::StoreIC_ExtendStorage));
392 __ Jump(ic, RelocInfo::CODE_TARGET);
393 return;
394 }
395
396 if (transition != NULL) {
397 // Update the map of the object; no write barrier updating is
398 // needed because the map is never in new space.
399 __ mov(ip, Operand(Handle<Map>(transition)));
400 __ str(ip, FieldMemOperand(receiver_reg, HeapObject::kMapOffset));
401 }
402
403 // Adjust for the number of properties stored in the object. Even in the
404 // face of a transition we can use the old map here because the size of the
405 // object and the number of in-object properties is not going to change.
406 index -= object->map()->inobject_properties();
407
408 if (index < 0) {
409 // Set the property straight into the object.
410 int offset = object->map()->instance_size() + (index * kPointerSize);
411 __ str(r0, FieldMemOperand(receiver_reg, offset));
412
413 // Skip updating write barrier if storing a smi.
414 __ tst(r0, Operand(kSmiTagMask));
415 __ b(eq, &exit);
416
417 // Update the write barrier for the array address.
418 // Pass the value being stored in the now unused name_reg.
419 __ mov(name_reg, Operand(offset));
420 __ RecordWrite(receiver_reg, name_reg, scratch);
421 } else {
422 // Write to the properties array.
423 int offset = index * kPointerSize + Array::kHeaderSize;
424 // Get the properties array
425 __ ldr(scratch, FieldMemOperand(receiver_reg, JSObject::kPropertiesOffset));
426 __ str(r0, FieldMemOperand(scratch, offset));
427
428 // Skip updating write barrier if storing a smi.
429 __ tst(r0, Operand(kSmiTagMask));
430 __ b(eq, &exit);
431
432 // Update the write barrier for the array address.
433 // Ok to clobber receiver_reg and name_reg, since we return.
434 __ mov(name_reg, Operand(offset));
435 __ RecordWrite(scratch, name_reg, receiver_reg);
436 }
437
438 // Return the value (register r0).
439 __ bind(&exit);
440 __ Ret();
441}
442
443
ager@chromium.org3bf7b912008-11-17 09:09:45 +0000444void StubCompiler::GenerateLoadMiss(MacroAssembler* masm, Code::Kind kind) {
445 ASSERT(kind == Code::LOAD_IC || kind == Code::KEYED_LOAD_IC);
446 Code* code = NULL;
447 if (kind == Code::LOAD_IC) {
448 code = Builtins::builtin(Builtins::LoadIC_Miss);
449 } else {
450 code = Builtins::builtin(Builtins::KeyedLoadIC_Miss);
451 }
452
453 Handle<Code> ic(code);
454 __ Jump(ic, RelocInfo::CODE_TARGET);
455}
456
457
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000458#undef __
459
460#define __ masm()->
461
462
463Object* StubCompiler::CompileLazyCompile(Code::Flags flags) {
kasperl@chromium.orgb9123622008-09-17 14:05:56 +0000464 // ----------- S t a t e -------------
465 // -- r1: function
466 // -- lr: return address
467 // -----------------------------------
468
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000469 HandleScope scope;
470
kasperl@chromium.orgb9123622008-09-17 14:05:56 +0000471 // Enter an internal frame.
472 __ EnterInternalFrame();
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000473
kasperl@chromium.orgb9123622008-09-17 14:05:56 +0000474 // Preserve the function.
475 __ push(r1);
476
477 // Push the function on the stack as the argument to the runtime function.
478 __ push(r1);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000479 __ CallRuntime(Runtime::kLazyCompile, 1);
480
kasperl@chromium.orgb9123622008-09-17 14:05:56 +0000481 // Calculate the entry point.
482 __ add(r2, r0, Operand(Code::kHeaderSize - kHeapObjectTag));
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000483
kasperl@chromium.orgb9123622008-09-17 14:05:56 +0000484 // Restore saved function.
485 __ pop(r1);
486
487 // Tear down temporary frame.
ager@chromium.org236ad962008-09-25 09:45:57 +0000488 __ LeaveInternalFrame();
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000489
490 // Do a tail-call of the compiled function.
kasperl@chromium.orgb9123622008-09-17 14:05:56 +0000491 __ Jump(r2);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000492
493 return GetCodeWithFlags(flags);
494}
495
496
497Object* CallStubCompiler::CompileCallField(Object* object,
498 JSObject* holder,
499 int index) {
500 // ----------- S t a t e -------------
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000501 // -- lr: return address
502 // -----------------------------------
503
504 HandleScope scope;
505 Label miss;
506
mads.s.ager31e71382008-08-13 09:32:07 +0000507 const int argc = arguments().immediate();
508
kasperl@chromium.org9fe21c62008-10-28 08:53:51 +0000509 // Get the receiver of the function from the stack into r0.
510 __ ldr(r0, MemOperand(sp, argc * kPointerSize));
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000511 // Check that the receiver isn't a smi.
kasperl@chromium.org9fe21c62008-10-28 08:53:51 +0000512 __ tst(r0, Operand(kSmiTagMask));
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000513 __ b(eq, &miss);
514
515 // Do the right check and compute the holder register.
516 Register reg =
kasperl@chromium.org9fe21c62008-10-28 08:53:51 +0000517 __ CheckMaps(JSObject::cast(object), r0, holder, r3, r2, &miss);
ager@chromium.org7c537e22008-10-16 08:43:32 +0000518 GenerateFastPropertyLoad(masm(), r1, reg, holder, index);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000519
520 // Check that the function really is a function.
kasperl@chromium.orgb9123622008-09-17 14:05:56 +0000521 __ tst(r1, Operand(kSmiTagMask));
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000522 __ b(eq, &miss);
523 // Get the map.
kasperl@chromium.orgb9123622008-09-17 14:05:56 +0000524 __ ldr(r2, FieldMemOperand(r1, HeapObject::kMapOffset));
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000525 __ ldrb(r2, FieldMemOperand(r2, Map::kInstanceTypeOffset));
526 __ cmp(r2, Operand(JS_FUNCTION_TYPE));
527 __ b(ne, &miss);
528
kasperl@chromium.org9fe21c62008-10-28 08:53:51 +0000529 // Patch the receiver on the stack with the global proxy if
530 // necessary.
531 if (object->IsGlobalObject()) {
532 __ ldr(r3, FieldMemOperand(r0, GlobalObject::kGlobalReceiverOffset));
533 __ str(r3, MemOperand(sp, argc * kPointerSize));
534 }
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000535
kasperl@chromium.orgb9123622008-09-17 14:05:56 +0000536 // Invoke the function.
537 __ InvokeFunction(r1, arguments(), JUMP_FUNCTION);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000538
539 // Handle call cache miss.
540 __ bind(&miss);
541 Handle<Code> ic = ComputeCallMiss(arguments().immediate());
ager@chromium.org236ad962008-09-25 09:45:57 +0000542 __ Jump(ic, RelocInfo::CODE_TARGET);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000543
544 // Return the generated code.
545 return GetCode(FIELD);
546}
547
548
549Object* CallStubCompiler::CompileCallConstant(Object* object,
550 JSObject* holder,
551 JSFunction* function,
552 CheckType check) {
553 // ----------- S t a t e -------------
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000554 // -- lr: return address
555 // -----------------------------------
556
557 HandleScope scope;
558 Label miss;
559
mads.s.ager31e71382008-08-13 09:32:07 +0000560 // Get the receiver from the stack
561 const int argc = arguments().immediate();
562 __ ldr(r1, MemOperand(sp, argc * kPointerSize));
563
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000564 // Check that the receiver isn't a smi.
565 if (check != NUMBER_CHECK) {
566 __ tst(r1, Operand(kSmiTagMask));
567 __ b(eq, &miss);
568 }
569
kasperl@chromium.org9fe21c62008-10-28 08:53:51 +0000570 // Make sure that it's okay not to patch the on stack receiver
571 // unless we're doing a receiver map check.
572 ASSERT(!object->IsGlobalObject() || check == RECEIVER_MAP_CHECK);
573
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000574 switch (check) {
575 case RECEIVER_MAP_CHECK:
576 // Check that the maps haven't changed.
577 __ CheckMaps(JSObject::cast(object), r1, holder, r3, r2, &miss);
kasperl@chromium.org9fe21c62008-10-28 08:53:51 +0000578
579 // Patch the receiver on the stack with the global proxy if
580 // necessary.
581 if (object->IsGlobalObject()) {
582 __ ldr(r3, FieldMemOperand(r1, GlobalObject::kGlobalReceiverOffset));
583 __ str(r3, MemOperand(sp, argc * kPointerSize));
584 }
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000585 break;
586
587 case STRING_CHECK:
588 // Check that the object is a two-byte string or a symbol.
589 __ ldr(r2, FieldMemOperand(r1, HeapObject::kMapOffset));
590 __ ldrb(r2, FieldMemOperand(r2, Map::kInstanceTypeOffset));
591 __ cmp(r2, Operand(FIRST_NONSTRING_TYPE));
592 __ b(hs, &miss);
593 // Check that the maps starting from the prototype haven't changed.
594 GenerateLoadGlobalFunctionPrototype(masm(),
595 Context::STRING_FUNCTION_INDEX,
596 r2);
597 __ CheckMaps(JSObject::cast(object->GetPrototype()),
598 r2, holder, r3, r1, &miss);
599 break;
600
601 case NUMBER_CHECK: {
602 Label fast;
603 // Check that the object is a smi or a heap number.
604 __ tst(r1, Operand(kSmiTagMask));
605 __ b(eq, &fast);
606 __ ldr(r2, FieldMemOperand(r1, HeapObject::kMapOffset));
607 __ ldrb(r2, FieldMemOperand(r2, Map::kInstanceTypeOffset));
608 __ cmp(r2, Operand(HEAP_NUMBER_TYPE));
609 __ b(ne, &miss);
610 __ bind(&fast);
611 // Check that the maps starting from the prototype haven't changed.
612 GenerateLoadGlobalFunctionPrototype(masm(),
613 Context::NUMBER_FUNCTION_INDEX,
614 r2);
615 __ CheckMaps(JSObject::cast(object->GetPrototype()),
616 r2, holder, r3, r1, &miss);
617 break;
618 }
619
620 case BOOLEAN_CHECK: {
621 Label fast;
622 // Check that the object is a boolean.
623 __ cmp(r1, Operand(Factory::true_value()));
624 __ b(eq, &fast);
625 __ cmp(r1, Operand(Factory::false_value()));
626 __ b(ne, &miss);
627 __ bind(&fast);
628 // Check that the maps starting from the prototype haven't changed.
629 GenerateLoadGlobalFunctionPrototype(masm(),
630 Context::BOOLEAN_FUNCTION_INDEX,
631 r2);
632 __ CheckMaps(JSObject::cast(object->GetPrototype()),
633 r2, holder, r3, r1, &miss);
634 break;
635 }
636
637 case JSARRAY_HAS_FAST_ELEMENTS_CHECK:
638 __ CheckMaps(JSObject::cast(object), r1, holder, r3, r2, &miss);
639 // Make sure object->elements()->map() != Heap::hash_table_map()
640 // Get the elements array of the object.
641 __ ldr(r3, FieldMemOperand(r1, JSObject::kElementsOffset));
642 // Check that the object is in fast mode (not dictionary).
643 __ ldr(r2, FieldMemOperand(r3, HeapObject::kMapOffset));
644 __ cmp(r2, Operand(Factory::hash_table_map()));
645 __ b(eq, &miss);
646 break;
647
648 default:
649 UNREACHABLE();
650 }
651
652 // Get the function and setup the context.
kasperl@chromium.orgb9123622008-09-17 14:05:56 +0000653 __ mov(r1, Operand(Handle<JSFunction>(function)));
654 __ ldr(cp, FieldMemOperand(r1, JSFunction::kContextOffset));
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000655
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000656 // Jump to the cached code (tail call).
657 Handle<Code> code(function->code());
mads.s.ager@gmail.com769cc962008-08-06 10:02:49 +0000658 ParameterCount expected(function->shared()->formal_parameter_count());
ager@chromium.org236ad962008-09-25 09:45:57 +0000659 __ InvokeCode(code, expected, arguments(),
660 RelocInfo::CODE_TARGET, JUMP_FUNCTION);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000661
662 // Handle call cache miss.
663 __ bind(&miss);
664 Handle<Code> ic = ComputeCallMiss(arguments().immediate());
ager@chromium.org236ad962008-09-25 09:45:57 +0000665 __ Jump(ic, RelocInfo::CODE_TARGET);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000666
667 // Return the generated code.
668 return GetCode(CONSTANT_FUNCTION);
669}
670
671
672Object* CallStubCompiler::CompileCallInterceptor(Object* object,
673 JSObject* holder,
674 String* name) {
675 // ----------- S t a t e -------------
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000676 // -- lr: return address
677 // -----------------------------------
678
679 HandleScope scope;
680 Label miss;
681
682 // TODO(1224669): Implement.
683
684 // Handle call cache miss.
685 __ bind(&miss);
686 Handle<Code> ic = ComputeCallMiss(arguments().immediate());
ager@chromium.org236ad962008-09-25 09:45:57 +0000687 __ Jump(ic, RelocInfo::CODE_TARGET);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000688
689 // Return the generated code.
690 return GetCode(INTERCEPTOR);
691}
692
693
694Object* StoreStubCompiler::CompileStoreField(JSObject* object,
695 int index,
696 Map* transition,
697 String* name) {
698 // ----------- S t a t e -------------
699 // -- r0 : value
700 // -- r2 : name
701 // -- lr : return address
702 // -- [sp] : receiver
703 // -----------------------------------
704
705 HandleScope scope;
ager@chromium.orga74f0da2008-12-03 16:05:52 +0000706 Label miss;
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000707
708 // Get the receiver from the stack.
709 __ ldr(r3, MemOperand(sp, 0 * kPointerSize));
710
ager@chromium.orga74f0da2008-12-03 16:05:52 +0000711 // name register might be clobbered.
712 GenerateStoreField(masm(),
713 Builtins::StoreIC_ExtendStorage,
714 object,
715 index,
716 transition,
717 r3, r2, r1,
718 &miss);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000719 __ bind(&miss);
720 __ mov(r2, Operand(Handle<String>(name))); // restore name
721 Handle<Code> ic(Builtins::builtin(Builtins::StoreIC_Miss));
ager@chromium.org236ad962008-09-25 09:45:57 +0000722 __ Jump(ic, RelocInfo::CODE_TARGET);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000723
724 // Return the generated code.
725 return GetCode(transition == NULL ? FIELD : MAP_TRANSITION);
726}
727
728
729Object* StoreStubCompiler::CompileStoreCallback(JSObject* object,
730 AccessorInfo* callback,
731 String* name) {
732 // ----------- S t a t e -------------
733 // -- r0 : value
734 // -- r2 : name
735 // -- lr : return address
736 // -- [sp] : receiver
737 // -----------------------------------
738
739 HandleScope scope;
740 Label miss;
741
742 // Get the object from the stack.
743 __ ldr(r3, MemOperand(sp, 0 * kPointerSize));
744
745 // Check that the object isn't a smi.
746 __ tst(r3, Operand(kSmiTagMask));
747 __ b(eq, &miss);
748
749 // Check that the map of the object hasn't changed.
750 __ ldr(r1, FieldMemOperand(r3, HeapObject::kMapOffset));
751 __ cmp(r1, Operand(Handle<Map>(object->map())));
752 __ b(ne, &miss);
753
754 // Perform global security token check if needed.
kasperl@chromium.org5a8ca6c2008-10-23 13:57:19 +0000755 if (object->IsJSGlobalProxy()) {
756 __ CheckAccessGlobalProxy(r3, r1, &miss);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000757 }
758
759 // Stub never generated for non-global objects that require access
760 // checks.
kasperl@chromium.org5a8ca6c2008-10-23 13:57:19 +0000761 ASSERT(object->IsJSGlobalProxy() || !object->IsAccessCheckNeeded());
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000762
763 __ ldr(ip, MemOperand(sp)); // receiver
764 __ push(ip);
765 __ mov(ip, Operand(Handle<AccessorInfo>(callback))); // callback info
766 __ push(ip);
767 __ push(r2); // name
768 __ push(r0); // value
769
mads.s.ager31e71382008-08-13 09:32:07 +0000770 // Do tail-call to the runtime system.
771 ExternalReference store_callback_property =
772 ExternalReference(IC_Utility(IC::kStoreCallbackProperty));
773 __ TailCallRuntime(store_callback_property, 4);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000774
775 // Handle store cache miss.
776 __ bind(&miss);
777 __ mov(r2, Operand(Handle<String>(name))); // restore name
778 Handle<Code> ic(Builtins::builtin(Builtins::StoreIC_Miss));
ager@chromium.org236ad962008-09-25 09:45:57 +0000779 __ Jump(ic, RelocInfo::CODE_TARGET);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000780
781 // Return the generated code.
782 return GetCode(CALLBACKS);
783}
784
785
786Object* StoreStubCompiler::CompileStoreInterceptor(JSObject* receiver,
787 String* name) {
788 // ----------- S t a t e -------------
789 // -- r0 : value
790 // -- r2 : name
791 // -- lr : return address
792 // -- [sp] : receiver
793 // -----------------------------------
794
795 HandleScope scope;
796 Label miss;
797
798 // Get the object from the stack.
799 __ ldr(r3, MemOperand(sp, 0 * kPointerSize));
800
801 // Check that the object isn't a smi.
802 __ tst(r3, Operand(kSmiTagMask));
803 __ b(eq, &miss);
804
805 // Check that the map of the object hasn't changed.
806 __ ldr(r1, FieldMemOperand(r3, HeapObject::kMapOffset));
807 __ cmp(r1, Operand(Handle<Map>(receiver->map())));
808 __ b(ne, &miss);
809
810 // Perform global security token check if needed.
kasperl@chromium.org5a8ca6c2008-10-23 13:57:19 +0000811 if (receiver->IsJSGlobalProxy()) {
812 __ CheckAccessGlobalProxy(r3, r1, &miss);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000813 }
814
815 // Stub never generated for non-global objects that require access
816 // checks.
kasperl@chromium.org5a8ca6c2008-10-23 13:57:19 +0000817 ASSERT(receiver->IsJSGlobalProxy() || !receiver->IsAccessCheckNeeded());
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000818
819 __ ldr(ip, MemOperand(sp)); // receiver
820 __ push(ip);
821 __ push(r2); // name
822 __ push(r0); // value
823
mads.s.ager31e71382008-08-13 09:32:07 +0000824 // Do tail-call to the runtime system.
825 ExternalReference store_ic_property =
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000826 ExternalReference(IC_Utility(IC::kStoreInterceptorProperty));
mads.s.ager31e71382008-08-13 09:32:07 +0000827 __ TailCallRuntime(store_ic_property, 3);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000828
829 // Handle store cache miss.
830 __ bind(&miss);
831 __ mov(r2, Operand(Handle<String>(name))); // restore name
832 Handle<Code> ic(Builtins::builtin(Builtins::StoreIC_Miss));
ager@chromium.org236ad962008-09-25 09:45:57 +0000833 __ Jump(ic, RelocInfo::CODE_TARGET);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000834
835 // Return the generated code.
836 return GetCode(INTERCEPTOR);
837}
838
839
840Object* LoadStubCompiler::CompileLoadField(JSObject* object,
841 JSObject* holder,
842 int index) {
843 // ----------- S t a t e -------------
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000844 // -- r2 : name
845 // -- lr : return address
846 // -- [sp] : receiver
847 // -----------------------------------
848
849 HandleScope scope;
850 Label miss;
851
mads.s.ager31e71382008-08-13 09:32:07 +0000852 __ ldr(r0, MemOperand(sp, 0));
853
ager@chromium.org3bf7b912008-11-17 09:09:45 +0000854 GenerateLoadField(masm(), object, holder, r0, r3, r1, index, &miss);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000855 __ bind(&miss);
ager@chromium.org3bf7b912008-11-17 09:09:45 +0000856 GenerateLoadMiss(masm(), Code::LOAD_IC);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000857
858 // Return the generated code.
859 return GetCode(FIELD);
860}
861
862
863Object* LoadStubCompiler::CompileLoadCallback(JSObject* object,
864 JSObject* holder,
865 AccessorInfo* callback) {
866 // ----------- S t a t e -------------
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000867 // -- r2 : name
868 // -- lr : return address
869 // -- [sp] : receiver
870 // -----------------------------------
871
872 HandleScope scope;
873 Label miss;
874
mads.s.ager31e71382008-08-13 09:32:07 +0000875 __ ldr(r0, MemOperand(sp, 0));
ager@chromium.org3bf7b912008-11-17 09:09:45 +0000876 GenerateLoadCallback(masm(), object, holder, r0, r2, r3, r1, callback, &miss);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000877 __ bind(&miss);
ager@chromium.org3bf7b912008-11-17 09:09:45 +0000878 GenerateLoadMiss(masm(), Code::LOAD_IC);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000879
880 // Return the generated code.
881 return GetCode(CALLBACKS);
882}
883
884
885Object* LoadStubCompiler::CompileLoadConstant(JSObject* object,
886 JSObject* holder,
887 Object* value) {
888 // ----------- S t a t e -------------
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000889 // -- r2 : name
890 // -- lr : return address
891 // -- [sp] : receiver
892 // -----------------------------------
893
894 HandleScope scope;
895 Label miss;
896
mads.s.ager31e71382008-08-13 09:32:07 +0000897 __ ldr(r0, MemOperand(sp, 0));
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000898
ager@chromium.org3bf7b912008-11-17 09:09:45 +0000899 GenerateLoadConstant(masm(), object, holder, r0, r3, r1, value, &miss);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000900 __ bind(&miss);
ager@chromium.org3bf7b912008-11-17 09:09:45 +0000901 GenerateLoadMiss(masm(), Code::LOAD_IC);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000902
903 // Return the generated code.
904 return GetCode(CONSTANT_FUNCTION);
905}
906
907
908Object* LoadStubCompiler::CompileLoadInterceptor(JSObject* object,
909 JSObject* holder,
910 String* name) {
911 // ----------- S t a t e -------------
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000912 // -- r2 : name
913 // -- lr : return address
914 // -- [sp] : receiver
915 // -----------------------------------
916
917 HandleScope scope;
918 Label miss;
919
mads.s.ager31e71382008-08-13 09:32:07 +0000920 __ ldr(r0, MemOperand(sp, 0));
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000921
ager@chromium.org3bf7b912008-11-17 09:09:45 +0000922 GenerateLoadInterceptor(masm(), object, holder, r0, r2, r3, r1, &miss);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000923 __ bind(&miss);
ager@chromium.org3bf7b912008-11-17 09:09:45 +0000924 GenerateLoadMiss(masm(), Code::LOAD_IC);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000925
926 // Return the generated code.
927 return GetCode(INTERCEPTOR);
928}
929
930
931// TODO(1224671): IC stubs for keyed loads have not been implemented
932// for ARM.
933Object* KeyedLoadStubCompiler::CompileLoadField(String* name,
934 JSObject* receiver,
935 JSObject* holder,
936 int index) {
ager@chromium.org3bf7b912008-11-17 09:09:45 +0000937 // ----------- S t a t e -------------
938 // -- lr : return address
939 // -- sp[0] : key
940 // -- sp[4] : receiver
941 // -----------------------------------
942 HandleScope scope;
943 Label miss;
944
945 __ ldr(r2, MemOperand(sp, 0));
946 __ ldr(r0, MemOperand(sp, kPointerSize));
947
948 __ cmp(r2, Operand(Handle<String>(name)));
949 __ b(ne, &miss);
950
951 GenerateLoadField(masm(), receiver, holder, r0, r3, r1, index, &miss);
952 __ bind(&miss);
953 GenerateLoadMiss(masm(), Code::KEYED_LOAD_IC);
954
955 return GetCode(FIELD);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000956}
957
958
959Object* KeyedLoadStubCompiler::CompileLoadCallback(String* name,
960 JSObject* receiver,
961 JSObject* holder,
962 AccessorInfo* callback) {
ager@chromium.org3bf7b912008-11-17 09:09:45 +0000963 // ----------- S t a t e -------------
964 // -- lr : return address
965 // -- sp[0] : key
966 // -- sp[4] : receiver
967 // -----------------------------------
968 HandleScope scope;
969 Label miss;
970
971 __ ldr(r2, MemOperand(sp, 0));
972 __ ldr(r0, MemOperand(sp, kPointerSize));
973
974 __ cmp(r2, Operand(Handle<String>(name)));
975 __ b(ne, &miss);
976
977 GenerateLoadCallback(masm(), receiver, holder, r0, r2, r3,
978 r1, callback, &miss);
979 __ bind(&miss);
980 GenerateLoadMiss(masm(), Code::KEYED_LOAD_IC);
981
982 return GetCode(CALLBACKS);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000983}
984
985
986Object* KeyedLoadStubCompiler::CompileLoadConstant(String* name,
987 JSObject* receiver,
988 JSObject* holder,
989 Object* value) {
ager@chromium.org3bf7b912008-11-17 09:09:45 +0000990 // ----------- S t a t e -------------
991 // -- lr : return address
992 // -- sp[0] : key
993 // -- sp[4] : receiver
994 // -----------------------------------
995 HandleScope scope;
996 Label miss;
997
998 // Check the key is the cached one
999 __ ldr(r2, MemOperand(sp, 0));
1000 __ ldr(r0, MemOperand(sp, kPointerSize));
1001
1002 __ cmp(r2, Operand(Handle<String>(name)));
1003 __ b(ne, &miss);
1004
1005 GenerateLoadConstant(masm(), receiver, holder, r0, r3, r1, value, &miss);
1006 __ bind(&miss);
1007 GenerateLoadMiss(masm(), Code::KEYED_LOAD_IC);
1008
1009 // Return the generated code.
1010 return GetCode(CONSTANT_FUNCTION);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001011}
1012
1013
1014Object* KeyedLoadStubCompiler::CompileLoadInterceptor(JSObject* receiver,
1015 JSObject* holder,
1016 String* name) {
ager@chromium.org3bf7b912008-11-17 09:09:45 +00001017 // ----------- S t a t e -------------
1018 // -- lr : return address
1019 // -- sp[0] : key
1020 // -- sp[4] : receiver
1021 // -----------------------------------
1022 HandleScope scope;
1023 Label miss;
1024
1025 // Check the key is the cached one
1026 __ ldr(r2, MemOperand(sp, 0));
1027 __ ldr(r0, MemOperand(sp, kPointerSize));
1028
1029 __ cmp(r2, Operand(Handle<String>(name)));
1030 __ b(ne, &miss);
1031
1032 GenerateLoadInterceptor(masm(), receiver, holder, r0, r2, r3, r1, &miss);
1033 __ bind(&miss);
1034 GenerateLoadMiss(masm(), Code::KEYED_LOAD_IC);
1035
1036 return GetCode(INTERCEPTOR);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001037}
1038
1039
1040Object* KeyedLoadStubCompiler::CompileLoadArrayLength(String* name) {
ager@chromium.org3bf7b912008-11-17 09:09:45 +00001041 // ----------- S t a t e -------------
1042 // -- lr : return address
1043 // -- sp[0] : key
1044 // -- sp[4] : receiver
1045 // -----------------------------------
1046 HandleScope scope;
1047 Label miss;
1048
1049 // Check the key is the cached one
1050 __ ldr(r2, MemOperand(sp, 0));
1051 __ ldr(r0, MemOperand(sp, kPointerSize));
1052
1053 __ cmp(r2, Operand(Handle<String>(name)));
1054 __ b(ne, &miss);
1055
1056 GenerateLoadArrayLength(masm(), r0, r3, &miss);
1057 __ bind(&miss);
1058 GenerateLoadMiss(masm(), Code::KEYED_LOAD_IC);
1059
1060 return GetCode(CALLBACKS);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001061}
1062
1063
kasperl@chromium.org9fe21c62008-10-28 08:53:51 +00001064Object* KeyedLoadStubCompiler::CompileLoadStringLength(String* name) {
ager@chromium.org3bf7b912008-11-17 09:09:45 +00001065 // ----------- S t a t e -------------
1066 // -- lr : return address
1067 // -- sp[0] : key
1068 // -- sp[4] : receiver
1069 // -----------------------------------
1070 HandleScope scope;
ager@chromium.orga74f0da2008-12-03 16:05:52 +00001071
1072 Label miss;
1073 __ IncrementCounter(&Counters::keyed_load_string_length, 1, r1, r3);
1074
1075 __ ldr(r2, MemOperand(sp));
1076 __ ldr(r0, MemOperand(sp, kPointerSize)); // receiver
1077
1078 __ cmp(r2, Operand(Handle<String>(name)));
1079 __ b(ne, &miss);
1080
1081 GenerateLoadStringLength2(masm(), r0, r1, r3, &miss);
1082 __ bind(&miss);
1083 __ DecrementCounter(&Counters::keyed_load_string_length, 1, r1, r3);
1084
ager@chromium.org3bf7b912008-11-17 09:09:45 +00001085 GenerateLoadMiss(masm(), Code::KEYED_LOAD_IC);
1086
1087 return GetCode(CALLBACKS);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001088}
1089
1090
ager@chromium.org3bf7b912008-11-17 09:09:45 +00001091// TODO(1224671): implement the fast case.
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001092Object* KeyedLoadStubCompiler::CompileLoadFunctionPrototype(String* name) {
ager@chromium.org3bf7b912008-11-17 09:09:45 +00001093 // ----------- S t a t e -------------
1094 // -- lr : return address
1095 // -- sp[0] : key
1096 // -- sp[4] : receiver
1097 // -----------------------------------
1098 HandleScope scope;
1099 GenerateLoadMiss(masm(), Code::KEYED_LOAD_IC);
1100
1101 return GetCode(CALLBACKS);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001102}
1103
1104
1105Object* KeyedStoreStubCompiler::CompileStoreField(JSObject* object,
1106 int index,
1107 Map* transition,
1108 String* name) {
ager@chromium.org3bf7b912008-11-17 09:09:45 +00001109 // ----------- S t a t e -------------
1110 // -- r0 : value
1111 // -- r2 : name
1112 // -- lr : return address
1113 // -- [sp] : receiver
1114 // -----------------------------------
1115 HandleScope scope;
ager@chromium.orga74f0da2008-12-03 16:05:52 +00001116 Label miss;
1117
1118 __ IncrementCounter(&Counters::keyed_store_field, 1, r1, r3);
1119
1120 // Check that the name has not changed.
1121 __ cmp(r2, Operand(Handle<String>(name)));
1122 __ b(ne, &miss);
1123
1124 // Load receiver from the stack.
1125 __ ldr(r3, MemOperand(sp));
1126 // r1 is used as scratch register, r3 and r2 might be clobbered.
1127 GenerateStoreField(masm(),
1128 Builtins::StoreIC_ExtendStorage,
1129 object,
1130 index,
1131 transition,
1132 r3, r2, r1,
1133 &miss);
1134 __ bind(&miss);
1135
1136 __ DecrementCounter(&Counters::keyed_store_field, 1, r1, r3);
1137 __ mov(r2, Operand(Handle<String>(name))); // restore name register.
ager@chromium.org3bf7b912008-11-17 09:09:45 +00001138 Handle<Code> ic(Builtins::builtin(Builtins::KeyedStoreIC_Miss));
1139 __ Jump(ic, RelocInfo::CODE_TARGET);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001140
ager@chromium.org3bf7b912008-11-17 09:09:45 +00001141 // Return the generated code.
1142 return GetCode(transition == NULL ? FIELD : MAP_TRANSITION);
1143}
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001144
1145
1146#undef __
1147
1148} } // namespace v8::internal