blob: 3eb82694da692f59a5766ca858288ae4ab5f39b6 [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,
249 Register receiver,
250 Register name,
251 Register scratch1,
252 Register scratch2,
253 Label* miss_label) {
254 // Check that the receiver isn't a smi.
255 __ tst(receiver, Operand(kSmiTagMask));
256 __ b(eq, miss_label);
257
258 // Check that the maps haven't changed.
259 Register reg =
ager@chromium.org65dad4b2009-04-23 08:48:43 +0000260 masm->CheckMaps(object, receiver, holder, scratch1, scratch2, miss_label);
ager@chromium.org3bf7b912008-11-17 09:09:45 +0000261
262 // Push the arguments on the JS stack of the caller.
263 __ push(receiver); // receiver
264 __ push(reg); // holder
265 __ push(name); // name
266
267 // Do tail-call to the runtime system.
268 ExternalReference load_ic_property =
269 ExternalReference(IC_Utility(IC::kLoadInterceptorProperty));
270 __ TailCallRuntime(load_ic_property, 3);
271}
272
273
274void StubCompiler::GenerateLoadArrayLength(MacroAssembler* masm,
275 Register receiver,
276 Register scratch,
277 Label* miss_label) {
278 // Check that the receiver isn't a smi.
279 __ tst(receiver, Operand(kSmiTagMask));
280 __ b(eq, miss_label);
281
282 // Check that the object is a JS array.
283 __ ldr(scratch, FieldMemOperand(receiver, HeapObject::kMapOffset));
284 __ ldrb(scratch, FieldMemOperand(scratch, Map::kInstanceTypeOffset));
285 __ cmp(scratch, Operand(JS_ARRAY_TYPE));
286 __ b(ne, miss_label);
287
288 // Load length directly from the JS array.
289 __ ldr(r0, FieldMemOperand(receiver, JSArray::kLengthOffset));
290 __ Ret();
291}
292
293
ager@chromium.orga74f0da2008-12-03 16:05:52 +0000294// Generate code to check if an object is a string. If the object is
295// a string, the map's instance type is left in the scratch1 register.
296static void GenerateStringCheck(MacroAssembler* masm,
297 Register receiver,
298 Register scratch1,
299 Register scratch2,
300 Label* smi,
301 Label* non_string_object) {
302 // Check that the receiver isn't a smi.
303 __ tst(receiver, Operand(kSmiTagMask));
304 __ b(eq, smi);
305
306 // Check that the object is a string.
307 __ ldr(scratch1, FieldMemOperand(receiver, HeapObject::kMapOffset));
308 __ ldrb(scratch1, FieldMemOperand(scratch1, Map::kInstanceTypeOffset));
309 __ and_(scratch2, scratch1, Operand(kIsNotStringMask));
310 // The cast is to resolve the overload for the argument of 0x0.
311 __ cmp(scratch2, Operand(static_cast<int32_t>(kStringTag)));
312 __ b(ne, non_string_object);
313}
314
315
ager@chromium.org32912102009-01-16 10:38:43 +0000316// Generate code to load the length from a string object and return the length.
317// If the receiver object is not a string or a wrapped string object the
318// execution continues at the miss label. The register containing the
319// receiver is potentially clobbered.
ager@chromium.orga74f0da2008-12-03 16:05:52 +0000320void StubCompiler::GenerateLoadStringLength2(MacroAssembler* masm,
321 Register receiver,
322 Register scratch1,
323 Register scratch2,
324 Label* miss) {
ager@chromium.org32912102009-01-16 10:38:43 +0000325 Label check_string, check_wrapper;
ager@chromium.orga74f0da2008-12-03 16:05:52 +0000326
ager@chromium.org32912102009-01-16 10:38:43 +0000327 __ bind(&check_string);
ager@chromium.orga74f0da2008-12-03 16:05:52 +0000328 // Check if the object is a string leaving the instance type in the
329 // scratch1 register.
330 GenerateStringCheck(masm, receiver, scratch1, scratch2,
331 miss, &check_wrapper);
332
333 // Load length directly from the string.
ager@chromium.orga74f0da2008-12-03 16:05:52 +0000334 __ and_(scratch1, scratch1, Operand(kStringSizeMask));
335 __ add(scratch1, scratch1, Operand(String::kHashShift));
336 __ ldr(r0, FieldMemOperand(receiver, String::kLengthOffset));
337 __ mov(r0, Operand(r0, LSR, scratch1));
338 __ mov(r0, Operand(r0, LSL, kSmiTagSize));
339 __ Ret();
340
341 // Check if the object is a JSValue wrapper.
342 __ bind(&check_wrapper);
343 __ cmp(scratch1, Operand(JS_VALUE_TYPE));
344 __ b(ne, miss);
345
ager@chromium.org32912102009-01-16 10:38:43 +0000346 // Unwrap the value in place and check if the wrapped value is a string.
347 __ ldr(receiver, FieldMemOperand(receiver, JSValue::kValueOffset));
348 __ b(&check_string);
ager@chromium.orga74f0da2008-12-03 16:05:52 +0000349}
350
351
352// Generate StoreField code, value is passed in r0 register.
353// After executing generated code, the receiver_reg and name_reg
354// may be clobbered.
355void StubCompiler::GenerateStoreField(MacroAssembler* masm,
356 Builtins::Name storage_extend,
357 JSObject* object,
358 int index,
359 Map* transition,
360 Register receiver_reg,
361 Register name_reg,
362 Register scratch,
363 Label* miss_label) {
364 // r0 : value
365 Label exit;
366
367 // Check that the receiver isn't a smi.
368 __ tst(receiver_reg, Operand(kSmiTagMask));
369 __ b(eq, miss_label);
370
371 // Check that the map of the receiver hasn't changed.
372 __ ldr(scratch, FieldMemOperand(receiver_reg, HeapObject::kMapOffset));
373 __ cmp(scratch, Operand(Handle<Map>(object->map())));
374 __ b(ne, miss_label);
375
376 // Perform global security token check if needed.
377 if (object->IsJSGlobalProxy()) {
378 __ CheckAccessGlobalProxy(receiver_reg, scratch, miss_label);
379 }
380
381 // Stub never generated for non-global objects that require access
382 // checks.
383 ASSERT(object->IsJSGlobalProxy() || !object->IsAccessCheckNeeded());
384
385 // Perform map transition for the receiver if necessary.
386 if ((transition != NULL) && (object->map()->unused_property_fields() == 0)) {
387 // The properties must be extended before we can store the value.
ager@chromium.org32912102009-01-16 10:38:43 +0000388 // We jump to a runtime call that extends the properties array.
ager@chromium.orga74f0da2008-12-03 16:05:52 +0000389 __ mov(r2, Operand(Handle<Map>(transition)));
390 // Please note, if we implement keyed store for arm we need
391 // to call the Builtins::KeyedStoreIC_ExtendStorage.
392 Handle<Code> ic(Builtins::builtin(Builtins::StoreIC_ExtendStorage));
393 __ Jump(ic, RelocInfo::CODE_TARGET);
394 return;
395 }
396
397 if (transition != NULL) {
398 // Update the map of the object; no write barrier updating is
399 // needed because the map is never in new space.
400 __ mov(ip, Operand(Handle<Map>(transition)));
401 __ str(ip, FieldMemOperand(receiver_reg, HeapObject::kMapOffset));
402 }
403
404 // Adjust for the number of properties stored in the object. Even in the
405 // face of a transition we can use the old map here because the size of the
406 // object and the number of in-object properties is not going to change.
407 index -= object->map()->inobject_properties();
408
409 if (index < 0) {
410 // Set the property straight into the object.
411 int offset = object->map()->instance_size() + (index * kPointerSize);
412 __ str(r0, FieldMemOperand(receiver_reg, offset));
413
414 // Skip updating write barrier if storing a smi.
415 __ tst(r0, Operand(kSmiTagMask));
416 __ b(eq, &exit);
417
418 // Update the write barrier for the array address.
419 // Pass the value being stored in the now unused name_reg.
420 __ mov(name_reg, Operand(offset));
421 __ RecordWrite(receiver_reg, name_reg, scratch);
422 } else {
423 // Write to the properties array.
424 int offset = index * kPointerSize + Array::kHeaderSize;
425 // Get the properties array
426 __ ldr(scratch, FieldMemOperand(receiver_reg, JSObject::kPropertiesOffset));
427 __ str(r0, FieldMemOperand(scratch, offset));
428
429 // Skip updating write barrier if storing a smi.
430 __ tst(r0, Operand(kSmiTagMask));
431 __ b(eq, &exit);
432
433 // Update the write barrier for the array address.
434 // Ok to clobber receiver_reg and name_reg, since we return.
435 __ mov(name_reg, Operand(offset));
436 __ RecordWrite(scratch, name_reg, receiver_reg);
437 }
438
439 // Return the value (register r0).
440 __ bind(&exit);
441 __ Ret();
442}
443
444
ager@chromium.org3bf7b912008-11-17 09:09:45 +0000445void StubCompiler::GenerateLoadMiss(MacroAssembler* masm, Code::Kind kind) {
446 ASSERT(kind == Code::LOAD_IC || kind == Code::KEYED_LOAD_IC);
447 Code* code = NULL;
448 if (kind == Code::LOAD_IC) {
449 code = Builtins::builtin(Builtins::LoadIC_Miss);
450 } else {
451 code = Builtins::builtin(Builtins::KeyedLoadIC_Miss);
452 }
453
454 Handle<Code> ic(code);
455 __ Jump(ic, RelocInfo::CODE_TARGET);
456}
457
458
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000459#undef __
ager@chromium.org65dad4b2009-04-23 08:48:43 +0000460#define __ ACCESS_MASM(masm())
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000461
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
kasperl@chromium.org7be3c992009-03-12 07:19:55 +0000491 return GetCodeWithFlags(flags, "LazyCompileStub");
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000492}
493
494
495Object* CallStubCompiler::CompileCallField(Object* object,
496 JSObject* holder,
kasperl@chromium.org7be3c992009-03-12 07:19:55 +0000497 int index,
kasperl@chromium.org71affb52009-05-26 05:44:31 +0000498 String* name,
499 Code::Flags flags) {
500 ASSERT_EQ(FIELD, Code::ExtractTypeFromFlags(flags));
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000501 // ----------- S t a t e -------------
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000502 // -- lr: return address
503 // -----------------------------------
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000504 Label miss;
505
mads.s.ager31e71382008-08-13 09:32:07 +0000506 const int argc = arguments().immediate();
507
kasperl@chromium.org9fe21c62008-10-28 08:53:51 +0000508 // Get the receiver of the function from the stack into r0.
509 __ ldr(r0, MemOperand(sp, argc * kPointerSize));
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000510 // Check that the receiver isn't a smi.
kasperl@chromium.org9fe21c62008-10-28 08:53:51 +0000511 __ tst(r0, Operand(kSmiTagMask));
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000512 __ b(eq, &miss);
513
514 // Do the right check and compute the holder register.
515 Register reg =
ager@chromium.org65dad4b2009-04-23 08:48:43 +0000516 masm()->CheckMaps(JSObject::cast(object), r0, holder, r3, r2, &miss);
ager@chromium.org7c537e22008-10-16 08:43:32 +0000517 GenerateFastPropertyLoad(masm(), r1, reg, holder, index);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000518
519 // Check that the function really is a function.
kasperl@chromium.orgb9123622008-09-17 14:05:56 +0000520 __ tst(r1, Operand(kSmiTagMask));
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000521 __ b(eq, &miss);
522 // Get the map.
kasperl@chromium.orgb9123622008-09-17 14:05:56 +0000523 __ ldr(r2, FieldMemOperand(r1, HeapObject::kMapOffset));
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000524 __ ldrb(r2, FieldMemOperand(r2, Map::kInstanceTypeOffset));
525 __ cmp(r2, Operand(JS_FUNCTION_TYPE));
526 __ b(ne, &miss);
527
kasperl@chromium.org9fe21c62008-10-28 08:53:51 +0000528 // Patch the receiver on the stack with the global proxy if
529 // necessary.
530 if (object->IsGlobalObject()) {
531 __ ldr(r3, FieldMemOperand(r0, GlobalObject::kGlobalReceiverOffset));
532 __ str(r3, MemOperand(sp, argc * kPointerSize));
533 }
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000534
kasperl@chromium.orgb9123622008-09-17 14:05:56 +0000535 // Invoke the function.
536 __ InvokeFunction(r1, arguments(), JUMP_FUNCTION);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000537
538 // Handle call cache miss.
539 __ bind(&miss);
540 Handle<Code> ic = ComputeCallMiss(arguments().immediate());
ager@chromium.org236ad962008-09-25 09:45:57 +0000541 __ Jump(ic, RelocInfo::CODE_TARGET);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000542
543 // Return the generated code.
kasperl@chromium.org71affb52009-05-26 05:44:31 +0000544 return GetCodeWithFlags(flags, name);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000545}
546
547
548Object* CallStubCompiler::CompileCallConstant(Object* object,
549 JSObject* holder,
550 JSFunction* function,
kasperl@chromium.org71affb52009-05-26 05:44:31 +0000551 CheckType check,
552 Code::Flags flags) {
553 ASSERT_EQ(CONSTANT_FUNCTION, Code::ExtractTypeFromFlags(flags));
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000554 // ----------- S t a t e -------------
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000555 // -- lr: return address
556 // -----------------------------------
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000557 Label miss;
558
mads.s.ager31e71382008-08-13 09:32:07 +0000559 // Get the receiver from the stack
560 const int argc = arguments().immediate();
561 __ ldr(r1, MemOperand(sp, argc * kPointerSize));
562
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000563 // Check that the receiver isn't a smi.
564 if (check != NUMBER_CHECK) {
565 __ tst(r1, Operand(kSmiTagMask));
566 __ b(eq, &miss);
567 }
568
kasperl@chromium.org9fe21c62008-10-28 08:53:51 +0000569 // Make sure that it's okay not to patch the on stack receiver
570 // unless we're doing a receiver map check.
571 ASSERT(!object->IsGlobalObject() || check == RECEIVER_MAP_CHECK);
572
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000573 switch (check) {
574 case RECEIVER_MAP_CHECK:
575 // Check that the maps haven't changed.
576 __ CheckMaps(JSObject::cast(object), r1, holder, r3, r2, &miss);
kasperl@chromium.org9fe21c62008-10-28 08:53:51 +0000577
578 // Patch the receiver on the stack with the global proxy if
579 // necessary.
580 if (object->IsGlobalObject()) {
581 __ ldr(r3, FieldMemOperand(r1, GlobalObject::kGlobalReceiverOffset));
582 __ str(r3, MemOperand(sp, argc * kPointerSize));
583 }
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000584 break;
585
586 case STRING_CHECK:
587 // Check that the object is a two-byte string or a symbol.
588 __ ldr(r2, FieldMemOperand(r1, HeapObject::kMapOffset));
589 __ ldrb(r2, FieldMemOperand(r2, Map::kInstanceTypeOffset));
590 __ cmp(r2, Operand(FIRST_NONSTRING_TYPE));
591 __ b(hs, &miss);
592 // Check that the maps starting from the prototype haven't changed.
593 GenerateLoadGlobalFunctionPrototype(masm(),
594 Context::STRING_FUNCTION_INDEX,
595 r2);
596 __ CheckMaps(JSObject::cast(object->GetPrototype()),
597 r2, holder, r3, r1, &miss);
598 break;
599
600 case NUMBER_CHECK: {
601 Label fast;
602 // Check that the object is a smi or a heap number.
603 __ tst(r1, Operand(kSmiTagMask));
604 __ b(eq, &fast);
605 __ ldr(r2, FieldMemOperand(r1, HeapObject::kMapOffset));
606 __ ldrb(r2, FieldMemOperand(r2, Map::kInstanceTypeOffset));
607 __ cmp(r2, Operand(HEAP_NUMBER_TYPE));
608 __ b(ne, &miss);
609 __ bind(&fast);
610 // Check that the maps starting from the prototype haven't changed.
611 GenerateLoadGlobalFunctionPrototype(masm(),
612 Context::NUMBER_FUNCTION_INDEX,
613 r2);
614 __ CheckMaps(JSObject::cast(object->GetPrototype()),
615 r2, holder, r3, r1, &miss);
616 break;
617 }
618
619 case BOOLEAN_CHECK: {
620 Label fast;
621 // Check that the object is a boolean.
622 __ cmp(r1, Operand(Factory::true_value()));
623 __ b(eq, &fast);
624 __ cmp(r1, Operand(Factory::false_value()));
625 __ b(ne, &miss);
626 __ bind(&fast);
627 // Check that the maps starting from the prototype haven't changed.
628 GenerateLoadGlobalFunctionPrototype(masm(),
629 Context::BOOLEAN_FUNCTION_INDEX,
630 r2);
631 __ CheckMaps(JSObject::cast(object->GetPrototype()),
632 r2, holder, r3, r1, &miss);
633 break;
634 }
635
636 case JSARRAY_HAS_FAST_ELEMENTS_CHECK:
637 __ CheckMaps(JSObject::cast(object), r1, holder, r3, r2, &miss);
638 // Make sure object->elements()->map() != Heap::hash_table_map()
639 // Get the elements array of the object.
640 __ ldr(r3, FieldMemOperand(r1, JSObject::kElementsOffset));
641 // Check that the object is in fast mode (not dictionary).
642 __ ldr(r2, FieldMemOperand(r3, HeapObject::kMapOffset));
643 __ cmp(r2, Operand(Factory::hash_table_map()));
644 __ b(eq, &miss);
645 break;
646
647 default:
648 UNREACHABLE();
649 }
650
651 // Get the function and setup the context.
kasperl@chromium.orgb9123622008-09-17 14:05:56 +0000652 __ mov(r1, Operand(Handle<JSFunction>(function)));
653 __ ldr(cp, FieldMemOperand(r1, JSFunction::kContextOffset));
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000654
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000655 // Jump to the cached code (tail call).
656 Handle<Code> code(function->code());
mads.s.ager@gmail.com769cc962008-08-06 10:02:49 +0000657 ParameterCount expected(function->shared()->formal_parameter_count());
ager@chromium.org236ad962008-09-25 09:45:57 +0000658 __ InvokeCode(code, expected, arguments(),
659 RelocInfo::CODE_TARGET, JUMP_FUNCTION);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000660
661 // Handle call cache miss.
662 __ bind(&miss);
663 Handle<Code> ic = ComputeCallMiss(arguments().immediate());
ager@chromium.org236ad962008-09-25 09:45:57 +0000664 __ Jump(ic, RelocInfo::CODE_TARGET);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000665
666 // Return the generated code.
kasperl@chromium.org7be3c992009-03-12 07:19:55 +0000667 String* function_name = NULL;
668 if (function->shared()->name()->IsString()) {
669 function_name = String::cast(function->shared()->name());
670 }
kasperl@chromium.org71affb52009-05-26 05:44:31 +0000671 return GetCodeWithFlags(flags, function_name);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000672}
673
674
675Object* CallStubCompiler::CompileCallInterceptor(Object* object,
676 JSObject* holder,
677 String* name) {
678 // ----------- S t a t e -------------
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000679 // -- lr: return address
680 // -----------------------------------
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000681 Label miss;
682
683 // TODO(1224669): Implement.
684
685 // Handle call cache miss.
686 __ bind(&miss);
687 Handle<Code> ic = ComputeCallMiss(arguments().immediate());
ager@chromium.org236ad962008-09-25 09:45:57 +0000688 __ Jump(ic, RelocInfo::CODE_TARGET);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000689
690 // Return the generated code.
kasperl@chromium.org7be3c992009-03-12 07:19:55 +0000691 return GetCode(INTERCEPTOR, name);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000692}
693
694
695Object* StoreStubCompiler::CompileStoreField(JSObject* object,
696 int index,
697 Map* transition,
698 String* name) {
699 // ----------- S t a t e -------------
700 // -- r0 : value
701 // -- r2 : name
702 // -- lr : return address
703 // -- [sp] : receiver
704 // -----------------------------------
ager@chromium.orga74f0da2008-12-03 16:05:52 +0000705 Label miss;
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000706
707 // Get the receiver from the stack.
708 __ ldr(r3, MemOperand(sp, 0 * kPointerSize));
709
ager@chromium.orga74f0da2008-12-03 16:05:52 +0000710 // name register might be clobbered.
711 GenerateStoreField(masm(),
712 Builtins::StoreIC_ExtendStorage,
713 object,
714 index,
715 transition,
716 r3, r2, r1,
717 &miss);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000718 __ bind(&miss);
719 __ mov(r2, Operand(Handle<String>(name))); // restore name
720 Handle<Code> ic(Builtins::builtin(Builtins::StoreIC_Miss));
ager@chromium.org236ad962008-09-25 09:45:57 +0000721 __ Jump(ic, RelocInfo::CODE_TARGET);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000722
723 // Return the generated code.
kasperl@chromium.org7be3c992009-03-12 07:19:55 +0000724 return GetCode(transition == NULL ? FIELD : MAP_TRANSITION, name);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000725}
726
727
728Object* StoreStubCompiler::CompileStoreCallback(JSObject* object,
729 AccessorInfo* callback,
730 String* name) {
731 // ----------- S t a t e -------------
732 // -- r0 : value
733 // -- r2 : name
734 // -- lr : return address
735 // -- [sp] : receiver
736 // -----------------------------------
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000737 Label miss;
738
739 // Get the object from the stack.
740 __ ldr(r3, MemOperand(sp, 0 * kPointerSize));
741
742 // Check that the object isn't a smi.
743 __ tst(r3, Operand(kSmiTagMask));
744 __ b(eq, &miss);
745
746 // Check that the map of the object hasn't changed.
747 __ ldr(r1, FieldMemOperand(r3, HeapObject::kMapOffset));
748 __ cmp(r1, Operand(Handle<Map>(object->map())));
749 __ b(ne, &miss);
750
751 // Perform global security token check if needed.
kasperl@chromium.org5a8ca6c2008-10-23 13:57:19 +0000752 if (object->IsJSGlobalProxy()) {
753 __ CheckAccessGlobalProxy(r3, r1, &miss);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000754 }
755
756 // Stub never generated for non-global objects that require access
757 // checks.
kasperl@chromium.org5a8ca6c2008-10-23 13:57:19 +0000758 ASSERT(object->IsJSGlobalProxy() || !object->IsAccessCheckNeeded());
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000759
760 __ ldr(ip, MemOperand(sp)); // receiver
761 __ push(ip);
762 __ mov(ip, Operand(Handle<AccessorInfo>(callback))); // callback info
763 __ push(ip);
764 __ push(r2); // name
765 __ push(r0); // value
766
mads.s.ager31e71382008-08-13 09:32:07 +0000767 // Do tail-call to the runtime system.
768 ExternalReference store_callback_property =
769 ExternalReference(IC_Utility(IC::kStoreCallbackProperty));
770 __ TailCallRuntime(store_callback_property, 4);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000771
772 // Handle store cache miss.
773 __ bind(&miss);
774 __ mov(r2, Operand(Handle<String>(name))); // restore name
775 Handle<Code> ic(Builtins::builtin(Builtins::StoreIC_Miss));
ager@chromium.org236ad962008-09-25 09:45:57 +0000776 __ Jump(ic, RelocInfo::CODE_TARGET);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000777
778 // Return the generated code.
kasperl@chromium.org7be3c992009-03-12 07:19:55 +0000779 return GetCode(CALLBACKS, name);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000780}
781
782
783Object* StoreStubCompiler::CompileStoreInterceptor(JSObject* receiver,
784 String* name) {
785 // ----------- S t a t e -------------
786 // -- r0 : value
787 // -- r2 : name
788 // -- lr : return address
789 // -- [sp] : receiver
790 // -----------------------------------
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000791 Label miss;
792
793 // Get the object from the stack.
794 __ ldr(r3, MemOperand(sp, 0 * kPointerSize));
795
796 // Check that the object isn't a smi.
797 __ tst(r3, Operand(kSmiTagMask));
798 __ b(eq, &miss);
799
800 // Check that the map of the object hasn't changed.
801 __ ldr(r1, FieldMemOperand(r3, HeapObject::kMapOffset));
802 __ cmp(r1, Operand(Handle<Map>(receiver->map())));
803 __ b(ne, &miss);
804
805 // Perform global security token check if needed.
kasperl@chromium.org5a8ca6c2008-10-23 13:57:19 +0000806 if (receiver->IsJSGlobalProxy()) {
807 __ CheckAccessGlobalProxy(r3, r1, &miss);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000808 }
809
810 // Stub never generated for non-global objects that require access
811 // checks.
kasperl@chromium.org5a8ca6c2008-10-23 13:57:19 +0000812 ASSERT(receiver->IsJSGlobalProxy() || !receiver->IsAccessCheckNeeded());
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000813
814 __ ldr(ip, MemOperand(sp)); // receiver
815 __ push(ip);
816 __ push(r2); // name
817 __ push(r0); // value
818
mads.s.ager31e71382008-08-13 09:32:07 +0000819 // Do tail-call to the runtime system.
820 ExternalReference store_ic_property =
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000821 ExternalReference(IC_Utility(IC::kStoreInterceptorProperty));
mads.s.ager31e71382008-08-13 09:32:07 +0000822 __ TailCallRuntime(store_ic_property, 3);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000823
824 // Handle store cache miss.
825 __ bind(&miss);
826 __ mov(r2, Operand(Handle<String>(name))); // restore name
827 Handle<Code> ic(Builtins::builtin(Builtins::StoreIC_Miss));
ager@chromium.org236ad962008-09-25 09:45:57 +0000828 __ Jump(ic, RelocInfo::CODE_TARGET);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000829
830 // Return the generated code.
kasperl@chromium.org7be3c992009-03-12 07:19:55 +0000831 return GetCode(INTERCEPTOR, name);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000832}
833
834
835Object* LoadStubCompiler::CompileLoadField(JSObject* object,
836 JSObject* holder,
kasperl@chromium.org7be3c992009-03-12 07:19:55 +0000837 int index,
838 String* name) {
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000839 // ----------- S t a t e -------------
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000840 // -- r2 : name
841 // -- lr : return address
842 // -- [sp] : receiver
843 // -----------------------------------
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000844 Label miss;
845
mads.s.ager31e71382008-08-13 09:32:07 +0000846 __ ldr(r0, MemOperand(sp, 0));
847
ager@chromium.org3bf7b912008-11-17 09:09:45 +0000848 GenerateLoadField(masm(), object, holder, r0, r3, r1, index, &miss);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000849 __ bind(&miss);
ager@chromium.org3bf7b912008-11-17 09:09:45 +0000850 GenerateLoadMiss(masm(), Code::LOAD_IC);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000851
852 // Return the generated code.
kasperl@chromium.org7be3c992009-03-12 07:19:55 +0000853 return GetCode(FIELD, name);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000854}
855
856
857Object* LoadStubCompiler::CompileLoadCallback(JSObject* object,
858 JSObject* holder,
kasperl@chromium.org7be3c992009-03-12 07:19:55 +0000859 AccessorInfo* callback,
860 String* name) {
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000861 // ----------- S t a t e -------------
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000862 // -- r2 : name
863 // -- lr : return address
864 // -- [sp] : receiver
865 // -----------------------------------
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000866 Label miss;
867
mads.s.ager31e71382008-08-13 09:32:07 +0000868 __ ldr(r0, MemOperand(sp, 0));
ager@chromium.org3bf7b912008-11-17 09:09:45 +0000869 GenerateLoadCallback(masm(), object, holder, r0, r2, r3, r1, callback, &miss);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000870 __ bind(&miss);
ager@chromium.org3bf7b912008-11-17 09:09:45 +0000871 GenerateLoadMiss(masm(), Code::LOAD_IC);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000872
873 // Return the generated code.
kasperl@chromium.org7be3c992009-03-12 07:19:55 +0000874 return GetCode(CALLBACKS, name);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000875}
876
877
878Object* LoadStubCompiler::CompileLoadConstant(JSObject* object,
879 JSObject* holder,
kasperl@chromium.org7be3c992009-03-12 07:19:55 +0000880 Object* value,
881 String* name) {
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000882 // ----------- S t a t e -------------
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000883 // -- r2 : name
884 // -- lr : return address
885 // -- [sp] : receiver
886 // -----------------------------------
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000887 Label miss;
888
mads.s.ager31e71382008-08-13 09:32:07 +0000889 __ ldr(r0, MemOperand(sp, 0));
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000890
ager@chromium.org3bf7b912008-11-17 09:09:45 +0000891 GenerateLoadConstant(masm(), object, holder, r0, r3, r1, value, &miss);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000892 __ bind(&miss);
ager@chromium.org3bf7b912008-11-17 09:09:45 +0000893 GenerateLoadMiss(masm(), Code::LOAD_IC);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000894
895 // Return the generated code.
kasperl@chromium.org7be3c992009-03-12 07:19:55 +0000896 return GetCode(CONSTANT_FUNCTION, name);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000897}
898
899
900Object* LoadStubCompiler::CompileLoadInterceptor(JSObject* object,
901 JSObject* holder,
902 String* name) {
903 // ----------- S t a t e -------------
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000904 // -- r2 : name
905 // -- lr : return address
906 // -- [sp] : receiver
907 // -----------------------------------
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000908 Label miss;
909
mads.s.ager31e71382008-08-13 09:32:07 +0000910 __ ldr(r0, MemOperand(sp, 0));
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000911
ager@chromium.org3bf7b912008-11-17 09:09:45 +0000912 GenerateLoadInterceptor(masm(), object, holder, r0, r2, r3, r1, &miss);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000913 __ bind(&miss);
ager@chromium.org3bf7b912008-11-17 09:09:45 +0000914 GenerateLoadMiss(masm(), Code::LOAD_IC);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000915
916 // Return the generated code.
kasperl@chromium.org7be3c992009-03-12 07:19:55 +0000917 return GetCode(INTERCEPTOR, name);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000918}
919
920
921// TODO(1224671): IC stubs for keyed loads have not been implemented
922// for ARM.
923Object* KeyedLoadStubCompiler::CompileLoadField(String* name,
924 JSObject* receiver,
925 JSObject* holder,
926 int index) {
ager@chromium.org3bf7b912008-11-17 09:09:45 +0000927 // ----------- S t a t e -------------
928 // -- lr : return address
929 // -- sp[0] : key
930 // -- sp[4] : receiver
931 // -----------------------------------
ager@chromium.org3bf7b912008-11-17 09:09:45 +0000932 Label miss;
933
934 __ ldr(r2, MemOperand(sp, 0));
935 __ ldr(r0, MemOperand(sp, kPointerSize));
936
937 __ cmp(r2, Operand(Handle<String>(name)));
938 __ b(ne, &miss);
939
940 GenerateLoadField(masm(), receiver, holder, r0, r3, r1, index, &miss);
941 __ bind(&miss);
942 GenerateLoadMiss(masm(), Code::KEYED_LOAD_IC);
943
kasperl@chromium.org7be3c992009-03-12 07:19:55 +0000944 return GetCode(FIELD, name);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000945}
946
947
948Object* KeyedLoadStubCompiler::CompileLoadCallback(String* name,
949 JSObject* receiver,
950 JSObject* holder,
951 AccessorInfo* callback) {
ager@chromium.org3bf7b912008-11-17 09:09:45 +0000952 // ----------- S t a t e -------------
953 // -- lr : return address
954 // -- sp[0] : key
955 // -- sp[4] : receiver
956 // -----------------------------------
ager@chromium.org3bf7b912008-11-17 09:09:45 +0000957 Label miss;
958
959 __ ldr(r2, MemOperand(sp, 0));
960 __ ldr(r0, MemOperand(sp, kPointerSize));
961
962 __ cmp(r2, Operand(Handle<String>(name)));
963 __ b(ne, &miss);
964
965 GenerateLoadCallback(masm(), receiver, holder, r0, r2, r3,
966 r1, callback, &miss);
967 __ bind(&miss);
968 GenerateLoadMiss(masm(), Code::KEYED_LOAD_IC);
969
kasperl@chromium.org7be3c992009-03-12 07:19:55 +0000970 return GetCode(CALLBACKS, name);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000971}
972
973
974Object* KeyedLoadStubCompiler::CompileLoadConstant(String* name,
975 JSObject* receiver,
976 JSObject* holder,
977 Object* value) {
ager@chromium.org3bf7b912008-11-17 09:09:45 +0000978 // ----------- S t a t e -------------
979 // -- lr : return address
980 // -- sp[0] : key
981 // -- sp[4] : receiver
982 // -----------------------------------
ager@chromium.org3bf7b912008-11-17 09:09:45 +0000983 Label miss;
984
985 // Check the key is the cached one
986 __ ldr(r2, MemOperand(sp, 0));
987 __ ldr(r0, MemOperand(sp, kPointerSize));
988
989 __ cmp(r2, Operand(Handle<String>(name)));
990 __ b(ne, &miss);
991
992 GenerateLoadConstant(masm(), receiver, holder, r0, r3, r1, value, &miss);
993 __ bind(&miss);
994 GenerateLoadMiss(masm(), Code::KEYED_LOAD_IC);
995
996 // Return the generated code.
kasperl@chromium.org7be3c992009-03-12 07:19:55 +0000997 return GetCode(CONSTANT_FUNCTION, name);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000998}
999
1000
1001Object* KeyedLoadStubCompiler::CompileLoadInterceptor(JSObject* receiver,
1002 JSObject* holder,
1003 String* name) {
ager@chromium.org3bf7b912008-11-17 09:09:45 +00001004 // ----------- S t a t e -------------
1005 // -- lr : return address
1006 // -- sp[0] : key
1007 // -- sp[4] : receiver
1008 // -----------------------------------
ager@chromium.org3bf7b912008-11-17 09:09:45 +00001009 Label miss;
1010
1011 // Check the key is the cached one
1012 __ ldr(r2, MemOperand(sp, 0));
1013 __ ldr(r0, MemOperand(sp, kPointerSize));
1014
1015 __ cmp(r2, Operand(Handle<String>(name)));
1016 __ b(ne, &miss);
1017
1018 GenerateLoadInterceptor(masm(), receiver, holder, r0, r2, r3, r1, &miss);
1019 __ bind(&miss);
1020 GenerateLoadMiss(masm(), Code::KEYED_LOAD_IC);
1021
kasperl@chromium.org7be3c992009-03-12 07:19:55 +00001022 return GetCode(INTERCEPTOR, name);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001023}
1024
1025
1026Object* KeyedLoadStubCompiler::CompileLoadArrayLength(String* name) {
ager@chromium.org3bf7b912008-11-17 09:09:45 +00001027 // ----------- S t a t e -------------
1028 // -- lr : return address
1029 // -- sp[0] : key
1030 // -- sp[4] : receiver
1031 // -----------------------------------
ager@chromium.org3bf7b912008-11-17 09:09:45 +00001032 Label miss;
1033
1034 // Check the key is the cached one
1035 __ ldr(r2, MemOperand(sp, 0));
1036 __ ldr(r0, MemOperand(sp, kPointerSize));
1037
1038 __ cmp(r2, Operand(Handle<String>(name)));
1039 __ b(ne, &miss);
1040
1041 GenerateLoadArrayLength(masm(), r0, r3, &miss);
1042 __ bind(&miss);
1043 GenerateLoadMiss(masm(), Code::KEYED_LOAD_IC);
1044
kasperl@chromium.org7be3c992009-03-12 07:19:55 +00001045 return GetCode(CALLBACKS, name);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001046}
1047
1048
kasperl@chromium.org9fe21c62008-10-28 08:53:51 +00001049Object* KeyedLoadStubCompiler::CompileLoadStringLength(String* name) {
ager@chromium.org3bf7b912008-11-17 09:09:45 +00001050 // ----------- S t a t e -------------
1051 // -- lr : return address
1052 // -- sp[0] : key
1053 // -- sp[4] : receiver
1054 // -----------------------------------
ager@chromium.orga74f0da2008-12-03 16:05:52 +00001055 Label miss;
1056 __ IncrementCounter(&Counters::keyed_load_string_length, 1, r1, r3);
1057
1058 __ ldr(r2, MemOperand(sp));
1059 __ ldr(r0, MemOperand(sp, kPointerSize)); // receiver
1060
1061 __ cmp(r2, Operand(Handle<String>(name)));
1062 __ b(ne, &miss);
1063
1064 GenerateLoadStringLength2(masm(), r0, r1, r3, &miss);
1065 __ bind(&miss);
1066 __ DecrementCounter(&Counters::keyed_load_string_length, 1, r1, r3);
1067
ager@chromium.org3bf7b912008-11-17 09:09:45 +00001068 GenerateLoadMiss(masm(), Code::KEYED_LOAD_IC);
1069
kasperl@chromium.org7be3c992009-03-12 07:19:55 +00001070 return GetCode(CALLBACKS, name);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001071}
1072
1073
ager@chromium.org3bf7b912008-11-17 09:09:45 +00001074// TODO(1224671): implement the fast case.
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001075Object* KeyedLoadStubCompiler::CompileLoadFunctionPrototype(String* name) {
ager@chromium.org3bf7b912008-11-17 09:09:45 +00001076 // ----------- S t a t e -------------
1077 // -- lr : return address
1078 // -- sp[0] : key
1079 // -- sp[4] : receiver
1080 // -----------------------------------
ager@chromium.org3bf7b912008-11-17 09:09:45 +00001081 GenerateLoadMiss(masm(), Code::KEYED_LOAD_IC);
1082
kasperl@chromium.org7be3c992009-03-12 07:19:55 +00001083 return GetCode(CALLBACKS, name);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001084}
1085
1086
1087Object* KeyedStoreStubCompiler::CompileStoreField(JSObject* object,
1088 int index,
1089 Map* transition,
1090 String* name) {
ager@chromium.org3bf7b912008-11-17 09:09:45 +00001091 // ----------- S t a t e -------------
1092 // -- r0 : value
1093 // -- r2 : name
1094 // -- lr : return address
1095 // -- [sp] : receiver
1096 // -----------------------------------
ager@chromium.orga74f0da2008-12-03 16:05:52 +00001097 Label miss;
1098
1099 __ IncrementCounter(&Counters::keyed_store_field, 1, r1, r3);
1100
1101 // Check that the name has not changed.
1102 __ cmp(r2, Operand(Handle<String>(name)));
1103 __ b(ne, &miss);
1104
1105 // Load receiver from the stack.
1106 __ ldr(r3, MemOperand(sp));
1107 // r1 is used as scratch register, r3 and r2 might be clobbered.
1108 GenerateStoreField(masm(),
1109 Builtins::StoreIC_ExtendStorage,
1110 object,
1111 index,
1112 transition,
1113 r3, r2, r1,
1114 &miss);
1115 __ bind(&miss);
1116
1117 __ DecrementCounter(&Counters::keyed_store_field, 1, r1, r3);
1118 __ mov(r2, Operand(Handle<String>(name))); // restore name register.
ager@chromium.org3bf7b912008-11-17 09:09:45 +00001119 Handle<Code> ic(Builtins::builtin(Builtins::KeyedStoreIC_Miss));
1120 __ Jump(ic, RelocInfo::CODE_TARGET);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001121
ager@chromium.org3bf7b912008-11-17 09:09:45 +00001122 // Return the generated code.
kasperl@chromium.org7be3c992009-03-12 07:19:55 +00001123 return GetCode(transition == NULL ? FIELD : MAP_TRANSITION, name);
ager@chromium.org3bf7b912008-11-17 09:09:45 +00001124}
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001125
1126
1127#undef __
1128
1129} } // namespace v8::internal