blob: 56afa0288484d59fd6bf030704f007dfc1a91913 [file] [log] [blame]
ager@chromium.org9258b6b2008-09-11 09:11:10 +00001// Copyright 2006-2008 the V8 project authors. All rights reserved.
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002// Redistribution and use in source and binary forms, with or without
3// modification, are permitted provided that the following conditions are
4// met:
5//
6// * Redistributions of source code must retain the above copyright
7// notice, this list of conditions and the following disclaimer.
8// * Redistributions in binary form must reproduce the above
9// copyright notice, this list of conditions and the following
10// disclaimer in the documentation and/or other materials provided
11// with the distribution.
12// * Neither the name of Google Inc. nor the names of its
13// contributors may be used to endorse or promote products derived
14// from this software without specific prior written permission.
15//
16// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
17// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
18// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
19// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
20// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
21// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
22// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
23// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
24// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
25// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
26// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27
28#include "v8.h"
29
30#include "ic-inl.h"
31#include "codegen-inl.h"
32#include "stub-cache.h"
33
34namespace v8 { namespace internal {
35
ager@chromium.org65dad4b2009-04-23 08:48:43 +000036#define __ ACCESS_MASM(masm)
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +000037
38
39static void ProbeTable(MacroAssembler* masm,
40 Code::Flags flags,
41 StubCache::Table table,
42 Register name,
43 Register offset) {
44 ExternalReference key_offset(SCTableReference::keyReference(table));
45 ExternalReference value_offset(SCTableReference::valueReference(table));
46
47 Label miss;
48
49 // Save the offset on the stack.
50 __ push(offset);
51
52 // Check that the key in the entry matches the name.
53 __ mov(ip, Operand(key_offset));
54 __ ldr(ip, MemOperand(ip, offset, LSL, 1));
55 __ cmp(name, Operand(ip));
56 __ b(ne, &miss);
57
58 // Get the code entry from the cache.
59 __ mov(ip, Operand(value_offset));
60 __ ldr(offset, MemOperand(ip, offset, LSL, 1));
61
62 // Check that the flags match what we're looking for.
63 __ ldr(offset, FieldMemOperand(offset, Code::kFlagsOffset));
64 __ and_(offset, offset, Operand(~Code::kFlagsTypeMask));
65 __ cmp(offset, Operand(flags));
66 __ b(ne, &miss);
67
68 // Restore offset and re-load code entry from cache.
69 __ pop(offset);
70 __ mov(ip, Operand(value_offset));
71 __ ldr(offset, MemOperand(ip, offset, LSL, 1));
72
73 // Jump to the first instruction in the code stub.
74 __ add(offset, offset, Operand(Code::kHeaderSize - kHeapObjectTag));
75 __ Jump(offset);
76
77 // Miss: Restore offset and fall through.
78 __ bind(&miss);
79 __ pop(offset);
80}
81
82
83void StubCache::GenerateProbe(MacroAssembler* masm,
84 Code::Flags flags,
85 Register receiver,
86 Register name,
87 Register scratch) {
88 Label miss;
89
90 // Make sure that code is valid. The shifting code relies on the
91 // entry size being 8.
92 ASSERT(sizeof(Entry) == 8);
93
94 // Make sure the flags does not name a specific type.
95 ASSERT(Code::ExtractTypeFromFlags(flags) == 0);
96
97 // Make sure that there are no register conflicts.
98 ASSERT(!scratch.is(receiver));
99 ASSERT(!scratch.is(name));
100
101 // Check that the receiver isn't a smi.
102 __ tst(receiver, Operand(kSmiTagMask));
103 __ b(eq, &miss);
104
105 // Get the map of the receiver and compute the hash.
ager@chromium.org7c537e22008-10-16 08:43:32 +0000106 __ ldr(scratch, FieldMemOperand(name, String::kLengthOffset));
107 __ ldr(ip, FieldMemOperand(receiver, HeapObject::kMapOffset));
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000108 __ add(scratch, scratch, Operand(ip));
109 __ eor(scratch, scratch, Operand(flags));
110 __ and_(scratch,
111 scratch,
112 Operand((kPrimaryTableSize - 1) << kHeapObjectTagSize));
113
114 // Probe the primary table.
115 ProbeTable(masm, flags, kPrimary, name, scratch);
116
117 // Primary miss: Compute hash for secondary probe.
118 __ sub(scratch, scratch, Operand(name));
119 __ add(scratch, scratch, Operand(flags));
120 __ and_(scratch,
121 scratch,
122 Operand((kSecondaryTableSize - 1) << kHeapObjectTagSize));
123
124 // Probe the secondary table.
125 ProbeTable(masm, flags, kSecondary, name, scratch);
126
127 // Cache miss: Fall-through and let caller handle the miss by
128 // entering the runtime system.
129 __ bind(&miss);
130}
131
132
133void StubCompiler::GenerateLoadGlobalFunctionPrototype(MacroAssembler* masm,
134 int index,
135 Register prototype) {
136 // Load the global or builtins object from the current context.
137 __ ldr(prototype, MemOperand(cp, Context::SlotOffset(Context::GLOBAL_INDEX)));
138 // Load the global context from the global or builtins object.
139 __ ldr(prototype,
140 FieldMemOperand(prototype, GlobalObject::kGlobalContextOffset));
141 // Load the function from the global context.
142 __ ldr(prototype, MemOperand(prototype, Context::SlotOffset(index)));
143 // Load the initial map. The global functions all have initial maps.
144 __ ldr(prototype,
145 FieldMemOperand(prototype, JSFunction::kPrototypeOrInitialMapOffset));
146 // Load the prototype from the initial map.
147 __ ldr(prototype, FieldMemOperand(prototype, Map::kPrototypeOffset));
148}
149
150
ager@chromium.org7c537e22008-10-16 08:43:32 +0000151// Load a fast property out of a holder object (src). In-object properties
152// are loaded directly otherwise the property is loaded from the properties
153// fixed array.
154void StubCompiler::GenerateFastPropertyLoad(MacroAssembler* masm,
155 Register dst, Register src,
156 JSObject* holder, int index) {
157 // Adjust for the number of properties stored in the holder.
158 index -= holder->map()->inobject_properties();
159 if (index < 0) {
160 // Get the property straight out of the holder.
161 int offset = holder->map()->instance_size() + (index * kPointerSize);
162 __ ldr(dst, FieldMemOperand(src, offset));
163 } else {
164 // Calculate the offset into the properties array.
165 int offset = index * kPointerSize + Array::kHeaderSize;
166 __ ldr(dst, FieldMemOperand(src, JSObject::kPropertiesOffset));
167 __ ldr(dst, FieldMemOperand(dst, offset));
168 }
169}
170
171
ager@chromium.org3bf7b912008-11-17 09:09:45 +0000172void StubCompiler::GenerateLoadField(MacroAssembler* masm,
173 JSObject* object,
174 JSObject* holder,
175 Register receiver,
176 Register scratch1,
177 Register scratch2,
178 int index,
179 Label* miss_label) {
180 // Check that the receiver isn't a smi.
181 __ tst(receiver, Operand(kSmiTagMask));
182 __ b(eq, miss_label);
183
184 // Check that the maps haven't changed.
185 Register reg =
ager@chromium.org65dad4b2009-04-23 08:48:43 +0000186 masm->CheckMaps(object, receiver, holder, scratch1, scratch2, miss_label);
ager@chromium.org3bf7b912008-11-17 09:09:45 +0000187 GenerateFastPropertyLoad(masm, r0, reg, holder, index);
188 __ Ret();
189}
190
191
192void StubCompiler::GenerateLoadConstant(MacroAssembler* masm,
193 JSObject* object,
194 JSObject* holder,
195 Register receiver,
196 Register scratch1,
197 Register scratch2,
198 Object* value,
199 Label* miss_label) {
200 // Check that the receiver isn't a smi.
201 __ tst(receiver, Operand(kSmiTagMask));
202 __ b(eq, miss_label);
203
204 // Check that the maps haven't changed.
205 Register reg =
ager@chromium.org65dad4b2009-04-23 08:48:43 +0000206 masm->CheckMaps(object, receiver, holder, scratch1, scratch2, miss_label);
ager@chromium.org3bf7b912008-11-17 09:09:45 +0000207
208 // Return the constant value.
209 __ mov(r0, Operand(Handle<Object>(value)));
210 __ Ret();
211}
212
213
214void StubCompiler::GenerateLoadCallback(MacroAssembler* masm,
215 JSObject* object,
216 JSObject* holder,
217 Register receiver,
218 Register name,
219 Register scratch1,
220 Register scratch2,
221 AccessorInfo* callback,
222 Label* miss_label) {
223 // Check that the receiver isn't a smi.
224 __ tst(receiver, Operand(kSmiTagMask));
225 __ b(eq, miss_label);
226
227 // Check that the maps haven't changed.
228 Register reg =
ager@chromium.org65dad4b2009-04-23 08:48:43 +0000229 masm->CheckMaps(object, receiver, holder, scratch1, scratch2, miss_label);
ager@chromium.org3bf7b912008-11-17 09:09:45 +0000230
231 // Push the arguments on the JS stack of the caller.
232 __ push(receiver); // receiver
233 __ mov(ip, Operand(Handle<AccessorInfo>(callback))); // callback data
234 __ push(ip);
235 __ push(name); // name
236 __ push(reg); // holder
237
238 // Do tail-call to the runtime system.
239 ExternalReference load_callback_property =
240 ExternalReference(IC_Utility(IC::kLoadCallbackProperty));
241 __ TailCallRuntime(load_callback_property, 4);
242}
243
244
245void StubCompiler::GenerateLoadInterceptor(MacroAssembler* masm,
246 JSObject* object,
247 JSObject* holder,
248 Register receiver,
249 Register name,
250 Register scratch1,
251 Register scratch2,
252 Label* miss_label) {
253 // Check that the receiver isn't a smi.
254 __ tst(receiver, Operand(kSmiTagMask));
255 __ b(eq, miss_label);
256
257 // Check that the maps haven't changed.
258 Register reg =
ager@chromium.org65dad4b2009-04-23 08:48:43 +0000259 masm->CheckMaps(object, receiver, holder, scratch1, scratch2, miss_label);
ager@chromium.org3bf7b912008-11-17 09:09:45 +0000260
261 // Push the arguments on the JS stack of the caller.
262 __ push(receiver); // receiver
263 __ push(reg); // holder
264 __ push(name); // name
265
266 // Do tail-call to the runtime system.
267 ExternalReference load_ic_property =
268 ExternalReference(IC_Utility(IC::kLoadInterceptorProperty));
269 __ TailCallRuntime(load_ic_property, 3);
270}
271
272
273void StubCompiler::GenerateLoadArrayLength(MacroAssembler* masm,
274 Register receiver,
275 Register scratch,
276 Label* miss_label) {
277 // Check that the receiver isn't a smi.
278 __ tst(receiver, Operand(kSmiTagMask));
279 __ b(eq, miss_label);
280
281 // Check that the object is a JS array.
282 __ ldr(scratch, FieldMemOperand(receiver, HeapObject::kMapOffset));
283 __ ldrb(scratch, FieldMemOperand(scratch, Map::kInstanceTypeOffset));
284 __ cmp(scratch, Operand(JS_ARRAY_TYPE));
285 __ b(ne, miss_label);
286
287 // Load length directly from the JS array.
288 __ ldr(r0, FieldMemOperand(receiver, JSArray::kLengthOffset));
289 __ Ret();
290}
291
292
ager@chromium.orga74f0da2008-12-03 16:05:52 +0000293// Generate code to check if an object is a string. If the object is
294// a string, the map's instance type is left in the scratch1 register.
295static void GenerateStringCheck(MacroAssembler* masm,
296 Register receiver,
297 Register scratch1,
298 Register scratch2,
299 Label* smi,
300 Label* non_string_object) {
301 // Check that the receiver isn't a smi.
302 __ tst(receiver, Operand(kSmiTagMask));
303 __ b(eq, smi);
304
305 // Check that the object is a string.
306 __ ldr(scratch1, FieldMemOperand(receiver, HeapObject::kMapOffset));
307 __ ldrb(scratch1, FieldMemOperand(scratch1, Map::kInstanceTypeOffset));
308 __ and_(scratch2, scratch1, Operand(kIsNotStringMask));
309 // The cast is to resolve the overload for the argument of 0x0.
310 __ cmp(scratch2, Operand(static_cast<int32_t>(kStringTag)));
311 __ b(ne, non_string_object);
312}
313
314
ager@chromium.org32912102009-01-16 10:38:43 +0000315// Generate code to load the length from a string object and return the length.
316// If the receiver object is not a string or a wrapped string object the
317// execution continues at the miss label. The register containing the
318// receiver is potentially clobbered.
ager@chromium.orga74f0da2008-12-03 16:05:52 +0000319void StubCompiler::GenerateLoadStringLength2(MacroAssembler* masm,
320 Register receiver,
321 Register scratch1,
322 Register scratch2,
323 Label* miss) {
ager@chromium.org32912102009-01-16 10:38:43 +0000324 Label check_string, check_wrapper;
ager@chromium.orga74f0da2008-12-03 16:05:52 +0000325
ager@chromium.org32912102009-01-16 10:38:43 +0000326 __ bind(&check_string);
ager@chromium.orga74f0da2008-12-03 16:05:52 +0000327 // Check if the object is a string leaving the instance type in the
328 // scratch1 register.
329 GenerateStringCheck(masm, receiver, scratch1, scratch2,
330 miss, &check_wrapper);
331
332 // Load length directly from the string.
ager@chromium.orga74f0da2008-12-03 16:05:52 +0000333 __ and_(scratch1, scratch1, Operand(kStringSizeMask));
334 __ add(scratch1, scratch1, Operand(String::kHashShift));
335 __ ldr(r0, FieldMemOperand(receiver, String::kLengthOffset));
336 __ mov(r0, Operand(r0, LSR, scratch1));
337 __ mov(r0, Operand(r0, LSL, kSmiTagSize));
338 __ Ret();
339
340 // Check if the object is a JSValue wrapper.
341 __ bind(&check_wrapper);
342 __ cmp(scratch1, Operand(JS_VALUE_TYPE));
343 __ b(ne, miss);
344
ager@chromium.org32912102009-01-16 10:38:43 +0000345 // Unwrap the value in place and check if the wrapped value is a string.
346 __ ldr(receiver, FieldMemOperand(receiver, JSValue::kValueOffset));
347 __ b(&check_string);
ager@chromium.orga74f0da2008-12-03 16:05:52 +0000348}
349
350
351// Generate StoreField code, value is passed in r0 register.
352// After executing generated code, the receiver_reg and name_reg
353// may be clobbered.
354void StubCompiler::GenerateStoreField(MacroAssembler* masm,
355 Builtins::Name storage_extend,
356 JSObject* object,
357 int index,
358 Map* transition,
359 Register receiver_reg,
360 Register name_reg,
361 Register scratch,
362 Label* miss_label) {
363 // r0 : value
364 Label exit;
365
366 // Check that the receiver isn't a smi.
367 __ tst(receiver_reg, Operand(kSmiTagMask));
368 __ b(eq, miss_label);
369
370 // Check that the map of the receiver hasn't changed.
371 __ ldr(scratch, FieldMemOperand(receiver_reg, HeapObject::kMapOffset));
372 __ cmp(scratch, Operand(Handle<Map>(object->map())));
373 __ b(ne, miss_label);
374
375 // Perform global security token check if needed.
376 if (object->IsJSGlobalProxy()) {
377 __ CheckAccessGlobalProxy(receiver_reg, scratch, miss_label);
378 }
379
380 // Stub never generated for non-global objects that require access
381 // checks.
382 ASSERT(object->IsJSGlobalProxy() || !object->IsAccessCheckNeeded());
383
384 // Perform map transition for the receiver if necessary.
385 if ((transition != NULL) && (object->map()->unused_property_fields() == 0)) {
386 // The properties must be extended before we can store the value.
ager@chromium.org32912102009-01-16 10:38:43 +0000387 // We jump to a runtime call that extends the properties array.
ager@chromium.orga74f0da2008-12-03 16:05:52 +0000388 __ mov(r2, Operand(Handle<Map>(transition)));
389 // Please note, if we implement keyed store for arm we need
390 // to call the Builtins::KeyedStoreIC_ExtendStorage.
391 Handle<Code> ic(Builtins::builtin(Builtins::StoreIC_ExtendStorage));
392 __ Jump(ic, RelocInfo::CODE_TARGET);
393 return;
394 }
395
396 if (transition != NULL) {
397 // Update the map of the object; no write barrier updating is
398 // needed because the map is never in new space.
399 __ mov(ip, Operand(Handle<Map>(transition)));
400 __ str(ip, FieldMemOperand(receiver_reg, HeapObject::kMapOffset));
401 }
402
403 // Adjust for the number of properties stored in the object. Even in the
404 // face of a transition we can use the old map here because the size of the
405 // object and the number of in-object properties is not going to change.
406 index -= object->map()->inobject_properties();
407
408 if (index < 0) {
409 // Set the property straight into the object.
410 int offset = object->map()->instance_size() + (index * kPointerSize);
411 __ str(r0, FieldMemOperand(receiver_reg, offset));
412
413 // Skip updating write barrier if storing a smi.
414 __ tst(r0, Operand(kSmiTagMask));
415 __ b(eq, &exit);
416
417 // Update the write barrier for the array address.
418 // Pass the value being stored in the now unused name_reg.
419 __ mov(name_reg, Operand(offset));
420 __ RecordWrite(receiver_reg, name_reg, scratch);
421 } else {
422 // Write to the properties array.
423 int offset = index * kPointerSize + Array::kHeaderSize;
424 // Get the properties array
425 __ ldr(scratch, FieldMemOperand(receiver_reg, JSObject::kPropertiesOffset));
426 __ str(r0, FieldMemOperand(scratch, offset));
427
428 // Skip updating write barrier if storing a smi.
429 __ tst(r0, Operand(kSmiTagMask));
430 __ b(eq, &exit);
431
432 // Update the write barrier for the array address.
433 // Ok to clobber receiver_reg and name_reg, since we return.
434 __ mov(name_reg, Operand(offset));
435 __ RecordWrite(scratch, name_reg, receiver_reg);
436 }
437
438 // Return the value (register r0).
439 __ bind(&exit);
440 __ Ret();
441}
442
443
ager@chromium.org3bf7b912008-11-17 09:09:45 +0000444void StubCompiler::GenerateLoadMiss(MacroAssembler* masm, Code::Kind kind) {
445 ASSERT(kind == Code::LOAD_IC || kind == Code::KEYED_LOAD_IC);
446 Code* code = NULL;
447 if (kind == Code::LOAD_IC) {
448 code = Builtins::builtin(Builtins::LoadIC_Miss);
449 } else {
450 code = Builtins::builtin(Builtins::KeyedLoadIC_Miss);
451 }
452
453 Handle<Code> ic(code);
454 __ Jump(ic, RelocInfo::CODE_TARGET);
455}
456
457
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000458#undef __
ager@chromium.org65dad4b2009-04-23 08:48:43 +0000459#define __ ACCESS_MASM(masm())
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000460
461
462Object* StubCompiler::CompileLazyCompile(Code::Flags flags) {
kasperl@chromium.orgb9123622008-09-17 14:05:56 +0000463 // ----------- S t a t e -------------
464 // -- r1: function
465 // -- lr: return address
466 // -----------------------------------
467
kasperl@chromium.orgb9123622008-09-17 14:05:56 +0000468 // Enter an internal frame.
469 __ EnterInternalFrame();
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000470
kasperl@chromium.orgb9123622008-09-17 14:05:56 +0000471 // Preserve the function.
472 __ push(r1);
473
474 // Push the function on the stack as the argument to the runtime function.
475 __ push(r1);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000476 __ CallRuntime(Runtime::kLazyCompile, 1);
477
kasperl@chromium.orgb9123622008-09-17 14:05:56 +0000478 // Calculate the entry point.
479 __ add(r2, r0, Operand(Code::kHeaderSize - kHeapObjectTag));
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000480
kasperl@chromium.orgb9123622008-09-17 14:05:56 +0000481 // Restore saved function.
482 __ pop(r1);
483
484 // Tear down temporary frame.
ager@chromium.org236ad962008-09-25 09:45:57 +0000485 __ LeaveInternalFrame();
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000486
487 // Do a tail-call of the compiled function.
kasperl@chromium.orgb9123622008-09-17 14:05:56 +0000488 __ Jump(r2);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000489
kasperl@chromium.org7be3c992009-03-12 07:19:55 +0000490 return GetCodeWithFlags(flags, "LazyCompileStub");
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000491}
492
493
494Object* CallStubCompiler::CompileCallField(Object* object,
495 JSObject* holder,
kasperl@chromium.org7be3c992009-03-12 07:19:55 +0000496 int index,
497 String* name) {
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000498 // ----------- S t a t e -------------
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000499 // -- lr: return address
500 // -----------------------------------
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000501 Label miss;
502
mads.s.ager31e71382008-08-13 09:32:07 +0000503 const int argc = arguments().immediate();
504
kasperl@chromium.org9fe21c62008-10-28 08:53:51 +0000505 // Get the receiver of the function from the stack into r0.
506 __ ldr(r0, MemOperand(sp, argc * kPointerSize));
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000507 // Check that the receiver isn't a smi.
kasperl@chromium.org9fe21c62008-10-28 08:53:51 +0000508 __ tst(r0, Operand(kSmiTagMask));
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000509 __ b(eq, &miss);
510
511 // Do the right check and compute the holder register.
512 Register reg =
ager@chromium.org65dad4b2009-04-23 08:48:43 +0000513 masm()->CheckMaps(JSObject::cast(object), r0, holder, r3, r2, &miss);
ager@chromium.org7c537e22008-10-16 08:43:32 +0000514 GenerateFastPropertyLoad(masm(), r1, reg, holder, index);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000515
516 // Check that the function really is a function.
kasperl@chromium.orgb9123622008-09-17 14:05:56 +0000517 __ tst(r1, Operand(kSmiTagMask));
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000518 __ b(eq, &miss);
519 // Get the map.
kasperl@chromium.orgb9123622008-09-17 14:05:56 +0000520 __ ldr(r2, FieldMemOperand(r1, HeapObject::kMapOffset));
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000521 __ ldrb(r2, FieldMemOperand(r2, Map::kInstanceTypeOffset));
522 __ cmp(r2, Operand(JS_FUNCTION_TYPE));
523 __ b(ne, &miss);
524
kasperl@chromium.org9fe21c62008-10-28 08:53:51 +0000525 // Patch the receiver on the stack with the global proxy if
526 // necessary.
527 if (object->IsGlobalObject()) {
528 __ ldr(r3, FieldMemOperand(r0, GlobalObject::kGlobalReceiverOffset));
529 __ str(r3, MemOperand(sp, argc * kPointerSize));
530 }
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000531
kasperl@chromium.orgb9123622008-09-17 14:05:56 +0000532 // Invoke the function.
533 __ InvokeFunction(r1, arguments(), JUMP_FUNCTION);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000534
535 // Handle call cache miss.
536 __ bind(&miss);
537 Handle<Code> ic = ComputeCallMiss(arguments().immediate());
ager@chromium.org236ad962008-09-25 09:45:57 +0000538 __ Jump(ic, RelocInfo::CODE_TARGET);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000539
540 // Return the generated code.
kasperl@chromium.org7be3c992009-03-12 07:19:55 +0000541 return GetCode(FIELD, name);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000542}
543
544
545Object* CallStubCompiler::CompileCallConstant(Object* object,
546 JSObject* holder,
547 JSFunction* function,
548 CheckType check) {
549 // ----------- S t a t e -------------
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000550 // -- lr: return address
551 // -----------------------------------
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000552 Label miss;
553
mads.s.ager31e71382008-08-13 09:32:07 +0000554 // Get the receiver from the stack
555 const int argc = arguments().immediate();
556 __ ldr(r1, MemOperand(sp, argc * kPointerSize));
557
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000558 // Check that the receiver isn't a smi.
559 if (check != NUMBER_CHECK) {
560 __ tst(r1, Operand(kSmiTagMask));
561 __ b(eq, &miss);
562 }
563
kasperl@chromium.org9fe21c62008-10-28 08:53:51 +0000564 // Make sure that it's okay not to patch the on stack receiver
565 // unless we're doing a receiver map check.
566 ASSERT(!object->IsGlobalObject() || check == RECEIVER_MAP_CHECK);
567
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000568 switch (check) {
569 case RECEIVER_MAP_CHECK:
570 // Check that the maps haven't changed.
571 __ CheckMaps(JSObject::cast(object), r1, holder, r3, r2, &miss);
kasperl@chromium.org9fe21c62008-10-28 08:53:51 +0000572
573 // Patch the receiver on the stack with the global proxy if
574 // necessary.
575 if (object->IsGlobalObject()) {
576 __ ldr(r3, FieldMemOperand(r1, GlobalObject::kGlobalReceiverOffset));
577 __ str(r3, MemOperand(sp, argc * kPointerSize));
578 }
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000579 break;
580
581 case STRING_CHECK:
582 // Check that the object is a two-byte string or a symbol.
583 __ ldr(r2, FieldMemOperand(r1, HeapObject::kMapOffset));
584 __ ldrb(r2, FieldMemOperand(r2, Map::kInstanceTypeOffset));
585 __ cmp(r2, Operand(FIRST_NONSTRING_TYPE));
586 __ b(hs, &miss);
587 // Check that the maps starting from the prototype haven't changed.
588 GenerateLoadGlobalFunctionPrototype(masm(),
589 Context::STRING_FUNCTION_INDEX,
590 r2);
591 __ CheckMaps(JSObject::cast(object->GetPrototype()),
592 r2, holder, r3, r1, &miss);
593 break;
594
595 case NUMBER_CHECK: {
596 Label fast;
597 // Check that the object is a smi or a heap number.
598 __ tst(r1, Operand(kSmiTagMask));
599 __ b(eq, &fast);
600 __ ldr(r2, FieldMemOperand(r1, HeapObject::kMapOffset));
601 __ ldrb(r2, FieldMemOperand(r2, Map::kInstanceTypeOffset));
602 __ cmp(r2, Operand(HEAP_NUMBER_TYPE));
603 __ b(ne, &miss);
604 __ bind(&fast);
605 // Check that the maps starting from the prototype haven't changed.
606 GenerateLoadGlobalFunctionPrototype(masm(),
607 Context::NUMBER_FUNCTION_INDEX,
608 r2);
609 __ CheckMaps(JSObject::cast(object->GetPrototype()),
610 r2, holder, r3, r1, &miss);
611 break;
612 }
613
614 case BOOLEAN_CHECK: {
615 Label fast;
616 // Check that the object is a boolean.
617 __ cmp(r1, Operand(Factory::true_value()));
618 __ b(eq, &fast);
619 __ cmp(r1, Operand(Factory::false_value()));
620 __ b(ne, &miss);
621 __ bind(&fast);
622 // Check that the maps starting from the prototype haven't changed.
623 GenerateLoadGlobalFunctionPrototype(masm(),
624 Context::BOOLEAN_FUNCTION_INDEX,
625 r2);
626 __ CheckMaps(JSObject::cast(object->GetPrototype()),
627 r2, holder, r3, r1, &miss);
628 break;
629 }
630
631 case JSARRAY_HAS_FAST_ELEMENTS_CHECK:
632 __ CheckMaps(JSObject::cast(object), r1, holder, r3, r2, &miss);
633 // Make sure object->elements()->map() != Heap::hash_table_map()
634 // Get the elements array of the object.
635 __ ldr(r3, FieldMemOperand(r1, JSObject::kElementsOffset));
636 // Check that the object is in fast mode (not dictionary).
637 __ ldr(r2, FieldMemOperand(r3, HeapObject::kMapOffset));
638 __ cmp(r2, Operand(Factory::hash_table_map()));
639 __ b(eq, &miss);
640 break;
641
642 default:
643 UNREACHABLE();
644 }
645
646 // Get the function and setup the context.
kasperl@chromium.orgb9123622008-09-17 14:05:56 +0000647 __ mov(r1, Operand(Handle<JSFunction>(function)));
648 __ ldr(cp, FieldMemOperand(r1, JSFunction::kContextOffset));
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000649
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000650 // Jump to the cached code (tail call).
651 Handle<Code> code(function->code());
mads.s.ager@gmail.com769cc962008-08-06 10:02:49 +0000652 ParameterCount expected(function->shared()->formal_parameter_count());
ager@chromium.org236ad962008-09-25 09:45:57 +0000653 __ InvokeCode(code, expected, arguments(),
654 RelocInfo::CODE_TARGET, JUMP_FUNCTION);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000655
656 // Handle call cache miss.
657 __ bind(&miss);
658 Handle<Code> ic = ComputeCallMiss(arguments().immediate());
ager@chromium.org236ad962008-09-25 09:45:57 +0000659 __ Jump(ic, RelocInfo::CODE_TARGET);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000660
661 // Return the generated code.
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 }
666 return GetCode(CONSTANT_FUNCTION, 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.org3bf7b912008-11-17 09:09:45 +0000907 GenerateLoadInterceptor(masm(), object, holder, r0, r2, r3, r1, &miss);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000908 __ bind(&miss);
ager@chromium.org3bf7b912008-11-17 09:09:45 +0000909 GenerateLoadMiss(masm(), Code::LOAD_IC);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000910
911 // Return the generated code.
kasperl@chromium.org7be3c992009-03-12 07:19:55 +0000912 return GetCode(INTERCEPTOR, name);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000913}
914
915
916// TODO(1224671): IC stubs for keyed loads have not been implemented
917// for ARM.
918Object* KeyedLoadStubCompiler::CompileLoadField(String* name,
919 JSObject* receiver,
920 JSObject* holder,
921 int index) {
ager@chromium.org3bf7b912008-11-17 09:09:45 +0000922 // ----------- S t a t e -------------
923 // -- lr : return address
924 // -- sp[0] : key
925 // -- sp[4] : receiver
926 // -----------------------------------
ager@chromium.org3bf7b912008-11-17 09:09:45 +0000927 Label miss;
928
929 __ ldr(r2, MemOperand(sp, 0));
930 __ ldr(r0, MemOperand(sp, kPointerSize));
931
932 __ cmp(r2, Operand(Handle<String>(name)));
933 __ b(ne, &miss);
934
935 GenerateLoadField(masm(), receiver, holder, r0, r3, r1, index, &miss);
936 __ bind(&miss);
937 GenerateLoadMiss(masm(), Code::KEYED_LOAD_IC);
938
kasperl@chromium.org7be3c992009-03-12 07:19:55 +0000939 return GetCode(FIELD, name);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000940}
941
942
943Object* KeyedLoadStubCompiler::CompileLoadCallback(String* name,
944 JSObject* receiver,
945 JSObject* holder,
946 AccessorInfo* callback) {
ager@chromium.org3bf7b912008-11-17 09:09:45 +0000947 // ----------- S t a t e -------------
948 // -- lr : return address
949 // -- sp[0] : key
950 // -- sp[4] : receiver
951 // -----------------------------------
ager@chromium.org3bf7b912008-11-17 09:09:45 +0000952 Label miss;
953
954 __ ldr(r2, MemOperand(sp, 0));
955 __ ldr(r0, MemOperand(sp, kPointerSize));
956
957 __ cmp(r2, Operand(Handle<String>(name)));
958 __ b(ne, &miss);
959
960 GenerateLoadCallback(masm(), receiver, holder, r0, r2, r3,
961 r1, callback, &miss);
962 __ bind(&miss);
963 GenerateLoadMiss(masm(), Code::KEYED_LOAD_IC);
964
kasperl@chromium.org7be3c992009-03-12 07:19:55 +0000965 return GetCode(CALLBACKS, name);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000966}
967
968
969Object* KeyedLoadStubCompiler::CompileLoadConstant(String* name,
970 JSObject* receiver,
971 JSObject* holder,
972 Object* value) {
ager@chromium.org3bf7b912008-11-17 09:09:45 +0000973 // ----------- S t a t e -------------
974 // -- lr : return address
975 // -- sp[0] : key
976 // -- sp[4] : receiver
977 // -----------------------------------
ager@chromium.org3bf7b912008-11-17 09:09:45 +0000978 Label miss;
979
980 // Check the key is the cached one
981 __ ldr(r2, MemOperand(sp, 0));
982 __ ldr(r0, MemOperand(sp, kPointerSize));
983
984 __ cmp(r2, Operand(Handle<String>(name)));
985 __ b(ne, &miss);
986
987 GenerateLoadConstant(masm(), receiver, holder, r0, r3, r1, value, &miss);
988 __ bind(&miss);
989 GenerateLoadMiss(masm(), Code::KEYED_LOAD_IC);
990
991 // Return the generated code.
kasperl@chromium.org7be3c992009-03-12 07:19:55 +0000992 return GetCode(CONSTANT_FUNCTION, name);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000993}
994
995
996Object* KeyedLoadStubCompiler::CompileLoadInterceptor(JSObject* receiver,
997 JSObject* holder,
998 String* name) {
ager@chromium.org3bf7b912008-11-17 09:09:45 +0000999 // ----------- S t a t e -------------
1000 // -- lr : return address
1001 // -- sp[0] : key
1002 // -- sp[4] : receiver
1003 // -----------------------------------
ager@chromium.org3bf7b912008-11-17 09:09:45 +00001004 Label miss;
1005
1006 // Check the key is the cached one
1007 __ ldr(r2, MemOperand(sp, 0));
1008 __ ldr(r0, MemOperand(sp, kPointerSize));
1009
1010 __ cmp(r2, Operand(Handle<String>(name)));
1011 __ b(ne, &miss);
1012
1013 GenerateLoadInterceptor(masm(), receiver, holder, r0, r2, r3, r1, &miss);
1014 __ bind(&miss);
1015 GenerateLoadMiss(masm(), Code::KEYED_LOAD_IC);
1016
kasperl@chromium.org7be3c992009-03-12 07:19:55 +00001017 return GetCode(INTERCEPTOR, name);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001018}
1019
1020
1021Object* KeyedLoadStubCompiler::CompileLoadArrayLength(String* name) {
ager@chromium.org3bf7b912008-11-17 09:09:45 +00001022 // ----------- S t a t e -------------
1023 // -- lr : return address
1024 // -- sp[0] : key
1025 // -- sp[4] : receiver
1026 // -----------------------------------
ager@chromium.org3bf7b912008-11-17 09:09:45 +00001027 Label miss;
1028
1029 // Check the key is the cached one
1030 __ ldr(r2, MemOperand(sp, 0));
1031 __ ldr(r0, MemOperand(sp, kPointerSize));
1032
1033 __ cmp(r2, Operand(Handle<String>(name)));
1034 __ b(ne, &miss);
1035
1036 GenerateLoadArrayLength(masm(), r0, r3, &miss);
1037 __ bind(&miss);
1038 GenerateLoadMiss(masm(), Code::KEYED_LOAD_IC);
1039
kasperl@chromium.org7be3c992009-03-12 07:19:55 +00001040 return GetCode(CALLBACKS, name);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001041}
1042
1043
kasperl@chromium.org9fe21c62008-10-28 08:53:51 +00001044Object* KeyedLoadStubCompiler::CompileLoadStringLength(String* name) {
ager@chromium.org3bf7b912008-11-17 09:09:45 +00001045 // ----------- S t a t e -------------
1046 // -- lr : return address
1047 // -- sp[0] : key
1048 // -- sp[4] : receiver
1049 // -----------------------------------
ager@chromium.orga74f0da2008-12-03 16:05:52 +00001050 Label miss;
1051 __ IncrementCounter(&Counters::keyed_load_string_length, 1, r1, r3);
1052
1053 __ ldr(r2, MemOperand(sp));
1054 __ ldr(r0, MemOperand(sp, kPointerSize)); // receiver
1055
1056 __ cmp(r2, Operand(Handle<String>(name)));
1057 __ b(ne, &miss);
1058
1059 GenerateLoadStringLength2(masm(), r0, r1, r3, &miss);
1060 __ bind(&miss);
1061 __ DecrementCounter(&Counters::keyed_load_string_length, 1, r1, r3);
1062
ager@chromium.org3bf7b912008-11-17 09:09:45 +00001063 GenerateLoadMiss(masm(), Code::KEYED_LOAD_IC);
1064
kasperl@chromium.org7be3c992009-03-12 07:19:55 +00001065 return GetCode(CALLBACKS, name);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001066}
1067
1068
ager@chromium.org3bf7b912008-11-17 09:09:45 +00001069// TODO(1224671): implement the fast case.
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001070Object* KeyedLoadStubCompiler::CompileLoadFunctionPrototype(String* name) {
ager@chromium.org3bf7b912008-11-17 09:09:45 +00001071 // ----------- S t a t e -------------
1072 // -- lr : return address
1073 // -- sp[0] : key
1074 // -- sp[4] : receiver
1075 // -----------------------------------
ager@chromium.org3bf7b912008-11-17 09:09:45 +00001076 GenerateLoadMiss(masm(), Code::KEYED_LOAD_IC);
1077
kasperl@chromium.org7be3c992009-03-12 07:19:55 +00001078 return GetCode(CALLBACKS, name);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001079}
1080
1081
1082Object* KeyedStoreStubCompiler::CompileStoreField(JSObject* object,
1083 int index,
1084 Map* transition,
1085 String* name) {
ager@chromium.org3bf7b912008-11-17 09:09:45 +00001086 // ----------- S t a t e -------------
1087 // -- r0 : value
1088 // -- r2 : name
1089 // -- lr : return address
1090 // -- [sp] : receiver
1091 // -----------------------------------
ager@chromium.orga74f0da2008-12-03 16:05:52 +00001092 Label miss;
1093
1094 __ IncrementCounter(&Counters::keyed_store_field, 1, r1, r3);
1095
1096 // Check that the name has not changed.
1097 __ cmp(r2, Operand(Handle<String>(name)));
1098 __ b(ne, &miss);
1099
1100 // Load receiver from the stack.
1101 __ ldr(r3, MemOperand(sp));
1102 // r1 is used as scratch register, r3 and r2 might be clobbered.
1103 GenerateStoreField(masm(),
1104 Builtins::StoreIC_ExtendStorage,
1105 object,
1106 index,
1107 transition,
1108 r3, r2, r1,
1109 &miss);
1110 __ bind(&miss);
1111
1112 __ DecrementCounter(&Counters::keyed_store_field, 1, r1, r3);
1113 __ mov(r2, Operand(Handle<String>(name))); // restore name register.
ager@chromium.org3bf7b912008-11-17 09:09:45 +00001114 Handle<Code> ic(Builtins::builtin(Builtins::KeyedStoreIC_Miss));
1115 __ Jump(ic, RelocInfo::CODE_TARGET);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001116
ager@chromium.org3bf7b912008-11-17 09:09:45 +00001117 // Return the generated code.
kasperl@chromium.org7be3c992009-03-12 07:19:55 +00001118 return GetCode(transition == NULL ? FIELD : MAP_TRANSITION, name);
ager@chromium.org3bf7b912008-11-17 09:09:45 +00001119}
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001120
1121
1122#undef __
1123
1124} } // namespace v8::internal