blob: c09f9e3b6082e12ad676c944e785d9a1df78857b [file] [log] [blame]
kasperl@chromium.org71affb52009-05-26 05:44:31 +00001// Copyright 2006-2009 the V8 project authors. All rights reserved.
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002// Redistribution and use in source and binary forms, with or without
3// modification, are permitted provided that the following conditions are
4// met:
5//
6// * Redistributions of source code must retain the above copyright
7// notice, this list of conditions and the following disclaimer.
8// * Redistributions in binary form must reproduce the above
9// copyright notice, this list of conditions and the following
10// disclaimer in the documentation and/or other materials provided
11// with the distribution.
12// * Neither the name of Google Inc. nor the names of its
13// contributors may be used to endorse or promote products derived
14// from this software without specific prior written permission.
15//
16// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
17// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
18// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
19// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
20// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
21// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
22// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
23// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
24// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
25// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
26// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27
28#include "v8.h"
29
30#include "ic-inl.h"
31#include "codegen-inl.h"
32#include "stub-cache.h"
33
kasperl@chromium.org71affb52009-05-26 05:44:31 +000034namespace v8 {
35namespace internal {
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +000036
ager@chromium.org65dad4b2009-04-23 08:48:43 +000037#define __ ACCESS_MASM(masm)
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +000038
39
40static void ProbeTable(MacroAssembler* masm,
41 Code::Flags flags,
42 StubCache::Table table,
43 Register name,
44 Register offset) {
45 ExternalReference key_offset(SCTableReference::keyReference(table));
46 ExternalReference value_offset(SCTableReference::valueReference(table));
47
48 Label miss;
49
50 // Save the offset on the stack.
51 __ push(offset);
52
53 // Check that the key in the entry matches the name.
54 __ mov(ip, Operand(key_offset));
55 __ ldr(ip, MemOperand(ip, offset, LSL, 1));
56 __ cmp(name, Operand(ip));
57 __ b(ne, &miss);
58
59 // Get the code entry from the cache.
60 __ mov(ip, Operand(value_offset));
61 __ ldr(offset, MemOperand(ip, offset, LSL, 1));
62
63 // Check that the flags match what we're looking for.
64 __ ldr(offset, FieldMemOperand(offset, Code::kFlagsOffset));
kasperl@chromium.org71affb52009-05-26 05:44:31 +000065 __ and_(offset, offset, Operand(~Code::kFlagsNotUsedInLookup));
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +000066 __ cmp(offset, Operand(flags));
67 __ b(ne, &miss);
68
69 // Restore offset and re-load code entry from cache.
70 __ pop(offset);
71 __ mov(ip, Operand(value_offset));
72 __ ldr(offset, MemOperand(ip, offset, LSL, 1));
73
74 // Jump to the first instruction in the code stub.
75 __ add(offset, offset, Operand(Code::kHeaderSize - kHeapObjectTag));
76 __ Jump(offset);
77
78 // Miss: Restore offset and fall through.
79 __ bind(&miss);
80 __ pop(offset);
81}
82
83
84void StubCache::GenerateProbe(MacroAssembler* masm,
85 Code::Flags flags,
86 Register receiver,
87 Register name,
88 Register scratch) {
89 Label miss;
90
91 // Make sure that code is valid. The shifting code relies on the
92 // entry size being 8.
93 ASSERT(sizeof(Entry) == 8);
94
95 // Make sure the flags does not name a specific type.
96 ASSERT(Code::ExtractTypeFromFlags(flags) == 0);
97
98 // Make sure that there are no register conflicts.
99 ASSERT(!scratch.is(receiver));
100 ASSERT(!scratch.is(name));
101
102 // Check that the receiver isn't a smi.
103 __ tst(receiver, Operand(kSmiTagMask));
104 __ b(eq, &miss);
105
106 // Get the map of the receiver and compute the hash.
ager@chromium.org7c537e22008-10-16 08:43:32 +0000107 __ ldr(scratch, FieldMemOperand(name, String::kLengthOffset));
108 __ ldr(ip, FieldMemOperand(receiver, HeapObject::kMapOffset));
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000109 __ add(scratch, scratch, Operand(ip));
110 __ eor(scratch, scratch, Operand(flags));
111 __ and_(scratch,
112 scratch,
113 Operand((kPrimaryTableSize - 1) << kHeapObjectTagSize));
114
115 // Probe the primary table.
116 ProbeTable(masm, flags, kPrimary, name, scratch);
117
118 // Primary miss: Compute hash for secondary probe.
119 __ sub(scratch, scratch, Operand(name));
120 __ add(scratch, scratch, Operand(flags));
121 __ and_(scratch,
122 scratch,
123 Operand((kSecondaryTableSize - 1) << kHeapObjectTagSize));
124
125 // Probe the secondary table.
126 ProbeTable(masm, flags, kSecondary, name, scratch);
127
128 // Cache miss: Fall-through and let caller handle the miss by
129 // entering the runtime system.
130 __ bind(&miss);
131}
132
133
134void StubCompiler::GenerateLoadGlobalFunctionPrototype(MacroAssembler* masm,
135 int index,
136 Register prototype) {
137 // Load the global or builtins object from the current context.
138 __ ldr(prototype, MemOperand(cp, Context::SlotOffset(Context::GLOBAL_INDEX)));
139 // Load the global context from the global or builtins object.
140 __ ldr(prototype,
141 FieldMemOperand(prototype, GlobalObject::kGlobalContextOffset));
142 // Load the function from the global context.
143 __ ldr(prototype, MemOperand(prototype, Context::SlotOffset(index)));
144 // Load the initial map. The global functions all have initial maps.
145 __ ldr(prototype,
146 FieldMemOperand(prototype, JSFunction::kPrototypeOrInitialMapOffset));
147 // Load the prototype from the initial map.
148 __ ldr(prototype, FieldMemOperand(prototype, Map::kPrototypeOffset));
149}
150
151
ager@chromium.org7c537e22008-10-16 08:43:32 +0000152// Load a fast property out of a holder object (src). In-object properties
153// are loaded directly otherwise the property is loaded from the properties
154// fixed array.
155void StubCompiler::GenerateFastPropertyLoad(MacroAssembler* masm,
156 Register dst, Register src,
157 JSObject* holder, int index) {
158 // Adjust for the number of properties stored in the holder.
159 index -= holder->map()->inobject_properties();
160 if (index < 0) {
161 // Get the property straight out of the holder.
162 int offset = holder->map()->instance_size() + (index * kPointerSize);
163 __ ldr(dst, FieldMemOperand(src, offset));
164 } else {
165 // Calculate the offset into the properties array.
166 int offset = index * kPointerSize + Array::kHeaderSize;
167 __ ldr(dst, FieldMemOperand(src, JSObject::kPropertiesOffset));
168 __ ldr(dst, FieldMemOperand(dst, offset));
169 }
170}
171
172
ager@chromium.org3bf7b912008-11-17 09:09:45 +0000173void StubCompiler::GenerateLoadField(MacroAssembler* masm,
174 JSObject* object,
175 JSObject* holder,
176 Register receiver,
177 Register scratch1,
178 Register scratch2,
179 int index,
180 Label* miss_label) {
181 // Check that the receiver isn't a smi.
182 __ tst(receiver, Operand(kSmiTagMask));
183 __ b(eq, miss_label);
184
185 // Check that the maps haven't changed.
186 Register reg =
ager@chromium.org65dad4b2009-04-23 08:48:43 +0000187 masm->CheckMaps(object, receiver, holder, scratch1, scratch2, miss_label);
ager@chromium.org3bf7b912008-11-17 09:09:45 +0000188 GenerateFastPropertyLoad(masm, r0, reg, holder, index);
189 __ Ret();
190}
191
192
193void StubCompiler::GenerateLoadConstant(MacroAssembler* masm,
194 JSObject* object,
195 JSObject* holder,
196 Register receiver,
197 Register scratch1,
198 Register scratch2,
199 Object* value,
200 Label* miss_label) {
201 // Check that the receiver isn't a smi.
202 __ tst(receiver, Operand(kSmiTagMask));
203 __ b(eq, miss_label);
204
205 // Check that the maps haven't changed.
206 Register reg =
ager@chromium.org65dad4b2009-04-23 08:48:43 +0000207 masm->CheckMaps(object, receiver, holder, scratch1, scratch2, miss_label);
ager@chromium.org3bf7b912008-11-17 09:09:45 +0000208
209 // Return the constant value.
210 __ mov(r0, Operand(Handle<Object>(value)));
211 __ Ret();
212}
213
214
215void StubCompiler::GenerateLoadCallback(MacroAssembler* masm,
216 JSObject* object,
217 JSObject* holder,
218 Register receiver,
219 Register name,
220 Register scratch1,
221 Register scratch2,
222 AccessorInfo* callback,
223 Label* miss_label) {
224 // Check that the receiver isn't a smi.
225 __ tst(receiver, Operand(kSmiTagMask));
226 __ b(eq, miss_label);
227
228 // Check that the maps haven't changed.
229 Register reg =
ager@chromium.org65dad4b2009-04-23 08:48:43 +0000230 masm->CheckMaps(object, receiver, holder, scratch1, scratch2, miss_label);
ager@chromium.org3bf7b912008-11-17 09:09:45 +0000231
232 // Push the arguments on the JS stack of the caller.
233 __ push(receiver); // receiver
234 __ mov(ip, Operand(Handle<AccessorInfo>(callback))); // callback data
235 __ push(ip);
236 __ push(name); // name
237 __ push(reg); // holder
238
239 // Do tail-call to the runtime system.
240 ExternalReference load_callback_property =
241 ExternalReference(IC_Utility(IC::kLoadCallbackProperty));
242 __ TailCallRuntime(load_callback_property, 4);
243}
244
245
246void StubCompiler::GenerateLoadInterceptor(MacroAssembler* masm,
247 JSObject* object,
248 JSObject* holder,
ager@chromium.orge2902be2009-06-08 12:21:35 +0000249 Smi* lookup_hint,
ager@chromium.org3bf7b912008-11-17 09:09:45 +0000250 Register receiver,
251 Register name,
252 Register scratch1,
253 Register scratch2,
254 Label* miss_label) {
255 // Check that the receiver isn't a smi.
256 __ tst(receiver, Operand(kSmiTagMask));
257 __ b(eq, miss_label);
258
259 // Check that the maps haven't changed.
260 Register reg =
ager@chromium.org65dad4b2009-04-23 08:48:43 +0000261 masm->CheckMaps(object, receiver, holder, scratch1, scratch2, miss_label);
ager@chromium.org3bf7b912008-11-17 09:09:45 +0000262
263 // Push the arguments on the JS stack of the caller.
264 __ push(receiver); // receiver
265 __ push(reg); // holder
266 __ push(name); // name
ager@chromium.orge2902be2009-06-08 12:21:35 +0000267 __ mov(scratch1, Operand(lookup_hint));
268 __ push(scratch1);
ager@chromium.org3bf7b912008-11-17 09:09:45 +0000269
270 // Do tail-call to the runtime system.
271 ExternalReference load_ic_property =
272 ExternalReference(IC_Utility(IC::kLoadInterceptorProperty));
ager@chromium.orge2902be2009-06-08 12:21:35 +0000273 __ TailCallRuntime(load_ic_property, 4);
ager@chromium.org3bf7b912008-11-17 09:09:45 +0000274}
275
276
277void StubCompiler::GenerateLoadArrayLength(MacroAssembler* masm,
278 Register receiver,
279 Register scratch,
280 Label* miss_label) {
281 // Check that the receiver isn't a smi.
282 __ tst(receiver, Operand(kSmiTagMask));
283 __ b(eq, miss_label);
284
285 // Check that the object is a JS array.
286 __ ldr(scratch, FieldMemOperand(receiver, HeapObject::kMapOffset));
287 __ ldrb(scratch, FieldMemOperand(scratch, Map::kInstanceTypeOffset));
288 __ cmp(scratch, Operand(JS_ARRAY_TYPE));
289 __ b(ne, miss_label);
290
291 // Load length directly from the JS array.
292 __ ldr(r0, FieldMemOperand(receiver, JSArray::kLengthOffset));
293 __ Ret();
294}
295
296
ager@chromium.orga74f0da2008-12-03 16:05:52 +0000297// Generate code to check if an object is a string. If the object is
298// a string, the map's instance type is left in the scratch1 register.
299static void GenerateStringCheck(MacroAssembler* masm,
300 Register receiver,
301 Register scratch1,
302 Register scratch2,
303 Label* smi,
304 Label* non_string_object) {
305 // Check that the receiver isn't a smi.
306 __ tst(receiver, Operand(kSmiTagMask));
307 __ b(eq, smi);
308
309 // Check that the object is a string.
310 __ ldr(scratch1, FieldMemOperand(receiver, HeapObject::kMapOffset));
311 __ ldrb(scratch1, FieldMemOperand(scratch1, Map::kInstanceTypeOffset));
312 __ and_(scratch2, scratch1, Operand(kIsNotStringMask));
313 // The cast is to resolve the overload for the argument of 0x0.
314 __ cmp(scratch2, Operand(static_cast<int32_t>(kStringTag)));
315 __ b(ne, non_string_object);
316}
317
318
ager@chromium.org32912102009-01-16 10:38:43 +0000319// Generate code to load the length from a string object and return the length.
320// If the receiver object is not a string or a wrapped string object the
321// execution continues at the miss label. The register containing the
322// receiver is potentially clobbered.
ager@chromium.orga74f0da2008-12-03 16:05:52 +0000323void StubCompiler::GenerateLoadStringLength2(MacroAssembler* masm,
324 Register receiver,
325 Register scratch1,
326 Register scratch2,
327 Label* miss) {
ager@chromium.org32912102009-01-16 10:38:43 +0000328 Label check_string, check_wrapper;
ager@chromium.orga74f0da2008-12-03 16:05:52 +0000329
ager@chromium.org32912102009-01-16 10:38:43 +0000330 __ bind(&check_string);
ager@chromium.orga74f0da2008-12-03 16:05:52 +0000331 // Check if the object is a string leaving the instance type in the
332 // scratch1 register.
333 GenerateStringCheck(masm, receiver, scratch1, scratch2,
334 miss, &check_wrapper);
335
336 // Load length directly from the string.
ager@chromium.orga74f0da2008-12-03 16:05:52 +0000337 __ and_(scratch1, scratch1, Operand(kStringSizeMask));
338 __ add(scratch1, scratch1, Operand(String::kHashShift));
339 __ ldr(r0, FieldMemOperand(receiver, String::kLengthOffset));
340 __ mov(r0, Operand(r0, LSR, scratch1));
341 __ mov(r0, Operand(r0, LSL, kSmiTagSize));
342 __ Ret();
343
344 // Check if the object is a JSValue wrapper.
345 __ bind(&check_wrapper);
346 __ cmp(scratch1, Operand(JS_VALUE_TYPE));
347 __ b(ne, miss);
348
ager@chromium.org32912102009-01-16 10:38:43 +0000349 // Unwrap the value in place and check if the wrapped value is a string.
350 __ ldr(receiver, FieldMemOperand(receiver, JSValue::kValueOffset));
351 __ b(&check_string);
ager@chromium.orga74f0da2008-12-03 16:05:52 +0000352}
353
354
355// Generate StoreField code, value is passed in r0 register.
356// After executing generated code, the receiver_reg and name_reg
357// may be clobbered.
358void StubCompiler::GenerateStoreField(MacroAssembler* masm,
359 Builtins::Name storage_extend,
360 JSObject* object,
361 int index,
362 Map* transition,
363 Register receiver_reg,
364 Register name_reg,
365 Register scratch,
366 Label* miss_label) {
367 // r0 : value
368 Label exit;
369
370 // Check that the receiver isn't a smi.
371 __ tst(receiver_reg, Operand(kSmiTagMask));
372 __ b(eq, miss_label);
373
374 // Check that the map of the receiver hasn't changed.
375 __ ldr(scratch, FieldMemOperand(receiver_reg, HeapObject::kMapOffset));
376 __ cmp(scratch, Operand(Handle<Map>(object->map())));
377 __ b(ne, miss_label);
378
379 // Perform global security token check if needed.
380 if (object->IsJSGlobalProxy()) {
381 __ CheckAccessGlobalProxy(receiver_reg, scratch, miss_label);
382 }
383
384 // Stub never generated for non-global objects that require access
385 // checks.
386 ASSERT(object->IsJSGlobalProxy() || !object->IsAccessCheckNeeded());
387
388 // Perform map transition for the receiver if necessary.
389 if ((transition != NULL) && (object->map()->unused_property_fields() == 0)) {
390 // The properties must be extended before we can store the value.
ager@chromium.org32912102009-01-16 10:38:43 +0000391 // We jump to a runtime call that extends the properties array.
ager@chromium.orga74f0da2008-12-03 16:05:52 +0000392 __ mov(r2, Operand(Handle<Map>(transition)));
393 // Please note, if we implement keyed store for arm we need
394 // to call the Builtins::KeyedStoreIC_ExtendStorage.
395 Handle<Code> ic(Builtins::builtin(Builtins::StoreIC_ExtendStorage));
396 __ Jump(ic, RelocInfo::CODE_TARGET);
397 return;
398 }
399
400 if (transition != NULL) {
401 // Update the map of the object; no write barrier updating is
402 // needed because the map is never in new space.
403 __ mov(ip, Operand(Handle<Map>(transition)));
404 __ str(ip, FieldMemOperand(receiver_reg, HeapObject::kMapOffset));
405 }
406
407 // Adjust for the number of properties stored in the object. Even in the
408 // face of a transition we can use the old map here because the size of the
409 // object and the number of in-object properties is not going to change.
410 index -= object->map()->inobject_properties();
411
412 if (index < 0) {
413 // Set the property straight into the object.
414 int offset = object->map()->instance_size() + (index * kPointerSize);
415 __ str(r0, FieldMemOperand(receiver_reg, offset));
416
417 // Skip updating write barrier if storing a smi.
418 __ tst(r0, Operand(kSmiTagMask));
419 __ b(eq, &exit);
420
421 // Update the write barrier for the array address.
422 // Pass the value being stored in the now unused name_reg.
423 __ mov(name_reg, Operand(offset));
424 __ RecordWrite(receiver_reg, name_reg, scratch);
425 } else {
426 // Write to the properties array.
427 int offset = index * kPointerSize + Array::kHeaderSize;
428 // Get the properties array
429 __ ldr(scratch, FieldMemOperand(receiver_reg, JSObject::kPropertiesOffset));
430 __ str(r0, FieldMemOperand(scratch, offset));
431
432 // Skip updating write barrier if storing a smi.
433 __ tst(r0, Operand(kSmiTagMask));
434 __ b(eq, &exit);
435
436 // Update the write barrier for the array address.
437 // Ok to clobber receiver_reg and name_reg, since we return.
438 __ mov(name_reg, Operand(offset));
439 __ RecordWrite(scratch, name_reg, receiver_reg);
440 }
441
442 // Return the value (register r0).
443 __ bind(&exit);
444 __ Ret();
445}
446
447
ager@chromium.org3bf7b912008-11-17 09:09:45 +0000448void StubCompiler::GenerateLoadMiss(MacroAssembler* masm, Code::Kind kind) {
449 ASSERT(kind == Code::LOAD_IC || kind == Code::KEYED_LOAD_IC);
450 Code* code = NULL;
451 if (kind == Code::LOAD_IC) {
452 code = Builtins::builtin(Builtins::LoadIC_Miss);
453 } else {
454 code = Builtins::builtin(Builtins::KeyedLoadIC_Miss);
455 }
456
457 Handle<Code> ic(code);
458 __ Jump(ic, RelocInfo::CODE_TARGET);
459}
460
461
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000462#undef __
ager@chromium.org65dad4b2009-04-23 08:48:43 +0000463#define __ ACCESS_MASM(masm())
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000464
465
466Object* StubCompiler::CompileLazyCompile(Code::Flags flags) {
kasperl@chromium.orgb9123622008-09-17 14:05:56 +0000467 // ----------- S t a t e -------------
468 // -- r1: function
469 // -- lr: return address
470 // -----------------------------------
471
kasperl@chromium.orgb9123622008-09-17 14:05:56 +0000472 // Enter an internal frame.
473 __ EnterInternalFrame();
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000474
kasperl@chromium.orgb9123622008-09-17 14:05:56 +0000475 // Preserve the function.
476 __ push(r1);
477
478 // Push the function on the stack as the argument to the runtime function.
479 __ push(r1);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000480 __ CallRuntime(Runtime::kLazyCompile, 1);
481
kasperl@chromium.orgb9123622008-09-17 14:05:56 +0000482 // Calculate the entry point.
483 __ add(r2, r0, Operand(Code::kHeaderSize - kHeapObjectTag));
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000484
kasperl@chromium.orgb9123622008-09-17 14:05:56 +0000485 // Restore saved function.
486 __ pop(r1);
487
488 // Tear down temporary frame.
ager@chromium.org236ad962008-09-25 09:45:57 +0000489 __ LeaveInternalFrame();
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000490
491 // Do a tail-call of the compiled function.
kasperl@chromium.orgb9123622008-09-17 14:05:56 +0000492 __ Jump(r2);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000493
kasperl@chromium.org7be3c992009-03-12 07:19:55 +0000494 return GetCodeWithFlags(flags, "LazyCompileStub");
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000495}
496
497
498Object* CallStubCompiler::CompileCallField(Object* object,
499 JSObject* holder,
kasperl@chromium.org7be3c992009-03-12 07:19:55 +0000500 int index,
kasperl@chromium.org71affb52009-05-26 05:44:31 +0000501 String* name,
502 Code::Flags flags) {
503 ASSERT_EQ(FIELD, Code::ExtractTypeFromFlags(flags));
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000504 // ----------- S t a t e -------------
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000505 // -- lr: return address
506 // -----------------------------------
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000507 Label miss;
508
mads.s.ager31e71382008-08-13 09:32:07 +0000509 const int argc = arguments().immediate();
510
kasperl@chromium.org9fe21c62008-10-28 08:53:51 +0000511 // Get the receiver of the function from the stack into r0.
512 __ ldr(r0, MemOperand(sp, argc * kPointerSize));
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000513 // Check that the receiver isn't a smi.
kasperl@chromium.org9fe21c62008-10-28 08:53:51 +0000514 __ tst(r0, Operand(kSmiTagMask));
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000515 __ b(eq, &miss);
516
517 // Do the right check and compute the holder register.
518 Register reg =
ager@chromium.org65dad4b2009-04-23 08:48:43 +0000519 masm()->CheckMaps(JSObject::cast(object), r0, holder, r3, r2, &miss);
ager@chromium.org7c537e22008-10-16 08:43:32 +0000520 GenerateFastPropertyLoad(masm(), r1, reg, holder, index);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000521
522 // Check that the function really is a function.
kasperl@chromium.orgb9123622008-09-17 14:05:56 +0000523 __ tst(r1, Operand(kSmiTagMask));
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000524 __ b(eq, &miss);
525 // Get the map.
kasperl@chromium.orgb9123622008-09-17 14:05:56 +0000526 __ ldr(r2, FieldMemOperand(r1, HeapObject::kMapOffset));
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000527 __ ldrb(r2, FieldMemOperand(r2, Map::kInstanceTypeOffset));
528 __ cmp(r2, Operand(JS_FUNCTION_TYPE));
529 __ b(ne, &miss);
530
kasperl@chromium.org9fe21c62008-10-28 08:53:51 +0000531 // Patch the receiver on the stack with the global proxy if
532 // necessary.
533 if (object->IsGlobalObject()) {
534 __ ldr(r3, FieldMemOperand(r0, GlobalObject::kGlobalReceiverOffset));
535 __ str(r3, MemOperand(sp, argc * kPointerSize));
536 }
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000537
kasperl@chromium.orgb9123622008-09-17 14:05:56 +0000538 // Invoke the function.
539 __ InvokeFunction(r1, arguments(), JUMP_FUNCTION);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000540
541 // Handle call cache miss.
542 __ bind(&miss);
543 Handle<Code> ic = ComputeCallMiss(arguments().immediate());
ager@chromium.org236ad962008-09-25 09:45:57 +0000544 __ Jump(ic, RelocInfo::CODE_TARGET);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000545
546 // Return the generated code.
kasperl@chromium.org71affb52009-05-26 05:44:31 +0000547 return GetCodeWithFlags(flags, name);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000548}
549
550
551Object* CallStubCompiler::CompileCallConstant(Object* object,
552 JSObject* holder,
553 JSFunction* function,
kasperl@chromium.org71affb52009-05-26 05:44:31 +0000554 CheckType check,
555 Code::Flags flags) {
556 ASSERT_EQ(CONSTANT_FUNCTION, Code::ExtractTypeFromFlags(flags));
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000557 // ----------- S t a t e -------------
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000558 // -- lr: return address
559 // -----------------------------------
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000560 Label miss;
561
mads.s.ager31e71382008-08-13 09:32:07 +0000562 // Get the receiver from the stack
563 const int argc = arguments().immediate();
564 __ ldr(r1, MemOperand(sp, argc * kPointerSize));
565
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000566 // Check that the receiver isn't a smi.
567 if (check != NUMBER_CHECK) {
568 __ tst(r1, Operand(kSmiTagMask));
569 __ b(eq, &miss);
570 }
571
kasperl@chromium.org9fe21c62008-10-28 08:53:51 +0000572 // Make sure that it's okay not to patch the on stack receiver
573 // unless we're doing a receiver map check.
574 ASSERT(!object->IsGlobalObject() || check == RECEIVER_MAP_CHECK);
575
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000576 switch (check) {
577 case RECEIVER_MAP_CHECK:
578 // Check that the maps haven't changed.
579 __ CheckMaps(JSObject::cast(object), r1, holder, r3, r2, &miss);
kasperl@chromium.org9fe21c62008-10-28 08:53:51 +0000580
581 // Patch the receiver on the stack with the global proxy if
582 // necessary.
583 if (object->IsGlobalObject()) {
584 __ ldr(r3, FieldMemOperand(r1, GlobalObject::kGlobalReceiverOffset));
585 __ str(r3, MemOperand(sp, argc * kPointerSize));
586 }
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000587 break;
588
589 case STRING_CHECK:
590 // Check that the object is a two-byte string or a symbol.
591 __ ldr(r2, FieldMemOperand(r1, HeapObject::kMapOffset));
592 __ ldrb(r2, FieldMemOperand(r2, Map::kInstanceTypeOffset));
593 __ cmp(r2, Operand(FIRST_NONSTRING_TYPE));
594 __ b(hs, &miss);
595 // Check that the maps starting from the prototype haven't changed.
596 GenerateLoadGlobalFunctionPrototype(masm(),
597 Context::STRING_FUNCTION_INDEX,
598 r2);
599 __ CheckMaps(JSObject::cast(object->GetPrototype()),
600 r2, holder, r3, r1, &miss);
601 break;
602
603 case NUMBER_CHECK: {
604 Label fast;
605 // Check that the object is a smi or a heap number.
606 __ tst(r1, Operand(kSmiTagMask));
607 __ b(eq, &fast);
608 __ ldr(r2, FieldMemOperand(r1, HeapObject::kMapOffset));
609 __ ldrb(r2, FieldMemOperand(r2, Map::kInstanceTypeOffset));
610 __ cmp(r2, Operand(HEAP_NUMBER_TYPE));
611 __ b(ne, &miss);
612 __ bind(&fast);
613 // Check that the maps starting from the prototype haven't changed.
614 GenerateLoadGlobalFunctionPrototype(masm(),
615 Context::NUMBER_FUNCTION_INDEX,
616 r2);
617 __ CheckMaps(JSObject::cast(object->GetPrototype()),
618 r2, holder, r3, r1, &miss);
619 break;
620 }
621
622 case BOOLEAN_CHECK: {
623 Label fast;
624 // Check that the object is a boolean.
625 __ cmp(r1, Operand(Factory::true_value()));
626 __ b(eq, &fast);
627 __ cmp(r1, Operand(Factory::false_value()));
628 __ b(ne, &miss);
629 __ bind(&fast);
630 // Check that the maps starting from the prototype haven't changed.
631 GenerateLoadGlobalFunctionPrototype(masm(),
632 Context::BOOLEAN_FUNCTION_INDEX,
633 r2);
634 __ CheckMaps(JSObject::cast(object->GetPrototype()),
635 r2, holder, r3, r1, &miss);
636 break;
637 }
638
639 case JSARRAY_HAS_FAST_ELEMENTS_CHECK:
640 __ CheckMaps(JSObject::cast(object), r1, holder, r3, r2, &miss);
641 // Make sure object->elements()->map() != Heap::hash_table_map()
642 // Get the elements array of the object.
643 __ ldr(r3, FieldMemOperand(r1, JSObject::kElementsOffset));
644 // Check that the object is in fast mode (not dictionary).
645 __ ldr(r2, FieldMemOperand(r3, HeapObject::kMapOffset));
646 __ cmp(r2, Operand(Factory::hash_table_map()));
647 __ b(eq, &miss);
648 break;
649
650 default:
651 UNREACHABLE();
652 }
653
654 // Get the function and setup the context.
kasperl@chromium.orgb9123622008-09-17 14:05:56 +0000655 __ mov(r1, Operand(Handle<JSFunction>(function)));
656 __ ldr(cp, FieldMemOperand(r1, JSFunction::kContextOffset));
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000657
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000658 // Jump to the cached code (tail call).
659 Handle<Code> code(function->code());
mads.s.ager@gmail.com769cc962008-08-06 10:02:49 +0000660 ParameterCount expected(function->shared()->formal_parameter_count());
ager@chromium.org236ad962008-09-25 09:45:57 +0000661 __ InvokeCode(code, expected, arguments(),
662 RelocInfo::CODE_TARGET, JUMP_FUNCTION);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000663
664 // Handle call cache miss.
665 __ bind(&miss);
666 Handle<Code> ic = ComputeCallMiss(arguments().immediate());
ager@chromium.org236ad962008-09-25 09:45:57 +0000667 __ Jump(ic, RelocInfo::CODE_TARGET);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000668
669 // Return the generated code.
kasperl@chromium.org7be3c992009-03-12 07:19:55 +0000670 String* function_name = NULL;
671 if (function->shared()->name()->IsString()) {
672 function_name = String::cast(function->shared()->name());
673 }
kasperl@chromium.org71affb52009-05-26 05:44:31 +0000674 return GetCodeWithFlags(flags, function_name);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000675}
676
677
678Object* CallStubCompiler::CompileCallInterceptor(Object* object,
679 JSObject* holder,
680 String* name) {
681 // ----------- S t a t e -------------
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000682 // -- lr: return address
683 // -----------------------------------
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000684 Label miss;
685
686 // TODO(1224669): Implement.
687
688 // Handle call cache miss.
689 __ bind(&miss);
690 Handle<Code> ic = ComputeCallMiss(arguments().immediate());
ager@chromium.org236ad962008-09-25 09:45:57 +0000691 __ Jump(ic, RelocInfo::CODE_TARGET);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000692
693 // Return the generated code.
kasperl@chromium.org7be3c992009-03-12 07:19:55 +0000694 return GetCode(INTERCEPTOR, name);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000695}
696
697
698Object* StoreStubCompiler::CompileStoreField(JSObject* object,
699 int index,
700 Map* transition,
701 String* name) {
702 // ----------- S t a t e -------------
703 // -- r0 : value
704 // -- r2 : name
705 // -- lr : return address
706 // -- [sp] : receiver
707 // -----------------------------------
ager@chromium.orga74f0da2008-12-03 16:05:52 +0000708 Label miss;
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000709
710 // Get the receiver from the stack.
711 __ ldr(r3, MemOperand(sp, 0 * kPointerSize));
712
ager@chromium.orga74f0da2008-12-03 16:05:52 +0000713 // name register might be clobbered.
714 GenerateStoreField(masm(),
715 Builtins::StoreIC_ExtendStorage,
716 object,
717 index,
718 transition,
719 r3, r2, r1,
720 &miss);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000721 __ bind(&miss);
722 __ mov(r2, Operand(Handle<String>(name))); // restore name
723 Handle<Code> ic(Builtins::builtin(Builtins::StoreIC_Miss));
ager@chromium.org236ad962008-09-25 09:45:57 +0000724 __ Jump(ic, RelocInfo::CODE_TARGET);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000725
726 // Return the generated code.
kasperl@chromium.org7be3c992009-03-12 07:19:55 +0000727 return GetCode(transition == NULL ? FIELD : MAP_TRANSITION, name);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000728}
729
730
731Object* StoreStubCompiler::CompileStoreCallback(JSObject* object,
732 AccessorInfo* callback,
733 String* name) {
734 // ----------- S t a t e -------------
735 // -- r0 : value
736 // -- r2 : name
737 // -- lr : return address
738 // -- [sp] : receiver
739 // -----------------------------------
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000740 Label miss;
741
742 // Get the object from the stack.
743 __ ldr(r3, MemOperand(sp, 0 * kPointerSize));
744
745 // Check that the object isn't a smi.
746 __ tst(r3, Operand(kSmiTagMask));
747 __ b(eq, &miss);
748
749 // Check that the map of the object hasn't changed.
750 __ ldr(r1, FieldMemOperand(r3, HeapObject::kMapOffset));
751 __ cmp(r1, Operand(Handle<Map>(object->map())));
752 __ b(ne, &miss);
753
754 // Perform global security token check if needed.
kasperl@chromium.org5a8ca6c2008-10-23 13:57:19 +0000755 if (object->IsJSGlobalProxy()) {
756 __ CheckAccessGlobalProxy(r3, r1, &miss);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000757 }
758
759 // Stub never generated for non-global objects that require access
760 // checks.
kasperl@chromium.org5a8ca6c2008-10-23 13:57:19 +0000761 ASSERT(object->IsJSGlobalProxy() || !object->IsAccessCheckNeeded());
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000762
763 __ ldr(ip, MemOperand(sp)); // receiver
764 __ push(ip);
765 __ mov(ip, Operand(Handle<AccessorInfo>(callback))); // callback info
766 __ push(ip);
767 __ push(r2); // name
768 __ push(r0); // value
769
mads.s.ager31e71382008-08-13 09:32:07 +0000770 // Do tail-call to the runtime system.
771 ExternalReference store_callback_property =
772 ExternalReference(IC_Utility(IC::kStoreCallbackProperty));
773 __ TailCallRuntime(store_callback_property, 4);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000774
775 // Handle store cache miss.
776 __ bind(&miss);
777 __ mov(r2, Operand(Handle<String>(name))); // restore name
778 Handle<Code> ic(Builtins::builtin(Builtins::StoreIC_Miss));
ager@chromium.org236ad962008-09-25 09:45:57 +0000779 __ Jump(ic, RelocInfo::CODE_TARGET);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000780
781 // Return the generated code.
kasperl@chromium.org7be3c992009-03-12 07:19:55 +0000782 return GetCode(CALLBACKS, name);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000783}
784
785
786Object* StoreStubCompiler::CompileStoreInterceptor(JSObject* receiver,
787 String* name) {
788 // ----------- S t a t e -------------
789 // -- r0 : value
790 // -- r2 : name
791 // -- lr : return address
792 // -- [sp] : receiver
793 // -----------------------------------
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000794 Label miss;
795
796 // Get the object from the stack.
797 __ ldr(r3, MemOperand(sp, 0 * kPointerSize));
798
799 // Check that the object isn't a smi.
800 __ tst(r3, Operand(kSmiTagMask));
801 __ b(eq, &miss);
802
803 // Check that the map of the object hasn't changed.
804 __ ldr(r1, FieldMemOperand(r3, HeapObject::kMapOffset));
805 __ cmp(r1, Operand(Handle<Map>(receiver->map())));
806 __ b(ne, &miss);
807
808 // Perform global security token check if needed.
kasperl@chromium.org5a8ca6c2008-10-23 13:57:19 +0000809 if (receiver->IsJSGlobalProxy()) {
810 __ CheckAccessGlobalProxy(r3, r1, &miss);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000811 }
812
813 // Stub never generated for non-global objects that require access
814 // checks.
kasperl@chromium.org5a8ca6c2008-10-23 13:57:19 +0000815 ASSERT(receiver->IsJSGlobalProxy() || !receiver->IsAccessCheckNeeded());
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000816
817 __ ldr(ip, MemOperand(sp)); // receiver
818 __ push(ip);
819 __ push(r2); // name
820 __ push(r0); // value
821
mads.s.ager31e71382008-08-13 09:32:07 +0000822 // Do tail-call to the runtime system.
823 ExternalReference store_ic_property =
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000824 ExternalReference(IC_Utility(IC::kStoreInterceptorProperty));
mads.s.ager31e71382008-08-13 09:32:07 +0000825 __ TailCallRuntime(store_ic_property, 3);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000826
827 // Handle store cache miss.
828 __ bind(&miss);
829 __ mov(r2, Operand(Handle<String>(name))); // restore name
830 Handle<Code> ic(Builtins::builtin(Builtins::StoreIC_Miss));
ager@chromium.org236ad962008-09-25 09:45:57 +0000831 __ Jump(ic, RelocInfo::CODE_TARGET);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000832
833 // Return the generated code.
kasperl@chromium.org7be3c992009-03-12 07:19:55 +0000834 return GetCode(INTERCEPTOR, name);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000835}
836
837
838Object* LoadStubCompiler::CompileLoadField(JSObject* object,
839 JSObject* holder,
kasperl@chromium.org7be3c992009-03-12 07:19:55 +0000840 int index,
841 String* name) {
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000842 // ----------- S t a t e -------------
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000843 // -- r2 : name
844 // -- lr : return address
845 // -- [sp] : receiver
846 // -----------------------------------
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000847 Label miss;
848
mads.s.ager31e71382008-08-13 09:32:07 +0000849 __ ldr(r0, MemOperand(sp, 0));
850
ager@chromium.org3bf7b912008-11-17 09:09:45 +0000851 GenerateLoadField(masm(), object, holder, r0, r3, r1, index, &miss);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000852 __ bind(&miss);
ager@chromium.org3bf7b912008-11-17 09:09:45 +0000853 GenerateLoadMiss(masm(), Code::LOAD_IC);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000854
855 // Return the generated code.
kasperl@chromium.org7be3c992009-03-12 07:19:55 +0000856 return GetCode(FIELD, name);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000857}
858
859
860Object* LoadStubCompiler::CompileLoadCallback(JSObject* object,
861 JSObject* holder,
kasperl@chromium.org7be3c992009-03-12 07:19:55 +0000862 AccessorInfo* callback,
863 String* name) {
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000864 // ----------- S t a t e -------------
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000865 // -- r2 : name
866 // -- lr : return address
867 // -- [sp] : receiver
868 // -----------------------------------
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000869 Label miss;
870
mads.s.ager31e71382008-08-13 09:32:07 +0000871 __ ldr(r0, MemOperand(sp, 0));
ager@chromium.org3bf7b912008-11-17 09:09:45 +0000872 GenerateLoadCallback(masm(), object, holder, r0, r2, r3, r1, callback, &miss);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000873 __ bind(&miss);
ager@chromium.org3bf7b912008-11-17 09:09:45 +0000874 GenerateLoadMiss(masm(), Code::LOAD_IC);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000875
876 // Return the generated code.
kasperl@chromium.org7be3c992009-03-12 07:19:55 +0000877 return GetCode(CALLBACKS, name);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000878}
879
880
881Object* LoadStubCompiler::CompileLoadConstant(JSObject* object,
882 JSObject* holder,
kasperl@chromium.org7be3c992009-03-12 07:19:55 +0000883 Object* value,
884 String* name) {
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000885 // ----------- S t a t e -------------
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000886 // -- r2 : name
887 // -- lr : return address
888 // -- [sp] : receiver
889 // -----------------------------------
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000890 Label miss;
891
mads.s.ager31e71382008-08-13 09:32:07 +0000892 __ ldr(r0, MemOperand(sp, 0));
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000893
ager@chromium.org3bf7b912008-11-17 09:09:45 +0000894 GenerateLoadConstant(masm(), object, holder, r0, r3, r1, value, &miss);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000895 __ bind(&miss);
ager@chromium.org3bf7b912008-11-17 09:09:45 +0000896 GenerateLoadMiss(masm(), Code::LOAD_IC);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000897
898 // Return the generated code.
kasperl@chromium.org7be3c992009-03-12 07:19:55 +0000899 return GetCode(CONSTANT_FUNCTION, name);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000900}
901
902
903Object* LoadStubCompiler::CompileLoadInterceptor(JSObject* object,
904 JSObject* holder,
905 String* name) {
906 // ----------- S t a t e -------------
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000907 // -- r2 : name
908 // -- lr : return address
909 // -- [sp] : receiver
910 // -----------------------------------
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000911 Label miss;
912
mads.s.ager31e71382008-08-13 09:32:07 +0000913 __ ldr(r0, MemOperand(sp, 0));
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000914
ager@chromium.orge2902be2009-06-08 12:21:35 +0000915 GenerateLoadInterceptor(masm(),
916 object,
917 holder,
918 holder->InterceptorPropertyLookupHint(name),
919 r0,
920 r2,
921 r3,
922 r1,
923 &miss);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000924 __ bind(&miss);
ager@chromium.org3bf7b912008-11-17 09:09:45 +0000925 GenerateLoadMiss(masm(), Code::LOAD_IC);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000926
927 // Return the generated code.
kasperl@chromium.org7be3c992009-03-12 07:19:55 +0000928 return GetCode(INTERCEPTOR, name);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000929}
930
931
932// TODO(1224671): IC stubs for keyed loads have not been implemented
933// for ARM.
934Object* KeyedLoadStubCompiler::CompileLoadField(String* name,
935 JSObject* receiver,
936 JSObject* holder,
937 int index) {
ager@chromium.org3bf7b912008-11-17 09:09:45 +0000938 // ----------- S t a t e -------------
939 // -- lr : return address
940 // -- sp[0] : key
941 // -- sp[4] : receiver
942 // -----------------------------------
ager@chromium.org3bf7b912008-11-17 09:09:45 +0000943 Label miss;
944
945 __ ldr(r2, MemOperand(sp, 0));
946 __ ldr(r0, MemOperand(sp, kPointerSize));
947
948 __ cmp(r2, Operand(Handle<String>(name)));
949 __ b(ne, &miss);
950
951 GenerateLoadField(masm(), receiver, holder, r0, r3, r1, index, &miss);
952 __ bind(&miss);
953 GenerateLoadMiss(masm(), Code::KEYED_LOAD_IC);
954
kasperl@chromium.org7be3c992009-03-12 07:19:55 +0000955 return GetCode(FIELD, name);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000956}
957
958
959Object* KeyedLoadStubCompiler::CompileLoadCallback(String* name,
960 JSObject* receiver,
961 JSObject* holder,
962 AccessorInfo* callback) {
ager@chromium.org3bf7b912008-11-17 09:09:45 +0000963 // ----------- S t a t e -------------
964 // -- lr : return address
965 // -- sp[0] : key
966 // -- sp[4] : receiver
967 // -----------------------------------
ager@chromium.org3bf7b912008-11-17 09:09:45 +0000968 Label miss;
969
970 __ ldr(r2, MemOperand(sp, 0));
971 __ ldr(r0, MemOperand(sp, kPointerSize));
972
973 __ cmp(r2, Operand(Handle<String>(name)));
974 __ b(ne, &miss);
975
976 GenerateLoadCallback(masm(), receiver, holder, r0, r2, r3,
977 r1, callback, &miss);
978 __ bind(&miss);
979 GenerateLoadMiss(masm(), Code::KEYED_LOAD_IC);
980
kasperl@chromium.org7be3c992009-03-12 07:19:55 +0000981 return GetCode(CALLBACKS, name);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000982}
983
984
985Object* KeyedLoadStubCompiler::CompileLoadConstant(String* name,
986 JSObject* receiver,
987 JSObject* holder,
988 Object* value) {
ager@chromium.org3bf7b912008-11-17 09:09:45 +0000989 // ----------- S t a t e -------------
990 // -- lr : return address
991 // -- sp[0] : key
992 // -- sp[4] : receiver
993 // -----------------------------------
ager@chromium.org3bf7b912008-11-17 09:09:45 +0000994 Label miss;
995
996 // Check the key is the cached one
997 __ ldr(r2, MemOperand(sp, 0));
998 __ ldr(r0, MemOperand(sp, kPointerSize));
999
1000 __ cmp(r2, Operand(Handle<String>(name)));
1001 __ b(ne, &miss);
1002
1003 GenerateLoadConstant(masm(), receiver, holder, r0, r3, r1, value, &miss);
1004 __ bind(&miss);
1005 GenerateLoadMiss(masm(), Code::KEYED_LOAD_IC);
1006
1007 // Return the generated code.
kasperl@chromium.org7be3c992009-03-12 07:19:55 +00001008 return GetCode(CONSTANT_FUNCTION, name);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001009}
1010
1011
1012Object* KeyedLoadStubCompiler::CompileLoadInterceptor(JSObject* receiver,
1013 JSObject* holder,
1014 String* name) {
ager@chromium.org3bf7b912008-11-17 09:09:45 +00001015 // ----------- S t a t e -------------
1016 // -- lr : return address
1017 // -- sp[0] : key
1018 // -- sp[4] : receiver
1019 // -----------------------------------
ager@chromium.org3bf7b912008-11-17 09:09:45 +00001020 Label miss;
1021
1022 // Check the key is the cached one
1023 __ ldr(r2, MemOperand(sp, 0));
1024 __ ldr(r0, MemOperand(sp, kPointerSize));
1025
1026 __ cmp(r2, Operand(Handle<String>(name)));
1027 __ b(ne, &miss);
1028
ager@chromium.orge2902be2009-06-08 12:21:35 +00001029 GenerateLoadInterceptor(masm(),
1030 receiver,
1031 holder,
1032 Smi::FromInt(JSObject::kLookupInHolder),
1033 r0,
1034 r2,
1035 r3,
1036 r1,
1037 &miss);
ager@chromium.org3bf7b912008-11-17 09:09:45 +00001038 __ bind(&miss);
1039 GenerateLoadMiss(masm(), Code::KEYED_LOAD_IC);
1040
kasperl@chromium.org7be3c992009-03-12 07:19:55 +00001041 return GetCode(INTERCEPTOR, name);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001042}
1043
1044
1045Object* KeyedLoadStubCompiler::CompileLoadArrayLength(String* name) {
ager@chromium.org3bf7b912008-11-17 09:09:45 +00001046 // ----------- S t a t e -------------
1047 // -- lr : return address
1048 // -- sp[0] : key
1049 // -- sp[4] : receiver
1050 // -----------------------------------
ager@chromium.org3bf7b912008-11-17 09:09:45 +00001051 Label miss;
1052
1053 // Check the key is the cached one
1054 __ ldr(r2, MemOperand(sp, 0));
1055 __ ldr(r0, MemOperand(sp, kPointerSize));
1056
1057 __ cmp(r2, Operand(Handle<String>(name)));
1058 __ b(ne, &miss);
1059
1060 GenerateLoadArrayLength(masm(), r0, r3, &miss);
1061 __ bind(&miss);
1062 GenerateLoadMiss(masm(), Code::KEYED_LOAD_IC);
1063
kasperl@chromium.org7be3c992009-03-12 07:19:55 +00001064 return GetCode(CALLBACKS, name);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001065}
1066
1067
kasperl@chromium.org9fe21c62008-10-28 08:53:51 +00001068Object* KeyedLoadStubCompiler::CompileLoadStringLength(String* name) {
ager@chromium.org3bf7b912008-11-17 09:09:45 +00001069 // ----------- S t a t e -------------
1070 // -- lr : return address
1071 // -- sp[0] : key
1072 // -- sp[4] : receiver
1073 // -----------------------------------
ager@chromium.orga74f0da2008-12-03 16:05:52 +00001074 Label miss;
1075 __ IncrementCounter(&Counters::keyed_load_string_length, 1, r1, r3);
1076
1077 __ ldr(r2, MemOperand(sp));
1078 __ ldr(r0, MemOperand(sp, kPointerSize)); // receiver
1079
1080 __ cmp(r2, Operand(Handle<String>(name)));
1081 __ b(ne, &miss);
1082
1083 GenerateLoadStringLength2(masm(), r0, r1, r3, &miss);
1084 __ bind(&miss);
1085 __ DecrementCounter(&Counters::keyed_load_string_length, 1, r1, r3);
1086
ager@chromium.org3bf7b912008-11-17 09:09:45 +00001087 GenerateLoadMiss(masm(), Code::KEYED_LOAD_IC);
1088
kasperl@chromium.org7be3c992009-03-12 07:19:55 +00001089 return GetCode(CALLBACKS, name);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001090}
1091
1092
ager@chromium.org3bf7b912008-11-17 09:09:45 +00001093// TODO(1224671): implement the fast case.
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001094Object* KeyedLoadStubCompiler::CompileLoadFunctionPrototype(String* name) {
ager@chromium.org3bf7b912008-11-17 09:09:45 +00001095 // ----------- S t a t e -------------
1096 // -- lr : return address
1097 // -- sp[0] : key
1098 // -- sp[4] : receiver
1099 // -----------------------------------
ager@chromium.org3bf7b912008-11-17 09:09:45 +00001100 GenerateLoadMiss(masm(), Code::KEYED_LOAD_IC);
1101
kasperl@chromium.org7be3c992009-03-12 07:19:55 +00001102 return GetCode(CALLBACKS, name);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001103}
1104
1105
1106Object* KeyedStoreStubCompiler::CompileStoreField(JSObject* object,
1107 int index,
1108 Map* transition,
1109 String* name) {
ager@chromium.org3bf7b912008-11-17 09:09:45 +00001110 // ----------- S t a t e -------------
1111 // -- r0 : value
1112 // -- r2 : name
1113 // -- lr : return address
1114 // -- [sp] : receiver
1115 // -----------------------------------
ager@chromium.orga74f0da2008-12-03 16:05:52 +00001116 Label miss;
1117
1118 __ IncrementCounter(&Counters::keyed_store_field, 1, r1, r3);
1119
1120 // Check that the name has not changed.
1121 __ cmp(r2, Operand(Handle<String>(name)));
1122 __ b(ne, &miss);
1123
1124 // Load receiver from the stack.
1125 __ ldr(r3, MemOperand(sp));
1126 // r1 is used as scratch register, r3 and r2 might be clobbered.
1127 GenerateStoreField(masm(),
1128 Builtins::StoreIC_ExtendStorage,
1129 object,
1130 index,
1131 transition,
1132 r3, r2, r1,
1133 &miss);
1134 __ bind(&miss);
1135
1136 __ DecrementCounter(&Counters::keyed_store_field, 1, r1, r3);
1137 __ mov(r2, Operand(Handle<String>(name))); // restore name register.
ager@chromium.org3bf7b912008-11-17 09:09:45 +00001138 Handle<Code> ic(Builtins::builtin(Builtins::KeyedStoreIC_Miss));
1139 __ Jump(ic, RelocInfo::CODE_TARGET);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001140
ager@chromium.org3bf7b912008-11-17 09:09:45 +00001141 // Return the generated code.
kasperl@chromium.org7be3c992009-03-12 07:19:55 +00001142 return GetCode(transition == NULL ? FIELD : MAP_TRANSITION, name);
ager@chromium.org3bf7b912008-11-17 09:09:45 +00001143}
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001144
1145
1146#undef __
1147
1148} } // namespace v8::internal