blob: 782455792e27eeef7772e23fb17bdaf1060f8d1c [file] [log] [blame]
kasperl@chromium.org71affb52009-05-26 05:44:31 +00001// Copyright 2006-2009 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
kasperl@chromium.org71affb52009-05-26 05:44:31 +000034namespace v8 {
35namespace internal {
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +000036
ager@chromium.org65dad4b2009-04-23 08:48:43 +000037#define __ ACCESS_MASM(masm)
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +000038
39
40static void ProbeTable(MacroAssembler* masm,
41 Code::Flags flags,
42 StubCache::Table table,
43 Register name,
44 Register offset) {
45 ExternalReference key_offset(SCTableReference::keyReference(table));
46 ExternalReference value_offset(SCTableReference::valueReference(table));
47
48 Label miss;
49
50 // Save the offset on the stack.
51 __ push(offset);
52
53 // Check that the key in the entry matches the name.
54 __ mov(ip, Operand(key_offset));
55 __ ldr(ip, MemOperand(ip, offset, LSL, 1));
56 __ cmp(name, Operand(ip));
57 __ b(ne, &miss);
58
59 // Get the code entry from the cache.
60 __ mov(ip, Operand(value_offset));
61 __ ldr(offset, MemOperand(ip, offset, LSL, 1));
62
63 // Check that the flags match what we're looking for.
64 __ ldr(offset, FieldMemOperand(offset, Code::kFlagsOffset));
kasperl@chromium.org71affb52009-05-26 05:44:31 +000065 __ and_(offset, offset, Operand(~Code::kFlagsNotUsedInLookup));
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +000066 __ cmp(offset, Operand(flags));
67 __ b(ne, &miss);
68
69 // Restore offset and re-load code entry from cache.
70 __ pop(offset);
71 __ mov(ip, Operand(value_offset));
72 __ ldr(offset, MemOperand(ip, offset, LSL, 1));
73
74 // Jump to the first instruction in the code stub.
75 __ add(offset, offset, Operand(Code::kHeaderSize - kHeapObjectTag));
76 __ Jump(offset);
77
78 // Miss: Restore offset and fall through.
79 __ bind(&miss);
80 __ pop(offset);
81}
82
83
84void StubCache::GenerateProbe(MacroAssembler* masm,
85 Code::Flags flags,
86 Register receiver,
87 Register name,
88 Register scratch) {
89 Label miss;
90
91 // Make sure that code is valid. The shifting code relies on the
92 // entry size being 8.
93 ASSERT(sizeof(Entry) == 8);
94
95 // Make sure the flags does not name a specific type.
96 ASSERT(Code::ExtractTypeFromFlags(flags) == 0);
97
98 // Make sure that there are no register conflicts.
99 ASSERT(!scratch.is(receiver));
100 ASSERT(!scratch.is(name));
101
102 // Check that the receiver isn't a smi.
103 __ tst(receiver, Operand(kSmiTagMask));
104 __ b(eq, &miss);
105
106 // Get the map of the receiver and compute the hash.
ager@chromium.org7c537e22008-10-16 08:43:32 +0000107 __ ldr(scratch, FieldMemOperand(name, String::kLengthOffset));
108 __ ldr(ip, FieldMemOperand(receiver, HeapObject::kMapOffset));
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000109 __ add(scratch, scratch, Operand(ip));
110 __ eor(scratch, scratch, Operand(flags));
111 __ and_(scratch,
112 scratch,
113 Operand((kPrimaryTableSize - 1) << kHeapObjectTagSize));
114
115 // Probe the primary table.
116 ProbeTable(masm, flags, kPrimary, name, scratch);
117
118 // Primary miss: Compute hash for secondary probe.
119 __ sub(scratch, scratch, Operand(name));
120 __ add(scratch, scratch, Operand(flags));
121 __ and_(scratch,
122 scratch,
123 Operand((kSecondaryTableSize - 1) << kHeapObjectTagSize));
124
125 // Probe the secondary table.
126 ProbeTable(masm, flags, kSecondary, name, scratch);
127
128 // Cache miss: Fall-through and let caller handle the miss by
129 // entering the runtime system.
130 __ bind(&miss);
131}
132
133
134void StubCompiler::GenerateLoadGlobalFunctionPrototype(MacroAssembler* masm,
135 int index,
136 Register prototype) {
137 // Load the global or builtins object from the current context.
138 __ ldr(prototype, MemOperand(cp, Context::SlotOffset(Context::GLOBAL_INDEX)));
139 // Load the global context from the global or builtins object.
140 __ ldr(prototype,
141 FieldMemOperand(prototype, GlobalObject::kGlobalContextOffset));
142 // Load the function from the global context.
143 __ ldr(prototype, MemOperand(prototype, Context::SlotOffset(index)));
144 // Load the initial map. The global functions all have initial maps.
145 __ ldr(prototype,
146 FieldMemOperand(prototype, JSFunction::kPrototypeOrInitialMapOffset));
147 // Load the prototype from the initial map.
148 __ ldr(prototype, FieldMemOperand(prototype, Map::kPrototypeOffset));
149}
150
151
ager@chromium.org7c537e22008-10-16 08:43:32 +0000152// Load a fast property out of a holder object (src). In-object properties
153// are loaded directly otherwise the property is loaded from the properties
154// fixed array.
155void StubCompiler::GenerateFastPropertyLoad(MacroAssembler* masm,
156 Register dst, Register src,
157 JSObject* holder, int index) {
158 // Adjust for the number of properties stored in the holder.
159 index -= holder->map()->inobject_properties();
160 if (index < 0) {
161 // Get the property straight out of the holder.
162 int offset = holder->map()->instance_size() + (index * kPointerSize);
163 __ ldr(dst, FieldMemOperand(src, offset));
164 } else {
165 // Calculate the offset into the properties array.
166 int offset = index * kPointerSize + Array::kHeaderSize;
167 __ ldr(dst, FieldMemOperand(src, JSObject::kPropertiesOffset));
168 __ ldr(dst, FieldMemOperand(dst, offset));
169 }
170}
171
172
ager@chromium.org3bf7b912008-11-17 09:09:45 +0000173void StubCompiler::GenerateLoadField(MacroAssembler* masm,
174 JSObject* object,
175 JSObject* holder,
176 Register receiver,
177 Register scratch1,
178 Register scratch2,
179 int index,
180 Label* miss_label) {
181 // Check that the receiver isn't a smi.
182 __ tst(receiver, Operand(kSmiTagMask));
183 __ b(eq, miss_label);
184
185 // Check that the maps haven't changed.
186 Register reg =
ager@chromium.org65dad4b2009-04-23 08:48:43 +0000187 masm->CheckMaps(object, receiver, holder, scratch1, scratch2, miss_label);
ager@chromium.org3bf7b912008-11-17 09:09:45 +0000188 GenerateFastPropertyLoad(masm, r0, reg, holder, index);
189 __ Ret();
190}
191
192
193void StubCompiler::GenerateLoadConstant(MacroAssembler* masm,
194 JSObject* object,
195 JSObject* holder,
196 Register receiver,
197 Register scratch1,
198 Register scratch2,
199 Object* value,
200 Label* miss_label) {
201 // Check that the receiver isn't a smi.
202 __ tst(receiver, Operand(kSmiTagMask));
203 __ b(eq, miss_label);
204
205 // Check that the maps haven't changed.
206 Register reg =
ager@chromium.org65dad4b2009-04-23 08:48:43 +0000207 masm->CheckMaps(object, receiver, holder, scratch1, scratch2, miss_label);
ager@chromium.org3bf7b912008-11-17 09:09:45 +0000208
209 // Return the constant value.
210 __ mov(r0, Operand(Handle<Object>(value)));
211 __ Ret();
212}
213
214
215void StubCompiler::GenerateLoadCallback(MacroAssembler* masm,
216 JSObject* object,
217 JSObject* holder,
218 Register receiver,
219 Register name,
220 Register scratch1,
221 Register scratch2,
222 AccessorInfo* callback,
223 Label* miss_label) {
224 // Check that the receiver isn't a smi.
225 __ tst(receiver, Operand(kSmiTagMask));
226 __ b(eq, miss_label);
227
228 // Check that the maps haven't changed.
229 Register reg =
ager@chromium.org65dad4b2009-04-23 08:48:43 +0000230 masm->CheckMaps(object, receiver, holder, scratch1, scratch2, miss_label);
ager@chromium.org3bf7b912008-11-17 09:09:45 +0000231
232 // Push the arguments on the JS stack of the caller.
233 __ push(receiver); // receiver
234 __ mov(ip, Operand(Handle<AccessorInfo>(callback))); // callback data
235 __ push(ip);
236 __ push(name); // name
237 __ push(reg); // holder
238
239 // Do tail-call to the runtime system.
240 ExternalReference load_callback_property =
241 ExternalReference(IC_Utility(IC::kLoadCallbackProperty));
242 __ TailCallRuntime(load_callback_property, 4);
243}
244
245
246void StubCompiler::GenerateLoadInterceptor(MacroAssembler* masm,
247 JSObject* object,
248 JSObject* holder,
ager@chromium.orge2902be2009-06-08 12:21:35 +0000249 Smi* lookup_hint,
ager@chromium.org3bf7b912008-11-17 09:09:45 +0000250 Register receiver,
251 Register name,
252 Register scratch1,
253 Register scratch2,
254 Label* miss_label) {
255 // Check that the receiver isn't a smi.
256 __ tst(receiver, Operand(kSmiTagMask));
257 __ b(eq, miss_label);
258
259 // Check that the maps haven't changed.
260 Register reg =
ager@chromium.org65dad4b2009-04-23 08:48:43 +0000261 masm->CheckMaps(object, receiver, holder, scratch1, scratch2, miss_label);
ager@chromium.org3bf7b912008-11-17 09:09:45 +0000262
263 // Push the arguments on the JS stack of the caller.
264 __ push(receiver); // receiver
265 __ push(reg); // holder
266 __ push(name); // name
ager@chromium.orge2902be2009-06-08 12:21:35 +0000267 __ mov(scratch1, Operand(lookup_hint));
268 __ push(scratch1);
ager@chromium.org3bf7b912008-11-17 09:09:45 +0000269
270 // Do tail-call to the runtime system.
271 ExternalReference load_ic_property =
272 ExternalReference(IC_Utility(IC::kLoadInterceptorProperty));
ager@chromium.orge2902be2009-06-08 12:21:35 +0000273 __ TailCallRuntime(load_ic_property, 4);
ager@chromium.org3bf7b912008-11-17 09:09:45 +0000274}
275
276
277void StubCompiler::GenerateLoadArrayLength(MacroAssembler* masm,
278 Register receiver,
279 Register scratch,
280 Label* miss_label) {
281 // Check that the receiver isn't a smi.
282 __ tst(receiver, Operand(kSmiTagMask));
283 __ b(eq, miss_label);
284
285 // Check that the object is a JS array.
ager@chromium.orgeadaf222009-06-16 09:43:10 +0000286 __ CompareObjectType(receiver, scratch, scratch, JS_ARRAY_TYPE);
ager@chromium.org3bf7b912008-11-17 09:09:45 +0000287 __ b(ne, miss_label);
288
289 // Load length directly from the JS array.
290 __ ldr(r0, FieldMemOperand(receiver, JSArray::kLengthOffset));
291 __ Ret();
292}
293
294
ager@chromium.orga74f0da2008-12-03 16:05:52 +0000295// Generate code to check if an object is a string. If the object is
296// a string, the map's instance type is left in the scratch1 register.
297static void GenerateStringCheck(MacroAssembler* masm,
298 Register receiver,
299 Register scratch1,
300 Register scratch2,
301 Label* smi,
302 Label* non_string_object) {
303 // Check that the receiver isn't a smi.
304 __ tst(receiver, Operand(kSmiTagMask));
305 __ b(eq, smi);
306
307 // Check that the object is a string.
308 __ ldr(scratch1, FieldMemOperand(receiver, HeapObject::kMapOffset));
309 __ ldrb(scratch1, FieldMemOperand(scratch1, Map::kInstanceTypeOffset));
310 __ and_(scratch2, scratch1, Operand(kIsNotStringMask));
311 // The cast is to resolve the overload for the argument of 0x0.
312 __ cmp(scratch2, Operand(static_cast<int32_t>(kStringTag)));
313 __ b(ne, non_string_object);
314}
315
316
ager@chromium.org32912102009-01-16 10:38:43 +0000317// Generate code to load the length from a string object and return the length.
318// If the receiver object is not a string or a wrapped string object the
319// execution continues at the miss label. The register containing the
320// receiver is potentially clobbered.
ager@chromium.orga74f0da2008-12-03 16:05:52 +0000321void StubCompiler::GenerateLoadStringLength2(MacroAssembler* masm,
322 Register receiver,
323 Register scratch1,
324 Register scratch2,
325 Label* miss) {
ager@chromium.org32912102009-01-16 10:38:43 +0000326 Label check_string, check_wrapper;
ager@chromium.orga74f0da2008-12-03 16:05:52 +0000327
ager@chromium.org32912102009-01-16 10:38:43 +0000328 __ bind(&check_string);
ager@chromium.orga74f0da2008-12-03 16:05:52 +0000329 // Check if the object is a string leaving the instance type in the
330 // scratch1 register.
331 GenerateStringCheck(masm, receiver, scratch1, scratch2,
332 miss, &check_wrapper);
333
334 // Load length directly from the string.
ager@chromium.orga74f0da2008-12-03 16:05:52 +0000335 __ and_(scratch1, scratch1, Operand(kStringSizeMask));
336 __ add(scratch1, scratch1, Operand(String::kHashShift));
337 __ ldr(r0, FieldMemOperand(receiver, String::kLengthOffset));
338 __ mov(r0, Operand(r0, LSR, scratch1));
339 __ mov(r0, Operand(r0, LSL, kSmiTagSize));
340 __ Ret();
341
342 // Check if the object is a JSValue wrapper.
343 __ bind(&check_wrapper);
344 __ cmp(scratch1, Operand(JS_VALUE_TYPE));
345 __ b(ne, miss);
346
ager@chromium.org32912102009-01-16 10:38:43 +0000347 // Unwrap the value in place and check if the wrapped value is a string.
348 __ ldr(receiver, FieldMemOperand(receiver, JSValue::kValueOffset));
349 __ b(&check_string);
ager@chromium.orga74f0da2008-12-03 16:05:52 +0000350}
351
352
353// Generate StoreField code, value is passed in r0 register.
354// After executing generated code, the receiver_reg and name_reg
355// may be clobbered.
356void StubCompiler::GenerateStoreField(MacroAssembler* masm,
357 Builtins::Name storage_extend,
358 JSObject* object,
359 int index,
360 Map* transition,
361 Register receiver_reg,
362 Register name_reg,
363 Register scratch,
364 Label* miss_label) {
365 // r0 : value
366 Label exit;
367
368 // Check that the receiver isn't a smi.
369 __ tst(receiver_reg, Operand(kSmiTagMask));
370 __ b(eq, miss_label);
371
372 // Check that the map of the receiver hasn't changed.
373 __ ldr(scratch, FieldMemOperand(receiver_reg, HeapObject::kMapOffset));
374 __ cmp(scratch, Operand(Handle<Map>(object->map())));
375 __ b(ne, miss_label);
376
377 // Perform global security token check if needed.
378 if (object->IsJSGlobalProxy()) {
379 __ CheckAccessGlobalProxy(receiver_reg, scratch, miss_label);
380 }
381
382 // Stub never generated for non-global objects that require access
383 // checks.
384 ASSERT(object->IsJSGlobalProxy() || !object->IsAccessCheckNeeded());
385
386 // Perform map transition for the receiver if necessary.
387 if ((transition != NULL) && (object->map()->unused_property_fields() == 0)) {
388 // The properties must be extended before we can store the value.
ager@chromium.org32912102009-01-16 10:38:43 +0000389 // We jump to a runtime call that extends the properties array.
ager@chromium.orga74f0da2008-12-03 16:05:52 +0000390 __ mov(r2, Operand(Handle<Map>(transition)));
391 // Please note, if we implement keyed store for arm we need
392 // to call the Builtins::KeyedStoreIC_ExtendStorage.
393 Handle<Code> ic(Builtins::builtin(Builtins::StoreIC_ExtendStorage));
394 __ Jump(ic, RelocInfo::CODE_TARGET);
395 return;
396 }
397
398 if (transition != NULL) {
399 // Update the map of the object; no write barrier updating is
400 // needed because the map is never in new space.
401 __ mov(ip, Operand(Handle<Map>(transition)));
402 __ str(ip, FieldMemOperand(receiver_reg, HeapObject::kMapOffset));
403 }
404
405 // Adjust for the number of properties stored in the object. Even in the
406 // face of a transition we can use the old map here because the size of the
407 // object and the number of in-object properties is not going to change.
408 index -= object->map()->inobject_properties();
409
410 if (index < 0) {
411 // Set the property straight into the object.
412 int offset = object->map()->instance_size() + (index * kPointerSize);
413 __ str(r0, FieldMemOperand(receiver_reg, offset));
414
415 // Skip updating write barrier if storing a smi.
416 __ tst(r0, Operand(kSmiTagMask));
417 __ b(eq, &exit);
418
419 // Update the write barrier for the array address.
420 // Pass the value being stored in the now unused name_reg.
421 __ mov(name_reg, Operand(offset));
422 __ RecordWrite(receiver_reg, name_reg, scratch);
423 } else {
424 // Write to the properties array.
425 int offset = index * kPointerSize + Array::kHeaderSize;
426 // Get the properties array
427 __ ldr(scratch, FieldMemOperand(receiver_reg, JSObject::kPropertiesOffset));
428 __ str(r0, FieldMemOperand(scratch, offset));
429
430 // Skip updating write barrier if storing a smi.
431 __ tst(r0, Operand(kSmiTagMask));
432 __ b(eq, &exit);
433
434 // Update the write barrier for the array address.
435 // Ok to clobber receiver_reg and name_reg, since we return.
436 __ mov(name_reg, Operand(offset));
437 __ RecordWrite(scratch, name_reg, receiver_reg);
438 }
439
440 // Return the value (register r0).
441 __ bind(&exit);
442 __ Ret();
443}
444
445
ager@chromium.org3bf7b912008-11-17 09:09:45 +0000446void StubCompiler::GenerateLoadMiss(MacroAssembler* masm, Code::Kind kind) {
447 ASSERT(kind == Code::LOAD_IC || kind == Code::KEYED_LOAD_IC);
448 Code* code = NULL;
449 if (kind == Code::LOAD_IC) {
450 code = Builtins::builtin(Builtins::LoadIC_Miss);
451 } else {
452 code = Builtins::builtin(Builtins::KeyedLoadIC_Miss);
453 }
454
455 Handle<Code> ic(code);
456 __ Jump(ic, RelocInfo::CODE_TARGET);
457}
458
459
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000460#undef __
ager@chromium.org65dad4b2009-04-23 08:48:43 +0000461#define __ ACCESS_MASM(masm())
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000462
463
464Object* StubCompiler::CompileLazyCompile(Code::Flags flags) {
kasperl@chromium.orgb9123622008-09-17 14:05:56 +0000465 // ----------- S t a t e -------------
466 // -- r1: function
467 // -- lr: return address
468 // -----------------------------------
469
kasperl@chromium.orgb9123622008-09-17 14:05:56 +0000470 // Enter an internal frame.
471 __ EnterInternalFrame();
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000472
kasperl@chromium.orgb9123622008-09-17 14:05:56 +0000473 // Preserve the function.
474 __ push(r1);
475
476 // Push the function on the stack as the argument to the runtime function.
477 __ push(r1);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000478 __ CallRuntime(Runtime::kLazyCompile, 1);
479
kasperl@chromium.orgb9123622008-09-17 14:05:56 +0000480 // Calculate the entry point.
481 __ add(r2, r0, Operand(Code::kHeaderSize - kHeapObjectTag));
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000482
kasperl@chromium.orgb9123622008-09-17 14:05:56 +0000483 // Restore saved function.
484 __ pop(r1);
485
486 // Tear down temporary frame.
ager@chromium.org236ad962008-09-25 09:45:57 +0000487 __ LeaveInternalFrame();
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000488
489 // Do a tail-call of the compiled function.
kasperl@chromium.orgb9123622008-09-17 14:05:56 +0000490 __ Jump(r2);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000491
kasperl@chromium.org7be3c992009-03-12 07:19:55 +0000492 return GetCodeWithFlags(flags, "LazyCompileStub");
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000493}
494
495
496Object* CallStubCompiler::CompileCallField(Object* object,
497 JSObject* holder,
kasperl@chromium.org7be3c992009-03-12 07:19:55 +0000498 int index,
kasperl@chromium.org71affb52009-05-26 05:44:31 +0000499 String* name,
500 Code::Flags flags) {
501 ASSERT_EQ(FIELD, Code::ExtractTypeFromFlags(flags));
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000502 // ----------- S t a t e -------------
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000503 // -- lr: return address
504 // -----------------------------------
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000505 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 =
ager@chromium.org65dad4b2009-04-23 08:48:43 +0000517 masm()->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.
ager@chromium.orgeadaf222009-06-16 09:43:10 +0000524 __ CompareObjectType(r1, r2, r2, JS_FUNCTION_TYPE);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000525 __ 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.
kasperl@chromium.org71affb52009-05-26 05:44:31 +0000543 return GetCodeWithFlags(flags, name);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000544}
545
546
547Object* CallStubCompiler::CompileCallConstant(Object* object,
548 JSObject* holder,
549 JSFunction* function,
kasperl@chromium.org71affb52009-05-26 05:44:31 +0000550 CheckType check,
551 Code::Flags flags) {
552 ASSERT_EQ(CONSTANT_FUNCTION, Code::ExtractTypeFromFlags(flags));
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000553 // ----------- S t a t e -------------
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000554 // -- lr: return address
555 // -----------------------------------
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000556 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.
ager@chromium.orgeadaf222009-06-16 09:43:10 +0000587 __ CompareObjectType(r1, r2, r2, FIRST_NONSTRING_TYPE);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000588 __ b(hs, &miss);
589 // Check that the maps starting from the prototype haven't changed.
590 GenerateLoadGlobalFunctionPrototype(masm(),
591 Context::STRING_FUNCTION_INDEX,
592 r2);
593 __ CheckMaps(JSObject::cast(object->GetPrototype()),
594 r2, holder, r3, r1, &miss);
595 break;
596
597 case NUMBER_CHECK: {
598 Label fast;
599 // Check that the object is a smi or a heap number.
600 __ tst(r1, Operand(kSmiTagMask));
601 __ b(eq, &fast);
ager@chromium.orgeadaf222009-06-16 09:43:10 +0000602 __ CompareObjectType(r1, r2, r2, HEAP_NUMBER_TYPE);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000603 __ 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.
kasperl@chromium.org7be3c992009-03-12 07:19:55 +0000662 String* function_name = NULL;
663 if (function->shared()->name()->IsString()) {
664 function_name = String::cast(function->shared()->name());
665 }
kasperl@chromium.org71affb52009-05-26 05:44:31 +0000666 return GetCodeWithFlags(flags, function_name);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000667}
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 // -----------------------------------
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000676 Label miss;
677
678 // TODO(1224669): Implement.
679
680 // Handle call cache miss.
681 __ bind(&miss);
682 Handle<Code> ic = ComputeCallMiss(arguments().immediate());
ager@chromium.org236ad962008-09-25 09:45:57 +0000683 __ Jump(ic, RelocInfo::CODE_TARGET);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000684
685 // Return the generated code.
kasperl@chromium.org7be3c992009-03-12 07:19:55 +0000686 return GetCode(INTERCEPTOR, name);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000687}
688
689
690Object* StoreStubCompiler::CompileStoreField(JSObject* object,
691 int index,
692 Map* transition,
693 String* name) {
694 // ----------- S t a t e -------------
695 // -- r0 : value
696 // -- r2 : name
697 // -- lr : return address
698 // -- [sp] : receiver
699 // -----------------------------------
ager@chromium.orga74f0da2008-12-03 16:05:52 +0000700 Label miss;
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000701
702 // Get the receiver from the stack.
703 __ ldr(r3, MemOperand(sp, 0 * kPointerSize));
704
ager@chromium.orga74f0da2008-12-03 16:05:52 +0000705 // name register might be clobbered.
706 GenerateStoreField(masm(),
707 Builtins::StoreIC_ExtendStorage,
708 object,
709 index,
710 transition,
711 r3, r2, r1,
712 &miss);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000713 __ bind(&miss);
714 __ mov(r2, Operand(Handle<String>(name))); // restore name
715 Handle<Code> ic(Builtins::builtin(Builtins::StoreIC_Miss));
ager@chromium.org236ad962008-09-25 09:45:57 +0000716 __ Jump(ic, RelocInfo::CODE_TARGET);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000717
718 // Return the generated code.
kasperl@chromium.org7be3c992009-03-12 07:19:55 +0000719 return GetCode(transition == NULL ? FIELD : MAP_TRANSITION, name);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000720}
721
722
723Object* StoreStubCompiler::CompileStoreCallback(JSObject* object,
724 AccessorInfo* callback,
725 String* name) {
726 // ----------- S t a t e -------------
727 // -- r0 : value
728 // -- r2 : name
729 // -- lr : return address
730 // -- [sp] : receiver
731 // -----------------------------------
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000732 Label miss;
733
734 // Get the object from the stack.
735 __ ldr(r3, MemOperand(sp, 0 * kPointerSize));
736
737 // Check that the object isn't a smi.
738 __ tst(r3, Operand(kSmiTagMask));
739 __ b(eq, &miss);
740
741 // Check that the map of the object hasn't changed.
742 __ ldr(r1, FieldMemOperand(r3, HeapObject::kMapOffset));
743 __ cmp(r1, Operand(Handle<Map>(object->map())));
744 __ b(ne, &miss);
745
746 // Perform global security token check if needed.
kasperl@chromium.org5a8ca6c2008-10-23 13:57:19 +0000747 if (object->IsJSGlobalProxy()) {
748 __ CheckAccessGlobalProxy(r3, r1, &miss);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000749 }
750
751 // Stub never generated for non-global objects that require access
752 // checks.
kasperl@chromium.org5a8ca6c2008-10-23 13:57:19 +0000753 ASSERT(object->IsJSGlobalProxy() || !object->IsAccessCheckNeeded());
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000754
755 __ ldr(ip, MemOperand(sp)); // receiver
756 __ push(ip);
757 __ mov(ip, Operand(Handle<AccessorInfo>(callback))); // callback info
758 __ push(ip);
759 __ push(r2); // name
760 __ push(r0); // value
761
mads.s.ager31e71382008-08-13 09:32:07 +0000762 // Do tail-call to the runtime system.
763 ExternalReference store_callback_property =
764 ExternalReference(IC_Utility(IC::kStoreCallbackProperty));
765 __ TailCallRuntime(store_callback_property, 4);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000766
767 // Handle store cache miss.
768 __ bind(&miss);
769 __ mov(r2, Operand(Handle<String>(name))); // restore name
770 Handle<Code> ic(Builtins::builtin(Builtins::StoreIC_Miss));
ager@chromium.org236ad962008-09-25 09:45:57 +0000771 __ Jump(ic, RelocInfo::CODE_TARGET);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000772
773 // Return the generated code.
kasperl@chromium.org7be3c992009-03-12 07:19:55 +0000774 return GetCode(CALLBACKS, name);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000775}
776
777
778Object* StoreStubCompiler::CompileStoreInterceptor(JSObject* receiver,
779 String* name) {
780 // ----------- S t a t e -------------
781 // -- r0 : value
782 // -- r2 : name
783 // -- lr : return address
784 // -- [sp] : receiver
785 // -----------------------------------
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000786 Label miss;
787
788 // Get the object from the stack.
789 __ ldr(r3, MemOperand(sp, 0 * kPointerSize));
790
791 // Check that the object isn't a smi.
792 __ tst(r3, Operand(kSmiTagMask));
793 __ b(eq, &miss);
794
795 // Check that the map of the object hasn't changed.
796 __ ldr(r1, FieldMemOperand(r3, HeapObject::kMapOffset));
797 __ cmp(r1, Operand(Handle<Map>(receiver->map())));
798 __ b(ne, &miss);
799
800 // Perform global security token check if needed.
kasperl@chromium.org5a8ca6c2008-10-23 13:57:19 +0000801 if (receiver->IsJSGlobalProxy()) {
802 __ CheckAccessGlobalProxy(r3, r1, &miss);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000803 }
804
805 // Stub never generated for non-global objects that require access
806 // checks.
kasperl@chromium.org5a8ca6c2008-10-23 13:57:19 +0000807 ASSERT(receiver->IsJSGlobalProxy() || !receiver->IsAccessCheckNeeded());
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000808
809 __ ldr(ip, MemOperand(sp)); // receiver
810 __ push(ip);
811 __ push(r2); // name
812 __ push(r0); // value
813
mads.s.ager31e71382008-08-13 09:32:07 +0000814 // Do tail-call to the runtime system.
815 ExternalReference store_ic_property =
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000816 ExternalReference(IC_Utility(IC::kStoreInterceptorProperty));
mads.s.ager31e71382008-08-13 09:32:07 +0000817 __ TailCallRuntime(store_ic_property, 3);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000818
819 // Handle store cache miss.
820 __ bind(&miss);
821 __ mov(r2, Operand(Handle<String>(name))); // restore name
822 Handle<Code> ic(Builtins::builtin(Builtins::StoreIC_Miss));
ager@chromium.org236ad962008-09-25 09:45:57 +0000823 __ Jump(ic, RelocInfo::CODE_TARGET);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000824
825 // Return the generated code.
kasperl@chromium.org7be3c992009-03-12 07:19:55 +0000826 return GetCode(INTERCEPTOR, name);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000827}
828
829
830Object* LoadStubCompiler::CompileLoadField(JSObject* object,
831 JSObject* holder,
kasperl@chromium.org7be3c992009-03-12 07:19:55 +0000832 int index,
833 String* name) {
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000834 // ----------- S t a t e -------------
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000835 // -- r2 : name
836 // -- lr : return address
837 // -- [sp] : receiver
838 // -----------------------------------
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000839 Label miss;
840
mads.s.ager31e71382008-08-13 09:32:07 +0000841 __ ldr(r0, MemOperand(sp, 0));
842
ager@chromium.org3bf7b912008-11-17 09:09:45 +0000843 GenerateLoadField(masm(), object, holder, r0, r3, r1, index, &miss);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000844 __ bind(&miss);
ager@chromium.org3bf7b912008-11-17 09:09:45 +0000845 GenerateLoadMiss(masm(), Code::LOAD_IC);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000846
847 // Return the generated code.
kasperl@chromium.org7be3c992009-03-12 07:19:55 +0000848 return GetCode(FIELD, name);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000849}
850
851
852Object* LoadStubCompiler::CompileLoadCallback(JSObject* object,
853 JSObject* holder,
kasperl@chromium.org7be3c992009-03-12 07:19:55 +0000854 AccessorInfo* callback,
855 String* name) {
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000856 // ----------- S t a t e -------------
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000857 // -- r2 : name
858 // -- lr : return address
859 // -- [sp] : receiver
860 // -----------------------------------
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000861 Label miss;
862
mads.s.ager31e71382008-08-13 09:32:07 +0000863 __ ldr(r0, MemOperand(sp, 0));
ager@chromium.org3bf7b912008-11-17 09:09:45 +0000864 GenerateLoadCallback(masm(), object, holder, r0, r2, r3, r1, callback, &miss);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000865 __ bind(&miss);
ager@chromium.org3bf7b912008-11-17 09:09:45 +0000866 GenerateLoadMiss(masm(), Code::LOAD_IC);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000867
868 // Return the generated code.
kasperl@chromium.org7be3c992009-03-12 07:19:55 +0000869 return GetCode(CALLBACKS, name);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000870}
871
872
873Object* LoadStubCompiler::CompileLoadConstant(JSObject* object,
874 JSObject* holder,
kasperl@chromium.org7be3c992009-03-12 07:19:55 +0000875 Object* value,
876 String* name) {
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000877 // ----------- S t a t e -------------
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000878 // -- r2 : name
879 // -- lr : return address
880 // -- [sp] : receiver
881 // -----------------------------------
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000882 Label miss;
883
mads.s.ager31e71382008-08-13 09:32:07 +0000884 __ ldr(r0, MemOperand(sp, 0));
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000885
ager@chromium.org3bf7b912008-11-17 09:09:45 +0000886 GenerateLoadConstant(masm(), object, holder, r0, r3, r1, value, &miss);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000887 __ bind(&miss);
ager@chromium.org3bf7b912008-11-17 09:09:45 +0000888 GenerateLoadMiss(masm(), Code::LOAD_IC);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000889
890 // Return the generated code.
kasperl@chromium.org7be3c992009-03-12 07:19:55 +0000891 return GetCode(CONSTANT_FUNCTION, name);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000892}
893
894
895Object* LoadStubCompiler::CompileLoadInterceptor(JSObject* object,
896 JSObject* holder,
897 String* name) {
898 // ----------- S t a t e -------------
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000899 // -- r2 : name
900 // -- lr : return address
901 // -- [sp] : receiver
902 // -----------------------------------
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000903 Label miss;
904
mads.s.ager31e71382008-08-13 09:32:07 +0000905 __ ldr(r0, MemOperand(sp, 0));
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000906
ager@chromium.orge2902be2009-06-08 12:21:35 +0000907 GenerateLoadInterceptor(masm(),
908 object,
909 holder,
910 holder->InterceptorPropertyLookupHint(name),
911 r0,
912 r2,
913 r3,
914 r1,
915 &miss);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000916 __ bind(&miss);
ager@chromium.org3bf7b912008-11-17 09:09:45 +0000917 GenerateLoadMiss(masm(), Code::LOAD_IC);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000918
919 // Return the generated code.
kasperl@chromium.org7be3c992009-03-12 07:19:55 +0000920 return GetCode(INTERCEPTOR, name);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000921}
922
923
924// TODO(1224671): IC stubs for keyed loads have not been implemented
925// for ARM.
926Object* KeyedLoadStubCompiler::CompileLoadField(String* name,
927 JSObject* receiver,
928 JSObject* holder,
929 int index) {
ager@chromium.org3bf7b912008-11-17 09:09:45 +0000930 // ----------- S t a t e -------------
931 // -- lr : return address
932 // -- sp[0] : key
933 // -- sp[4] : receiver
934 // -----------------------------------
ager@chromium.org3bf7b912008-11-17 09:09:45 +0000935 Label miss;
936
937 __ ldr(r2, MemOperand(sp, 0));
938 __ ldr(r0, MemOperand(sp, kPointerSize));
939
940 __ cmp(r2, Operand(Handle<String>(name)));
941 __ b(ne, &miss);
942
943 GenerateLoadField(masm(), receiver, holder, r0, r3, r1, index, &miss);
944 __ bind(&miss);
945 GenerateLoadMiss(masm(), Code::KEYED_LOAD_IC);
946
kasperl@chromium.org7be3c992009-03-12 07:19:55 +0000947 return GetCode(FIELD, name);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000948}
949
950
951Object* KeyedLoadStubCompiler::CompileLoadCallback(String* name,
952 JSObject* receiver,
953 JSObject* holder,
954 AccessorInfo* callback) {
ager@chromium.org3bf7b912008-11-17 09:09:45 +0000955 // ----------- S t a t e -------------
956 // -- lr : return address
957 // -- sp[0] : key
958 // -- sp[4] : receiver
959 // -----------------------------------
ager@chromium.org3bf7b912008-11-17 09:09:45 +0000960 Label miss;
961
962 __ ldr(r2, MemOperand(sp, 0));
963 __ ldr(r0, MemOperand(sp, kPointerSize));
964
965 __ cmp(r2, Operand(Handle<String>(name)));
966 __ b(ne, &miss);
967
968 GenerateLoadCallback(masm(), receiver, holder, r0, r2, r3,
969 r1, callback, &miss);
970 __ bind(&miss);
971 GenerateLoadMiss(masm(), Code::KEYED_LOAD_IC);
972
kasperl@chromium.org7be3c992009-03-12 07:19:55 +0000973 return GetCode(CALLBACKS, name);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000974}
975
976
977Object* KeyedLoadStubCompiler::CompileLoadConstant(String* name,
978 JSObject* receiver,
979 JSObject* holder,
980 Object* value) {
ager@chromium.org3bf7b912008-11-17 09:09:45 +0000981 // ----------- S t a t e -------------
982 // -- lr : return address
983 // -- sp[0] : key
984 // -- sp[4] : receiver
985 // -----------------------------------
ager@chromium.org3bf7b912008-11-17 09:09:45 +0000986 Label miss;
987
988 // Check the key is the cached one
989 __ ldr(r2, MemOperand(sp, 0));
990 __ ldr(r0, MemOperand(sp, kPointerSize));
991
992 __ cmp(r2, Operand(Handle<String>(name)));
993 __ b(ne, &miss);
994
995 GenerateLoadConstant(masm(), receiver, holder, r0, r3, r1, value, &miss);
996 __ bind(&miss);
997 GenerateLoadMiss(masm(), Code::KEYED_LOAD_IC);
998
999 // Return the generated code.
kasperl@chromium.org7be3c992009-03-12 07:19:55 +00001000 return GetCode(CONSTANT_FUNCTION, name);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001001}
1002
1003
1004Object* KeyedLoadStubCompiler::CompileLoadInterceptor(JSObject* receiver,
1005 JSObject* holder,
1006 String* name) {
ager@chromium.org3bf7b912008-11-17 09:09:45 +00001007 // ----------- S t a t e -------------
1008 // -- lr : return address
1009 // -- sp[0] : key
1010 // -- sp[4] : receiver
1011 // -----------------------------------
ager@chromium.org3bf7b912008-11-17 09:09:45 +00001012 Label miss;
1013
1014 // Check the key is the cached one
1015 __ ldr(r2, MemOperand(sp, 0));
1016 __ ldr(r0, MemOperand(sp, kPointerSize));
1017
1018 __ cmp(r2, Operand(Handle<String>(name)));
1019 __ b(ne, &miss);
1020
ager@chromium.orge2902be2009-06-08 12:21:35 +00001021 GenerateLoadInterceptor(masm(),
1022 receiver,
1023 holder,
1024 Smi::FromInt(JSObject::kLookupInHolder),
1025 r0,
1026 r2,
1027 r3,
1028 r1,
1029 &miss);
ager@chromium.org3bf7b912008-11-17 09:09:45 +00001030 __ bind(&miss);
1031 GenerateLoadMiss(masm(), Code::KEYED_LOAD_IC);
1032
kasperl@chromium.org7be3c992009-03-12 07:19:55 +00001033 return GetCode(INTERCEPTOR, name);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001034}
1035
1036
1037Object* KeyedLoadStubCompiler::CompileLoadArrayLength(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.org3bf7b912008-11-17 09:09:45 +00001043 Label miss;
1044
1045 // Check the key is the cached one
1046 __ ldr(r2, MemOperand(sp, 0));
1047 __ ldr(r0, MemOperand(sp, kPointerSize));
1048
1049 __ cmp(r2, Operand(Handle<String>(name)));
1050 __ b(ne, &miss);
1051
1052 GenerateLoadArrayLength(masm(), r0, r3, &miss);
1053 __ bind(&miss);
1054 GenerateLoadMiss(masm(), Code::KEYED_LOAD_IC);
1055
kasperl@chromium.org7be3c992009-03-12 07:19:55 +00001056 return GetCode(CALLBACKS, name);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001057}
1058
1059
kasperl@chromium.org9fe21c62008-10-28 08:53:51 +00001060Object* KeyedLoadStubCompiler::CompileLoadStringLength(String* name) {
ager@chromium.org3bf7b912008-11-17 09:09:45 +00001061 // ----------- S t a t e -------------
1062 // -- lr : return address
1063 // -- sp[0] : key
1064 // -- sp[4] : receiver
1065 // -----------------------------------
ager@chromium.orga74f0da2008-12-03 16:05:52 +00001066 Label miss;
1067 __ IncrementCounter(&Counters::keyed_load_string_length, 1, r1, r3);
1068
1069 __ ldr(r2, MemOperand(sp));
1070 __ ldr(r0, MemOperand(sp, kPointerSize)); // receiver
1071
1072 __ cmp(r2, Operand(Handle<String>(name)));
1073 __ b(ne, &miss);
1074
1075 GenerateLoadStringLength2(masm(), r0, r1, r3, &miss);
1076 __ bind(&miss);
1077 __ DecrementCounter(&Counters::keyed_load_string_length, 1, r1, r3);
1078
ager@chromium.org3bf7b912008-11-17 09:09:45 +00001079 GenerateLoadMiss(masm(), Code::KEYED_LOAD_IC);
1080
kasperl@chromium.org7be3c992009-03-12 07:19:55 +00001081 return GetCode(CALLBACKS, name);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001082}
1083
1084
ager@chromium.org3bf7b912008-11-17 09:09:45 +00001085// TODO(1224671): implement the fast case.
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001086Object* KeyedLoadStubCompiler::CompileLoadFunctionPrototype(String* name) {
ager@chromium.org3bf7b912008-11-17 09:09:45 +00001087 // ----------- S t a t e -------------
1088 // -- lr : return address
1089 // -- sp[0] : key
1090 // -- sp[4] : receiver
1091 // -----------------------------------
ager@chromium.org3bf7b912008-11-17 09:09:45 +00001092 GenerateLoadMiss(masm(), Code::KEYED_LOAD_IC);
1093
kasperl@chromium.org7be3c992009-03-12 07:19:55 +00001094 return GetCode(CALLBACKS, name);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001095}
1096
1097
1098Object* KeyedStoreStubCompiler::CompileStoreField(JSObject* object,
1099 int index,
1100 Map* transition,
1101 String* name) {
ager@chromium.org3bf7b912008-11-17 09:09:45 +00001102 // ----------- S t a t e -------------
1103 // -- r0 : value
1104 // -- r2 : name
1105 // -- lr : return address
1106 // -- [sp] : receiver
1107 // -----------------------------------
ager@chromium.orga74f0da2008-12-03 16:05:52 +00001108 Label miss;
1109
1110 __ IncrementCounter(&Counters::keyed_store_field, 1, r1, r3);
1111
1112 // Check that the name has not changed.
1113 __ cmp(r2, Operand(Handle<String>(name)));
1114 __ b(ne, &miss);
1115
1116 // Load receiver from the stack.
1117 __ ldr(r3, MemOperand(sp));
1118 // r1 is used as scratch register, r3 and r2 might be clobbered.
1119 GenerateStoreField(masm(),
1120 Builtins::StoreIC_ExtendStorage,
1121 object,
1122 index,
1123 transition,
1124 r3, r2, r1,
1125 &miss);
1126 __ bind(&miss);
1127
1128 __ DecrementCounter(&Counters::keyed_store_field, 1, r1, r3);
1129 __ mov(r2, Operand(Handle<String>(name))); // restore name register.
ager@chromium.org3bf7b912008-11-17 09:09:45 +00001130 Handle<Code> ic(Builtins::builtin(Builtins::KeyedStoreIC_Miss));
1131 __ Jump(ic, RelocInfo::CODE_TARGET);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001132
ager@chromium.org3bf7b912008-11-17 09:09:45 +00001133 // Return the generated code.
kasperl@chromium.org7be3c992009-03-12 07:19:55 +00001134 return GetCode(transition == NULL ? FIELD : MAP_TRANSITION, name);
ager@chromium.org3bf7b912008-11-17 09:09:45 +00001135}
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001136
1137
1138#undef __
1139
1140} } // namespace v8::internal