blob: 45fa1c9fed886356e94383326140868dae218cef [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
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 // -----------------------------------
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000501 Label miss;
502
mads.s.ager31e71382008-08-13 09:32:07 +0000503 const int argc = arguments().immediate();
504
kasperl@chromium.org9fe21c62008-10-28 08:53:51 +0000505 // Get the receiver of the function from the stack into r0.
506 __ ldr(r0, MemOperand(sp, argc * kPointerSize));
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000507 // Check that the receiver isn't a smi.
kasperl@chromium.org9fe21c62008-10-28 08:53:51 +0000508 __ tst(r0, Operand(kSmiTagMask));
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000509 __ b(eq, &miss);
510
511 // Do the right check and compute the holder register.
512 Register reg =
kasperl@chromium.org9fe21c62008-10-28 08:53:51 +0000513 __ CheckMaps(JSObject::cast(object), r0, holder, r3, r2, &miss);
ager@chromium.org7c537e22008-10-16 08:43:32 +0000514 GenerateFastPropertyLoad(masm(), r1, reg, holder, index);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000515
516 // Check that the function really is a function.
kasperl@chromium.orgb9123622008-09-17 14:05:56 +0000517 __ tst(r1, Operand(kSmiTagMask));
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000518 __ b(eq, &miss);
519 // Get the map.
kasperl@chromium.orgb9123622008-09-17 14:05:56 +0000520 __ ldr(r2, FieldMemOperand(r1, HeapObject::kMapOffset));
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000521 __ ldrb(r2, FieldMemOperand(r2, Map::kInstanceTypeOffset));
522 __ cmp(r2, Operand(JS_FUNCTION_TYPE));
523 __ b(ne, &miss);
524
kasperl@chromium.org9fe21c62008-10-28 08:53:51 +0000525 // Patch the receiver on the stack with the global proxy if
526 // necessary.
527 if (object->IsGlobalObject()) {
528 __ ldr(r3, FieldMemOperand(r0, GlobalObject::kGlobalReceiverOffset));
529 __ str(r3, MemOperand(sp, argc * kPointerSize));
530 }
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000531
kasperl@chromium.orgb9123622008-09-17 14:05:56 +0000532 // Invoke the function.
533 __ InvokeFunction(r1, arguments(), JUMP_FUNCTION);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000534
535 // Handle call cache miss.
536 __ bind(&miss);
537 Handle<Code> ic = ComputeCallMiss(arguments().immediate());
ager@chromium.org236ad962008-09-25 09:45:57 +0000538 __ Jump(ic, RelocInfo::CODE_TARGET);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000539
540 // Return the generated code.
541 return GetCode(FIELD);
542}
543
544
545Object* CallStubCompiler::CompileCallConstant(Object* object,
546 JSObject* holder,
547 JSFunction* function,
548 CheckType check) {
549 // ----------- S t a t e -------------
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000550 // -- lr: return address
551 // -----------------------------------
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000552 Label miss;
553
mads.s.ager31e71382008-08-13 09:32:07 +0000554 // Get the receiver from the stack
555 const int argc = arguments().immediate();
556 __ ldr(r1, MemOperand(sp, argc * kPointerSize));
557
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000558 // Check that the receiver isn't a smi.
559 if (check != NUMBER_CHECK) {
560 __ tst(r1, Operand(kSmiTagMask));
561 __ b(eq, &miss);
562 }
563
kasperl@chromium.org9fe21c62008-10-28 08:53:51 +0000564 // Make sure that it's okay not to patch the on stack receiver
565 // unless we're doing a receiver map check.
566 ASSERT(!object->IsGlobalObject() || check == RECEIVER_MAP_CHECK);
567
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000568 switch (check) {
569 case RECEIVER_MAP_CHECK:
570 // Check that the maps haven't changed.
571 __ CheckMaps(JSObject::cast(object), r1, holder, r3, r2, &miss);
kasperl@chromium.org9fe21c62008-10-28 08:53:51 +0000572
573 // Patch the receiver on the stack with the global proxy if
574 // necessary.
575 if (object->IsGlobalObject()) {
576 __ ldr(r3, FieldMemOperand(r1, GlobalObject::kGlobalReceiverOffset));
577 __ str(r3, MemOperand(sp, argc * kPointerSize));
578 }
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000579 break;
580
581 case STRING_CHECK:
582 // Check that the object is a two-byte string or a symbol.
583 __ ldr(r2, FieldMemOperand(r1, HeapObject::kMapOffset));
584 __ ldrb(r2, FieldMemOperand(r2, Map::kInstanceTypeOffset));
585 __ cmp(r2, Operand(FIRST_NONSTRING_TYPE));
586 __ b(hs, &miss);
587 // Check that the maps starting from the prototype haven't changed.
588 GenerateLoadGlobalFunctionPrototype(masm(),
589 Context::STRING_FUNCTION_INDEX,
590 r2);
591 __ CheckMaps(JSObject::cast(object->GetPrototype()),
592 r2, holder, r3, r1, &miss);
593 break;
594
595 case NUMBER_CHECK: {
596 Label fast;
597 // Check that the object is a smi or a heap number.
598 __ tst(r1, Operand(kSmiTagMask));
599 __ b(eq, &fast);
600 __ ldr(r2, FieldMemOperand(r1, HeapObject::kMapOffset));
601 __ ldrb(r2, FieldMemOperand(r2, Map::kInstanceTypeOffset));
602 __ cmp(r2, Operand(HEAP_NUMBER_TYPE));
603 __ b(ne, &miss);
604 __ bind(&fast);
605 // Check that the maps starting from the prototype haven't changed.
606 GenerateLoadGlobalFunctionPrototype(masm(),
607 Context::NUMBER_FUNCTION_INDEX,
608 r2);
609 __ CheckMaps(JSObject::cast(object->GetPrototype()),
610 r2, holder, r3, r1, &miss);
611 break;
612 }
613
614 case BOOLEAN_CHECK: {
615 Label fast;
616 // Check that the object is a boolean.
617 __ cmp(r1, Operand(Factory::true_value()));
618 __ b(eq, &fast);
619 __ cmp(r1, Operand(Factory::false_value()));
620 __ b(ne, &miss);
621 __ bind(&fast);
622 // Check that the maps starting from the prototype haven't changed.
623 GenerateLoadGlobalFunctionPrototype(masm(),
624 Context::BOOLEAN_FUNCTION_INDEX,
625 r2);
626 __ CheckMaps(JSObject::cast(object->GetPrototype()),
627 r2, holder, r3, r1, &miss);
628 break;
629 }
630
631 case JSARRAY_HAS_FAST_ELEMENTS_CHECK:
632 __ CheckMaps(JSObject::cast(object), r1, holder, r3, r2, &miss);
633 // Make sure object->elements()->map() != Heap::hash_table_map()
634 // Get the elements array of the object.
635 __ ldr(r3, FieldMemOperand(r1, JSObject::kElementsOffset));
636 // Check that the object is in fast mode (not dictionary).
637 __ ldr(r2, FieldMemOperand(r3, HeapObject::kMapOffset));
638 __ cmp(r2, Operand(Factory::hash_table_map()));
639 __ b(eq, &miss);
640 break;
641
642 default:
643 UNREACHABLE();
644 }
645
646 // Get the function and setup the context.
kasperl@chromium.orgb9123622008-09-17 14:05:56 +0000647 __ mov(r1, Operand(Handle<JSFunction>(function)));
648 __ ldr(cp, FieldMemOperand(r1, JSFunction::kContextOffset));
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000649
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000650 // Jump to the cached code (tail call).
651 Handle<Code> code(function->code());
mads.s.ager@gmail.com769cc962008-08-06 10:02:49 +0000652 ParameterCount expected(function->shared()->formal_parameter_count());
ager@chromium.org236ad962008-09-25 09:45:57 +0000653 __ InvokeCode(code, expected, arguments(),
654 RelocInfo::CODE_TARGET, JUMP_FUNCTION);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000655
656 // Handle call cache miss.
657 __ bind(&miss);
658 Handle<Code> ic = ComputeCallMiss(arguments().immediate());
ager@chromium.org236ad962008-09-25 09:45:57 +0000659 __ Jump(ic, RelocInfo::CODE_TARGET);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000660
661 // Return the generated code.
662 return GetCode(CONSTANT_FUNCTION);
663}
664
665
666Object* CallStubCompiler::CompileCallInterceptor(Object* object,
667 JSObject* holder,
668 String* name) {
669 // ----------- S t a t e -------------
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000670 // -- lr: return address
671 // -----------------------------------
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000672 Label miss;
673
674 // TODO(1224669): Implement.
675
676 // Handle call cache miss.
677 __ bind(&miss);
678 Handle<Code> ic = ComputeCallMiss(arguments().immediate());
ager@chromium.org236ad962008-09-25 09:45:57 +0000679 __ Jump(ic, RelocInfo::CODE_TARGET);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000680
681 // Return the generated code.
682 return GetCode(INTERCEPTOR);
683}
684
685
686Object* StoreStubCompiler::CompileStoreField(JSObject* object,
687 int index,
688 Map* transition,
689 String* name) {
690 // ----------- S t a t e -------------
691 // -- r0 : value
692 // -- r2 : name
693 // -- lr : return address
694 // -- [sp] : receiver
695 // -----------------------------------
ager@chromium.orga74f0da2008-12-03 16:05:52 +0000696 Label miss;
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000697
698 // Get the receiver from the stack.
699 __ ldr(r3, MemOperand(sp, 0 * kPointerSize));
700
ager@chromium.orga74f0da2008-12-03 16:05:52 +0000701 // name register might be clobbered.
702 GenerateStoreField(masm(),
703 Builtins::StoreIC_ExtendStorage,
704 object,
705 index,
706 transition,
707 r3, r2, r1,
708 &miss);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000709 __ bind(&miss);
710 __ mov(r2, Operand(Handle<String>(name))); // restore name
711 Handle<Code> ic(Builtins::builtin(Builtins::StoreIC_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(transition == NULL ? FIELD : MAP_TRANSITION);
716}
717
718
719Object* StoreStubCompiler::CompileStoreCallback(JSObject* object,
720 AccessorInfo* callback,
721 String* name) {
722 // ----------- S t a t e -------------
723 // -- r0 : value
724 // -- r2 : name
725 // -- lr : return address
726 // -- [sp] : receiver
727 // -----------------------------------
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000728 Label miss;
729
730 // Get the object from the stack.
731 __ ldr(r3, MemOperand(sp, 0 * kPointerSize));
732
733 // Check that the object isn't a smi.
734 __ tst(r3, Operand(kSmiTagMask));
735 __ b(eq, &miss);
736
737 // Check that the map of the object hasn't changed.
738 __ ldr(r1, FieldMemOperand(r3, HeapObject::kMapOffset));
739 __ cmp(r1, Operand(Handle<Map>(object->map())));
740 __ b(ne, &miss);
741
742 // Perform global security token check if needed.
kasperl@chromium.org5a8ca6c2008-10-23 13:57:19 +0000743 if (object->IsJSGlobalProxy()) {
744 __ CheckAccessGlobalProxy(r3, r1, &miss);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000745 }
746
747 // Stub never generated for non-global objects that require access
748 // checks.
kasperl@chromium.org5a8ca6c2008-10-23 13:57:19 +0000749 ASSERT(object->IsJSGlobalProxy() || !object->IsAccessCheckNeeded());
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000750
751 __ ldr(ip, MemOperand(sp)); // receiver
752 __ push(ip);
753 __ mov(ip, Operand(Handle<AccessorInfo>(callback))); // callback info
754 __ push(ip);
755 __ push(r2); // name
756 __ push(r0); // value
757
mads.s.ager31e71382008-08-13 09:32:07 +0000758 // Do tail-call to the runtime system.
759 ExternalReference store_callback_property =
760 ExternalReference(IC_Utility(IC::kStoreCallbackProperty));
761 __ TailCallRuntime(store_callback_property, 4);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000762
763 // Handle store cache miss.
764 __ bind(&miss);
765 __ mov(r2, Operand(Handle<String>(name))); // restore name
766 Handle<Code> ic(Builtins::builtin(Builtins::StoreIC_Miss));
ager@chromium.org236ad962008-09-25 09:45:57 +0000767 __ Jump(ic, RelocInfo::CODE_TARGET);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000768
769 // Return the generated code.
770 return GetCode(CALLBACKS);
771}
772
773
774Object* StoreStubCompiler::CompileStoreInterceptor(JSObject* receiver,
775 String* name) {
776 // ----------- S t a t e -------------
777 // -- r0 : value
778 // -- r2 : name
779 // -- lr : return address
780 // -- [sp] : receiver
781 // -----------------------------------
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000782 Label miss;
783
784 // Get the object from the stack.
785 __ ldr(r3, MemOperand(sp, 0 * kPointerSize));
786
787 // Check that the object isn't a smi.
788 __ tst(r3, Operand(kSmiTagMask));
789 __ b(eq, &miss);
790
791 // Check that the map of the object hasn't changed.
792 __ ldr(r1, FieldMemOperand(r3, HeapObject::kMapOffset));
793 __ cmp(r1, Operand(Handle<Map>(receiver->map())));
794 __ b(ne, &miss);
795
796 // Perform global security token check if needed.
kasperl@chromium.org5a8ca6c2008-10-23 13:57:19 +0000797 if (receiver->IsJSGlobalProxy()) {
798 __ CheckAccessGlobalProxy(r3, r1, &miss);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000799 }
800
801 // Stub never generated for non-global objects that require access
802 // checks.
kasperl@chromium.org5a8ca6c2008-10-23 13:57:19 +0000803 ASSERT(receiver->IsJSGlobalProxy() || !receiver->IsAccessCheckNeeded());
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000804
805 __ ldr(ip, MemOperand(sp)); // receiver
806 __ push(ip);
807 __ push(r2); // name
808 __ push(r0); // value
809
mads.s.ager31e71382008-08-13 09:32:07 +0000810 // Do tail-call to the runtime system.
811 ExternalReference store_ic_property =
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000812 ExternalReference(IC_Utility(IC::kStoreInterceptorProperty));
mads.s.ager31e71382008-08-13 09:32:07 +0000813 __ TailCallRuntime(store_ic_property, 3);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000814
815 // Handle store cache miss.
816 __ bind(&miss);
817 __ mov(r2, Operand(Handle<String>(name))); // restore name
818 Handle<Code> ic(Builtins::builtin(Builtins::StoreIC_Miss));
ager@chromium.org236ad962008-09-25 09:45:57 +0000819 __ Jump(ic, RelocInfo::CODE_TARGET);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000820
821 // Return the generated code.
822 return GetCode(INTERCEPTOR);
823}
824
825
826Object* LoadStubCompiler::CompileLoadField(JSObject* object,
827 JSObject* holder,
828 int index) {
829 // ----------- S t a t e -------------
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000830 // -- r2 : name
831 // -- lr : return address
832 // -- [sp] : receiver
833 // -----------------------------------
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000834 Label miss;
835
mads.s.ager31e71382008-08-13 09:32:07 +0000836 __ ldr(r0, MemOperand(sp, 0));
837
ager@chromium.org3bf7b912008-11-17 09:09:45 +0000838 GenerateLoadField(masm(), object, holder, r0, r3, r1, index, &miss);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000839 __ bind(&miss);
ager@chromium.org3bf7b912008-11-17 09:09:45 +0000840 GenerateLoadMiss(masm(), Code::LOAD_IC);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000841
842 // Return the generated code.
843 return GetCode(FIELD);
844}
845
846
847Object* LoadStubCompiler::CompileLoadCallback(JSObject* object,
848 JSObject* holder,
849 AccessorInfo* callback) {
850 // ----------- S t a t e -------------
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000851 // -- r2 : name
852 // -- lr : return address
853 // -- [sp] : receiver
854 // -----------------------------------
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000855 Label miss;
856
mads.s.ager31e71382008-08-13 09:32:07 +0000857 __ ldr(r0, MemOperand(sp, 0));
ager@chromium.org3bf7b912008-11-17 09:09:45 +0000858 GenerateLoadCallback(masm(), object, holder, r0, r2, r3, r1, callback, &miss);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000859 __ bind(&miss);
ager@chromium.org3bf7b912008-11-17 09:09:45 +0000860 GenerateLoadMiss(masm(), Code::LOAD_IC);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000861
862 // Return the generated code.
863 return GetCode(CALLBACKS);
864}
865
866
867Object* LoadStubCompiler::CompileLoadConstant(JSObject* object,
868 JSObject* holder,
869 Object* value) {
870 // ----------- S t a t e -------------
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000871 // -- r2 : name
872 // -- lr : return address
873 // -- [sp] : receiver
874 // -----------------------------------
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000875 Label miss;
876
mads.s.ager31e71382008-08-13 09:32:07 +0000877 __ ldr(r0, MemOperand(sp, 0));
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000878
ager@chromium.org3bf7b912008-11-17 09:09:45 +0000879 GenerateLoadConstant(masm(), object, holder, r0, r3, r1, value, &miss);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000880 __ bind(&miss);
ager@chromium.org3bf7b912008-11-17 09:09:45 +0000881 GenerateLoadMiss(masm(), Code::LOAD_IC);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000882
883 // Return the generated code.
884 return GetCode(CONSTANT_FUNCTION);
885}
886
887
888Object* LoadStubCompiler::CompileLoadInterceptor(JSObject* object,
889 JSObject* holder,
890 String* name) {
891 // ----------- S t a t e -------------
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000892 // -- r2 : name
893 // -- lr : return address
894 // -- [sp] : receiver
895 // -----------------------------------
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000896 Label miss;
897
mads.s.ager31e71382008-08-13 09:32:07 +0000898 __ ldr(r0, MemOperand(sp, 0));
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000899
ager@chromium.org3bf7b912008-11-17 09:09:45 +0000900 GenerateLoadInterceptor(masm(), object, holder, r0, r2, r3, r1, &miss);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000901 __ bind(&miss);
ager@chromium.org3bf7b912008-11-17 09:09:45 +0000902 GenerateLoadMiss(masm(), Code::LOAD_IC);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000903
904 // Return the generated code.
905 return GetCode(INTERCEPTOR);
906}
907
908
909// TODO(1224671): IC stubs for keyed loads have not been implemented
910// for ARM.
911Object* KeyedLoadStubCompiler::CompileLoadField(String* name,
912 JSObject* receiver,
913 JSObject* holder,
914 int index) {
ager@chromium.org3bf7b912008-11-17 09:09:45 +0000915 // ----------- S t a t e -------------
916 // -- lr : return address
917 // -- sp[0] : key
918 // -- sp[4] : receiver
919 // -----------------------------------
ager@chromium.org3bf7b912008-11-17 09:09:45 +0000920 Label miss;
921
922 __ ldr(r2, MemOperand(sp, 0));
923 __ ldr(r0, MemOperand(sp, kPointerSize));
924
925 __ cmp(r2, Operand(Handle<String>(name)));
926 __ b(ne, &miss);
927
928 GenerateLoadField(masm(), receiver, holder, r0, r3, r1, index, &miss);
929 __ bind(&miss);
930 GenerateLoadMiss(masm(), Code::KEYED_LOAD_IC);
931
932 return GetCode(FIELD);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000933}
934
935
936Object* KeyedLoadStubCompiler::CompileLoadCallback(String* name,
937 JSObject* receiver,
938 JSObject* holder,
939 AccessorInfo* callback) {
ager@chromium.org3bf7b912008-11-17 09:09:45 +0000940 // ----------- S t a t e -------------
941 // -- lr : return address
942 // -- sp[0] : key
943 // -- sp[4] : receiver
944 // -----------------------------------
ager@chromium.org3bf7b912008-11-17 09:09:45 +0000945 Label miss;
946
947 __ ldr(r2, MemOperand(sp, 0));
948 __ ldr(r0, MemOperand(sp, kPointerSize));
949
950 __ cmp(r2, Operand(Handle<String>(name)));
951 __ b(ne, &miss);
952
953 GenerateLoadCallback(masm(), receiver, holder, r0, r2, r3,
954 r1, callback, &miss);
955 __ bind(&miss);
956 GenerateLoadMiss(masm(), Code::KEYED_LOAD_IC);
957
958 return GetCode(CALLBACKS);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000959}
960
961
962Object* KeyedLoadStubCompiler::CompileLoadConstant(String* name,
963 JSObject* receiver,
964 JSObject* holder,
965 Object* value) {
ager@chromium.org3bf7b912008-11-17 09:09:45 +0000966 // ----------- S t a t e -------------
967 // -- lr : return address
968 // -- sp[0] : key
969 // -- sp[4] : receiver
970 // -----------------------------------
ager@chromium.org3bf7b912008-11-17 09:09:45 +0000971 Label miss;
972
973 // Check the key is the cached one
974 __ ldr(r2, MemOperand(sp, 0));
975 __ ldr(r0, MemOperand(sp, kPointerSize));
976
977 __ cmp(r2, Operand(Handle<String>(name)));
978 __ b(ne, &miss);
979
980 GenerateLoadConstant(masm(), receiver, holder, r0, r3, r1, value, &miss);
981 __ bind(&miss);
982 GenerateLoadMiss(masm(), Code::KEYED_LOAD_IC);
983
984 // Return the generated code.
985 return GetCode(CONSTANT_FUNCTION);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000986}
987
988
989Object* KeyedLoadStubCompiler::CompileLoadInterceptor(JSObject* receiver,
990 JSObject* holder,
991 String* name) {
ager@chromium.org3bf7b912008-11-17 09:09:45 +0000992 // ----------- S t a t e -------------
993 // -- lr : return address
994 // -- sp[0] : key
995 // -- sp[4] : receiver
996 // -----------------------------------
ager@chromium.org3bf7b912008-11-17 09:09:45 +0000997 Label miss;
998
999 // Check the key is the cached one
1000 __ ldr(r2, MemOperand(sp, 0));
1001 __ ldr(r0, MemOperand(sp, kPointerSize));
1002
1003 __ cmp(r2, Operand(Handle<String>(name)));
1004 __ b(ne, &miss);
1005
1006 GenerateLoadInterceptor(masm(), receiver, holder, r0, r2, r3, r1, &miss);
1007 __ bind(&miss);
1008 GenerateLoadMiss(masm(), Code::KEYED_LOAD_IC);
1009
1010 return GetCode(INTERCEPTOR);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001011}
1012
1013
1014Object* KeyedLoadStubCompiler::CompileLoadArrayLength(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 // -----------------------------------
ager@chromium.org3bf7b912008-11-17 09:09:45 +00001020 Label miss;
1021
1022 // Check the key is the cached one
1023 __ ldr(r2, MemOperand(sp, 0));
1024 __ ldr(r0, MemOperand(sp, kPointerSize));
1025
1026 __ cmp(r2, Operand(Handle<String>(name)));
1027 __ b(ne, &miss);
1028
1029 GenerateLoadArrayLength(masm(), r0, r3, &miss);
1030 __ bind(&miss);
1031 GenerateLoadMiss(masm(), Code::KEYED_LOAD_IC);
1032
1033 return GetCode(CALLBACKS);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001034}
1035
1036
kasperl@chromium.org9fe21c62008-10-28 08:53:51 +00001037Object* KeyedLoadStubCompiler::CompileLoadStringLength(String* name) {
ager@chromium.org3bf7b912008-11-17 09:09:45 +00001038 // ----------- S t a t e -------------
1039 // -- lr : return address
1040 // -- sp[0] : key
1041 // -- sp[4] : receiver
1042 // -----------------------------------
ager@chromium.orga74f0da2008-12-03 16:05:52 +00001043 Label miss;
1044 __ IncrementCounter(&Counters::keyed_load_string_length, 1, r1, r3);
1045
1046 __ ldr(r2, MemOperand(sp));
1047 __ ldr(r0, MemOperand(sp, kPointerSize)); // receiver
1048
1049 __ cmp(r2, Operand(Handle<String>(name)));
1050 __ b(ne, &miss);
1051
1052 GenerateLoadStringLength2(masm(), r0, r1, r3, &miss);
1053 __ bind(&miss);
1054 __ DecrementCounter(&Counters::keyed_load_string_length, 1, r1, r3);
1055
ager@chromium.org3bf7b912008-11-17 09:09:45 +00001056 GenerateLoadMiss(masm(), Code::KEYED_LOAD_IC);
1057
1058 return GetCode(CALLBACKS);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001059}
1060
1061
ager@chromium.org3bf7b912008-11-17 09:09:45 +00001062// TODO(1224671): implement the fast case.
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001063Object* KeyedLoadStubCompiler::CompileLoadFunctionPrototype(String* name) {
ager@chromium.org3bf7b912008-11-17 09:09:45 +00001064 // ----------- S t a t e -------------
1065 // -- lr : return address
1066 // -- sp[0] : key
1067 // -- sp[4] : receiver
1068 // -----------------------------------
ager@chromium.org3bf7b912008-11-17 09:09:45 +00001069 GenerateLoadMiss(masm(), Code::KEYED_LOAD_IC);
1070
1071 return GetCode(CALLBACKS);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001072}
1073
1074
1075Object* KeyedStoreStubCompiler::CompileStoreField(JSObject* object,
1076 int index,
1077 Map* transition,
1078 String* name) {
ager@chromium.org3bf7b912008-11-17 09:09:45 +00001079 // ----------- S t a t e -------------
1080 // -- r0 : value
1081 // -- r2 : name
1082 // -- lr : return address
1083 // -- [sp] : receiver
1084 // -----------------------------------
ager@chromium.orga74f0da2008-12-03 16:05:52 +00001085 Label miss;
1086
1087 __ IncrementCounter(&Counters::keyed_store_field, 1, r1, r3);
1088
1089 // Check that the name has not changed.
1090 __ cmp(r2, Operand(Handle<String>(name)));
1091 __ b(ne, &miss);
1092
1093 // Load receiver from the stack.
1094 __ ldr(r3, MemOperand(sp));
1095 // r1 is used as scratch register, r3 and r2 might be clobbered.
1096 GenerateStoreField(masm(),
1097 Builtins::StoreIC_ExtendStorage,
1098 object,
1099 index,
1100 transition,
1101 r3, r2, r1,
1102 &miss);
1103 __ bind(&miss);
1104
1105 __ DecrementCounter(&Counters::keyed_store_field, 1, r1, r3);
1106 __ mov(r2, Operand(Handle<String>(name))); // restore name register.
ager@chromium.org3bf7b912008-11-17 09:09:45 +00001107 Handle<Code> ic(Builtins::builtin(Builtins::KeyedStoreIC_Miss));
1108 __ Jump(ic, RelocInfo::CODE_TARGET);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001109
ager@chromium.org3bf7b912008-11-17 09:09:45 +00001110 // Return the generated code.
1111 return GetCode(transition == NULL ? FIELD : MAP_TRANSITION);
1112}
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001113
1114
1115#undef __
1116
1117} } // namespace v8::internal