blob: 211b643fae2aa2f5220e6d44218018147ec5b1d8 [file] [log] [blame]
ager@chromium.org9258b6b2008-09-11 09:11:10 +00001// Copyright 2006-2008 the V8 project authors. All rights reserved.
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002// Redistribution and use in source and binary forms, with or without
3// modification, are permitted provided that the following conditions are
4// met:
5//
6// * Redistributions of source code must retain the above copyright
7// notice, this list of conditions and the following disclaimer.
8// * Redistributions in binary form must reproduce the above
9// copyright notice, this list of conditions and the following
10// disclaimer in the documentation and/or other materials provided
11// with the distribution.
12// * Neither the name of Google Inc. nor the names of its
13// contributors may be used to endorse or promote products derived
14// from this software without specific prior written permission.
15//
16// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
17// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
18// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
19// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
20// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
21// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
22// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
23// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
24// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
25// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
26// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27
28#include "v8.h"
29
30#include "ic-inl.h"
31#include "codegen-inl.h"
32#include "stub-cache.h"
33
34namespace v8 { namespace internal {
35
36#define __ masm->
37
38
39static void ProbeTable(MacroAssembler* masm,
40 Code::Flags flags,
41 StubCache::Table table,
42 Register name,
43 Register offset) {
44 ExternalReference key_offset(SCTableReference::keyReference(table));
45 ExternalReference value_offset(SCTableReference::valueReference(table));
46
47 Label miss;
48
49 // Save the offset on the stack.
50 __ push(offset);
51
52 // Check that the key in the entry matches the name.
53 __ mov(ip, Operand(key_offset));
54 __ ldr(ip, MemOperand(ip, offset, LSL, 1));
55 __ cmp(name, Operand(ip));
56 __ b(ne, &miss);
57
58 // Get the code entry from the cache.
59 __ mov(ip, Operand(value_offset));
60 __ ldr(offset, MemOperand(ip, offset, LSL, 1));
61
62 // Check that the flags match what we're looking for.
63 __ ldr(offset, FieldMemOperand(offset, Code::kFlagsOffset));
64 __ and_(offset, offset, Operand(~Code::kFlagsTypeMask));
65 __ cmp(offset, Operand(flags));
66 __ b(ne, &miss);
67
68 // Restore offset and re-load code entry from cache.
69 __ pop(offset);
70 __ mov(ip, Operand(value_offset));
71 __ ldr(offset, MemOperand(ip, offset, LSL, 1));
72
73 // Jump to the first instruction in the code stub.
74 __ add(offset, offset, Operand(Code::kHeaderSize - kHeapObjectTag));
75 __ Jump(offset);
76
77 // Miss: Restore offset and fall through.
78 __ bind(&miss);
79 __ pop(offset);
80}
81
82
83void StubCache::GenerateProbe(MacroAssembler* masm,
84 Code::Flags flags,
85 Register receiver,
86 Register name,
87 Register scratch) {
88 Label miss;
89
90 // Make sure that code is valid. The shifting code relies on the
91 // entry size being 8.
92 ASSERT(sizeof(Entry) == 8);
93
94 // Make sure the flags does not name a specific type.
95 ASSERT(Code::ExtractTypeFromFlags(flags) == 0);
96
97 // Make sure that there are no register conflicts.
98 ASSERT(!scratch.is(receiver));
99 ASSERT(!scratch.is(name));
100
101 // Check that the receiver isn't a smi.
102 __ tst(receiver, Operand(kSmiTagMask));
103 __ b(eq, &miss);
104
105 // Get the map of the receiver and compute the hash.
ager@chromium.org7c537e22008-10-16 08:43:32 +0000106 __ ldr(scratch, FieldMemOperand(name, String::kLengthOffset));
107 __ ldr(ip, FieldMemOperand(receiver, HeapObject::kMapOffset));
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000108 __ add(scratch, scratch, Operand(ip));
109 __ eor(scratch, scratch, Operand(flags));
110 __ and_(scratch,
111 scratch,
112 Operand((kPrimaryTableSize - 1) << kHeapObjectTagSize));
113
114 // Probe the primary table.
115 ProbeTable(masm, flags, kPrimary, name, scratch);
116
117 // Primary miss: Compute hash for secondary probe.
118 __ sub(scratch, scratch, Operand(name));
119 __ add(scratch, scratch, Operand(flags));
120 __ and_(scratch,
121 scratch,
122 Operand((kSecondaryTableSize - 1) << kHeapObjectTagSize));
123
124 // Probe the secondary table.
125 ProbeTable(masm, flags, kSecondary, name, scratch);
126
127 // Cache miss: Fall-through and let caller handle the miss by
128 // entering the runtime system.
129 __ bind(&miss);
130}
131
132
133void StubCompiler::GenerateLoadGlobalFunctionPrototype(MacroAssembler* masm,
134 int index,
135 Register prototype) {
136 // Load the global or builtins object from the current context.
137 __ ldr(prototype, MemOperand(cp, Context::SlotOffset(Context::GLOBAL_INDEX)));
138 // Load the global context from the global or builtins object.
139 __ ldr(prototype,
140 FieldMemOperand(prototype, GlobalObject::kGlobalContextOffset));
141 // Load the function from the global context.
142 __ ldr(prototype, MemOperand(prototype, Context::SlotOffset(index)));
143 // Load the initial map. The global functions all have initial maps.
144 __ ldr(prototype,
145 FieldMemOperand(prototype, JSFunction::kPrototypeOrInitialMapOffset));
146 // Load the prototype from the initial map.
147 __ ldr(prototype, FieldMemOperand(prototype, Map::kPrototypeOffset));
148}
149
150
ager@chromium.org7c537e22008-10-16 08:43:32 +0000151// Load a fast property out of a holder object (src). In-object properties
152// are loaded directly otherwise the property is loaded from the properties
153// fixed array.
154void StubCompiler::GenerateFastPropertyLoad(MacroAssembler* masm,
155 Register dst, Register src,
156 JSObject* holder, int index) {
157 // Adjust for the number of properties stored in the holder.
158 index -= holder->map()->inobject_properties();
159 if (index < 0) {
160 // Get the property straight out of the holder.
161 int offset = holder->map()->instance_size() + (index * kPointerSize);
162 __ ldr(dst, FieldMemOperand(src, offset));
163 } else {
164 // Calculate the offset into the properties array.
165 int offset = index * kPointerSize + Array::kHeaderSize;
166 __ ldr(dst, FieldMemOperand(src, JSObject::kPropertiesOffset));
167 __ ldr(dst, FieldMemOperand(dst, offset));
168 }
169}
170
171
ager@chromium.org3bf7b912008-11-17 09:09:45 +0000172void StubCompiler::GenerateLoadField(MacroAssembler* masm,
173 JSObject* object,
174 JSObject* holder,
175 Register receiver,
176 Register scratch1,
177 Register scratch2,
178 int index,
179 Label* miss_label) {
180 // Check that the receiver isn't a smi.
181 __ tst(receiver, Operand(kSmiTagMask));
182 __ b(eq, miss_label);
183
184 // Check that the maps haven't changed.
185 Register reg =
186 __ CheckMaps(object, receiver, holder, scratch1, scratch2, miss_label);
187 GenerateFastPropertyLoad(masm, r0, reg, holder, index);
188 __ Ret();
189}
190
191
192void StubCompiler::GenerateLoadConstant(MacroAssembler* masm,
193 JSObject* object,
194 JSObject* holder,
195 Register receiver,
196 Register scratch1,
197 Register scratch2,
198 Object* value,
199 Label* miss_label) {
200 // Check that the receiver isn't a smi.
201 __ tst(receiver, Operand(kSmiTagMask));
202 __ b(eq, miss_label);
203
204 // Check that the maps haven't changed.
205 Register reg =
206 __ CheckMaps(object, receiver, holder, scratch1, scratch2, miss_label);
207
208 // Return the constant value.
209 __ mov(r0, Operand(Handle<Object>(value)));
210 __ Ret();
211}
212
213
214void StubCompiler::GenerateLoadCallback(MacroAssembler* masm,
215 JSObject* object,
216 JSObject* holder,
217 Register receiver,
218 Register name,
219 Register scratch1,
220 Register scratch2,
221 AccessorInfo* callback,
222 Label* miss_label) {
223 // Check that the receiver isn't a smi.
224 __ tst(receiver, Operand(kSmiTagMask));
225 __ b(eq, miss_label);
226
227 // Check that the maps haven't changed.
228 Register reg =
229 __ CheckMaps(object, receiver, holder, scratch1, scratch2, miss_label);
230
231 // Push the arguments on the JS stack of the caller.
232 __ push(receiver); // receiver
233 __ mov(ip, Operand(Handle<AccessorInfo>(callback))); // callback data
234 __ push(ip);
235 __ push(name); // name
236 __ push(reg); // holder
237
238 // Do tail-call to the runtime system.
239 ExternalReference load_callback_property =
240 ExternalReference(IC_Utility(IC::kLoadCallbackProperty));
241 __ TailCallRuntime(load_callback_property, 4);
242}
243
244
245void StubCompiler::GenerateLoadInterceptor(MacroAssembler* masm,
246 JSObject* object,
247 JSObject* holder,
248 Register receiver,
249 Register name,
250 Register scratch1,
251 Register scratch2,
252 Label* miss_label) {
253 // Check that the receiver isn't a smi.
254 __ tst(receiver, Operand(kSmiTagMask));
255 __ b(eq, miss_label);
256
257 // Check that the maps haven't changed.
258 Register reg =
259 __ CheckMaps(object, receiver, holder, scratch1, scratch2, miss_label);
260
261 // Push the arguments on the JS stack of the caller.
262 __ push(receiver); // receiver
263 __ push(reg); // holder
264 __ push(name); // name
265
266 // Do tail-call to the runtime system.
267 ExternalReference load_ic_property =
268 ExternalReference(IC_Utility(IC::kLoadInterceptorProperty));
269 __ TailCallRuntime(load_ic_property, 3);
270}
271
272
273void StubCompiler::GenerateLoadArrayLength(MacroAssembler* masm,
274 Register receiver,
275 Register scratch,
276 Label* miss_label) {
277 // Check that the receiver isn't a smi.
278 __ tst(receiver, Operand(kSmiTagMask));
279 __ b(eq, miss_label);
280
281 // Check that the object is a JS array.
282 __ ldr(scratch, FieldMemOperand(receiver, HeapObject::kMapOffset));
283 __ ldrb(scratch, FieldMemOperand(scratch, Map::kInstanceTypeOffset));
284 __ cmp(scratch, Operand(JS_ARRAY_TYPE));
285 __ b(ne, miss_label);
286
287 // Load length directly from the JS array.
288 __ ldr(r0, FieldMemOperand(receiver, JSArray::kLengthOffset));
289 __ Ret();
290}
291
292
ager@chromium.orga74f0da2008-12-03 16:05:52 +0000293// Generate code to check if an object is a string. If the object is
294// a string, the map's instance type is left in the scratch1 register.
295static void GenerateStringCheck(MacroAssembler* masm,
296 Register receiver,
297 Register scratch1,
298 Register scratch2,
299 Label* smi,
300 Label* non_string_object) {
301 // Check that the receiver isn't a smi.
302 __ tst(receiver, Operand(kSmiTagMask));
303 __ b(eq, smi);
304
305 // Check that the object is a string.
306 __ ldr(scratch1, FieldMemOperand(receiver, HeapObject::kMapOffset));
307 __ ldrb(scratch1, FieldMemOperand(scratch1, Map::kInstanceTypeOffset));
308 __ and_(scratch2, scratch1, Operand(kIsNotStringMask));
309 // The cast is to resolve the overload for the argument of 0x0.
310 __ cmp(scratch2, Operand(static_cast<int32_t>(kStringTag)));
311 __ b(ne, non_string_object);
312}
313
314
ager@chromium.org32912102009-01-16 10:38:43 +0000315// Generate code to load the length from a string object and return the length.
316// If the receiver object is not a string or a wrapped string object the
317// execution continues at the miss label. The register containing the
318// receiver is potentially clobbered.
ager@chromium.orga74f0da2008-12-03 16:05:52 +0000319void StubCompiler::GenerateLoadStringLength2(MacroAssembler* masm,
320 Register receiver,
321 Register scratch1,
322 Register scratch2,
323 Label* miss) {
ager@chromium.org32912102009-01-16 10:38:43 +0000324 Label check_string, check_wrapper;
ager@chromium.orga74f0da2008-12-03 16:05:52 +0000325
ager@chromium.org32912102009-01-16 10:38:43 +0000326 __ bind(&check_string);
ager@chromium.orga74f0da2008-12-03 16:05:52 +0000327 // Check if the object is a string leaving the instance type in the
328 // scratch1 register.
329 GenerateStringCheck(masm, receiver, scratch1, scratch2,
330 miss, &check_wrapper);
331
332 // Load length directly from the string.
ager@chromium.orga74f0da2008-12-03 16:05:52 +0000333 __ and_(scratch1, scratch1, Operand(kStringSizeMask));
334 __ add(scratch1, scratch1, Operand(String::kHashShift));
335 __ ldr(r0, FieldMemOperand(receiver, String::kLengthOffset));
336 __ mov(r0, Operand(r0, LSR, scratch1));
337 __ mov(r0, Operand(r0, LSL, kSmiTagSize));
338 __ Ret();
339
340 // Check if the object is a JSValue wrapper.
341 __ bind(&check_wrapper);
342 __ cmp(scratch1, Operand(JS_VALUE_TYPE));
343 __ b(ne, miss);
344
ager@chromium.org32912102009-01-16 10:38:43 +0000345 // Unwrap the value in place and check if the wrapped value is a string.
346 __ ldr(receiver, FieldMemOperand(receiver, JSValue::kValueOffset));
347 __ b(&check_string);
ager@chromium.orga74f0da2008-12-03 16:05:52 +0000348}
349
350
351// Generate StoreField code, value is passed in r0 register.
352// After executing generated code, the receiver_reg and name_reg
353// may be clobbered.
354void StubCompiler::GenerateStoreField(MacroAssembler* masm,
355 Builtins::Name storage_extend,
356 JSObject* object,
357 int index,
358 Map* transition,
359 Register receiver_reg,
360 Register name_reg,
361 Register scratch,
362 Label* miss_label) {
363 // r0 : value
364 Label exit;
365
366 // Check that the receiver isn't a smi.
367 __ tst(receiver_reg, Operand(kSmiTagMask));
368 __ b(eq, miss_label);
369
370 // Check that the map of the receiver hasn't changed.
371 __ ldr(scratch, FieldMemOperand(receiver_reg, HeapObject::kMapOffset));
372 __ cmp(scratch, Operand(Handle<Map>(object->map())));
373 __ b(ne, miss_label);
374
375 // Perform global security token check if needed.
376 if (object->IsJSGlobalProxy()) {
377 __ CheckAccessGlobalProxy(receiver_reg, scratch, miss_label);
378 }
379
380 // Stub never generated for non-global objects that require access
381 // checks.
382 ASSERT(object->IsJSGlobalProxy() || !object->IsAccessCheckNeeded());
383
384 // Perform map transition for the receiver if necessary.
385 if ((transition != NULL) && (object->map()->unused_property_fields() == 0)) {
386 // The properties must be extended before we can store the value.
ager@chromium.org32912102009-01-16 10:38:43 +0000387 // We jump to a runtime call that extends the properties array.
ager@chromium.orga74f0da2008-12-03 16:05:52 +0000388 __ mov(r2, Operand(Handle<Map>(transition)));
389 // Please note, if we implement keyed store for arm we need
390 // to call the Builtins::KeyedStoreIC_ExtendStorage.
391 Handle<Code> ic(Builtins::builtin(Builtins::StoreIC_ExtendStorage));
392 __ Jump(ic, RelocInfo::CODE_TARGET);
393 return;
394 }
395
396 if (transition != NULL) {
397 // Update the map of the object; no write barrier updating is
398 // needed because the map is never in new space.
399 __ mov(ip, Operand(Handle<Map>(transition)));
400 __ str(ip, FieldMemOperand(receiver_reg, HeapObject::kMapOffset));
401 }
402
403 // Adjust for the number of properties stored in the object. Even in the
404 // face of a transition we can use the old map here because the size of the
405 // object and the number of in-object properties is not going to change.
406 index -= object->map()->inobject_properties();
407
408 if (index < 0) {
409 // Set the property straight into the object.
410 int offset = object->map()->instance_size() + (index * kPointerSize);
411 __ str(r0, FieldMemOperand(receiver_reg, offset));
412
413 // Skip updating write barrier if storing a smi.
414 __ tst(r0, Operand(kSmiTagMask));
415 __ b(eq, &exit);
416
417 // Update the write barrier for the array address.
418 // Pass the value being stored in the now unused name_reg.
419 __ mov(name_reg, Operand(offset));
420 __ RecordWrite(receiver_reg, name_reg, scratch);
421 } else {
422 // Write to the properties array.
423 int offset = index * kPointerSize + Array::kHeaderSize;
424 // Get the properties array
425 __ ldr(scratch, FieldMemOperand(receiver_reg, JSObject::kPropertiesOffset));
426 __ str(r0, FieldMemOperand(scratch, offset));
427
428 // Skip updating write barrier if storing a smi.
429 __ tst(r0, Operand(kSmiTagMask));
430 __ b(eq, &exit);
431
432 // Update the write barrier for the array address.
433 // Ok to clobber receiver_reg and name_reg, since we return.
434 __ mov(name_reg, Operand(offset));
435 __ RecordWrite(scratch, name_reg, receiver_reg);
436 }
437
438 // Return the value (register r0).
439 __ bind(&exit);
440 __ Ret();
441}
442
443
ager@chromium.org3bf7b912008-11-17 09:09:45 +0000444void StubCompiler::GenerateLoadMiss(MacroAssembler* masm, Code::Kind kind) {
445 ASSERT(kind == Code::LOAD_IC || kind == Code::KEYED_LOAD_IC);
446 Code* code = NULL;
447 if (kind == Code::LOAD_IC) {
448 code = Builtins::builtin(Builtins::LoadIC_Miss);
449 } else {
450 code = Builtins::builtin(Builtins::KeyedLoadIC_Miss);
451 }
452
453 Handle<Code> ic(code);
454 __ Jump(ic, RelocInfo::CODE_TARGET);
455}
456
457
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000458#undef __
459
460#define __ masm()->
461
462
463Object* StubCompiler::CompileLazyCompile(Code::Flags flags) {
kasperl@chromium.orgb9123622008-09-17 14:05:56 +0000464 // ----------- S t a t e -------------
465 // -- r1: function
466 // -- lr: return address
467 // -----------------------------------
468
kasperl@chromium.orgb9123622008-09-17 14:05:56 +0000469 // Enter an internal frame.
470 __ EnterInternalFrame();
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000471
kasperl@chromium.orgb9123622008-09-17 14:05:56 +0000472 // Preserve the function.
473 __ push(r1);
474
475 // Push the function on the stack as the argument to the runtime function.
476 __ push(r1);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000477 __ CallRuntime(Runtime::kLazyCompile, 1);
478
kasperl@chromium.orgb9123622008-09-17 14:05:56 +0000479 // Calculate the entry point.
480 __ add(r2, r0, Operand(Code::kHeaderSize - kHeapObjectTag));
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000481
kasperl@chromium.orgb9123622008-09-17 14:05:56 +0000482 // Restore saved function.
483 __ pop(r1);
484
485 // Tear down temporary frame.
ager@chromium.org236ad962008-09-25 09:45:57 +0000486 __ LeaveInternalFrame();
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000487
488 // Do a tail-call of the compiled function.
kasperl@chromium.orgb9123622008-09-17 14:05:56 +0000489 __ Jump(r2);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000490
kasperl@chromium.org7be3c992009-03-12 07:19:55 +0000491 return GetCodeWithFlags(flags, "LazyCompileStub");
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000492}
493
494
495Object* CallStubCompiler::CompileCallField(Object* object,
496 JSObject* holder,
kasperl@chromium.org7be3c992009-03-12 07:19:55 +0000497 int index,
498 String* name) {
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000499 // ----------- S t a t e -------------
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000500 // -- lr: return address
501 // -----------------------------------
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000502 Label miss;
503
mads.s.ager31e71382008-08-13 09:32:07 +0000504 const int argc = arguments().immediate();
505
kasperl@chromium.org9fe21c62008-10-28 08:53:51 +0000506 // Get the receiver of the function from the stack into r0.
507 __ ldr(r0, MemOperand(sp, argc * kPointerSize));
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000508 // Check that the receiver isn't a smi.
kasperl@chromium.org9fe21c62008-10-28 08:53:51 +0000509 __ tst(r0, Operand(kSmiTagMask));
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000510 __ b(eq, &miss);
511
512 // Do the right check and compute the holder register.
513 Register reg =
kasperl@chromium.org9fe21c62008-10-28 08:53:51 +0000514 __ CheckMaps(JSObject::cast(object), r0, holder, r3, r2, &miss);
ager@chromium.org7c537e22008-10-16 08:43:32 +0000515 GenerateFastPropertyLoad(masm(), r1, reg, holder, index);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000516
517 // Check that the function really is a function.
kasperl@chromium.orgb9123622008-09-17 14:05:56 +0000518 __ tst(r1, Operand(kSmiTagMask));
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000519 __ b(eq, &miss);
520 // Get the map.
kasperl@chromium.orgb9123622008-09-17 14:05:56 +0000521 __ ldr(r2, FieldMemOperand(r1, HeapObject::kMapOffset));
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000522 __ ldrb(r2, FieldMemOperand(r2, Map::kInstanceTypeOffset));
523 __ cmp(r2, Operand(JS_FUNCTION_TYPE));
524 __ b(ne, &miss);
525
kasperl@chromium.org9fe21c62008-10-28 08:53:51 +0000526 // Patch the receiver on the stack with the global proxy if
527 // necessary.
528 if (object->IsGlobalObject()) {
529 __ ldr(r3, FieldMemOperand(r0, GlobalObject::kGlobalReceiverOffset));
530 __ str(r3, MemOperand(sp, argc * kPointerSize));
531 }
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000532
kasperl@chromium.orgb9123622008-09-17 14:05:56 +0000533 // Invoke the function.
534 __ InvokeFunction(r1, arguments(), JUMP_FUNCTION);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000535
536 // Handle call cache miss.
537 __ bind(&miss);
538 Handle<Code> ic = ComputeCallMiss(arguments().immediate());
ager@chromium.org236ad962008-09-25 09:45:57 +0000539 __ Jump(ic, RelocInfo::CODE_TARGET);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000540
541 // Return the generated code.
kasperl@chromium.org7be3c992009-03-12 07:19:55 +0000542 return GetCode(FIELD, name);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000543}
544
545
546Object* CallStubCompiler::CompileCallConstant(Object* object,
547 JSObject* holder,
548 JSFunction* function,
549 CheckType check) {
550 // ----------- S t a t e -------------
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000551 // -- lr: return address
552 // -----------------------------------
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000553 Label miss;
554
mads.s.ager31e71382008-08-13 09:32:07 +0000555 // Get the receiver from the stack
556 const int argc = arguments().immediate();
557 __ ldr(r1, MemOperand(sp, argc * kPointerSize));
558
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000559 // Check that the receiver isn't a smi.
560 if (check != NUMBER_CHECK) {
561 __ tst(r1, Operand(kSmiTagMask));
562 __ b(eq, &miss);
563 }
564
kasperl@chromium.org9fe21c62008-10-28 08:53:51 +0000565 // Make sure that it's okay not to patch the on stack receiver
566 // unless we're doing a receiver map check.
567 ASSERT(!object->IsGlobalObject() || check == RECEIVER_MAP_CHECK);
568
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000569 switch (check) {
570 case RECEIVER_MAP_CHECK:
571 // Check that the maps haven't changed.
572 __ CheckMaps(JSObject::cast(object), r1, holder, r3, r2, &miss);
kasperl@chromium.org9fe21c62008-10-28 08:53:51 +0000573
574 // Patch the receiver on the stack with the global proxy if
575 // necessary.
576 if (object->IsGlobalObject()) {
577 __ ldr(r3, FieldMemOperand(r1, GlobalObject::kGlobalReceiverOffset));
578 __ str(r3, MemOperand(sp, argc * kPointerSize));
579 }
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000580 break;
581
582 case STRING_CHECK:
583 // Check that the object is a two-byte string or a symbol.
584 __ ldr(r2, FieldMemOperand(r1, HeapObject::kMapOffset));
585 __ ldrb(r2, FieldMemOperand(r2, Map::kInstanceTypeOffset));
586 __ cmp(r2, Operand(FIRST_NONSTRING_TYPE));
587 __ b(hs, &miss);
588 // Check that the maps starting from the prototype haven't changed.
589 GenerateLoadGlobalFunctionPrototype(masm(),
590 Context::STRING_FUNCTION_INDEX,
591 r2);
592 __ CheckMaps(JSObject::cast(object->GetPrototype()),
593 r2, holder, r3, r1, &miss);
594 break;
595
596 case NUMBER_CHECK: {
597 Label fast;
598 // Check that the object is a smi or a heap number.
599 __ tst(r1, Operand(kSmiTagMask));
600 __ b(eq, &fast);
601 __ ldr(r2, FieldMemOperand(r1, HeapObject::kMapOffset));
602 __ ldrb(r2, FieldMemOperand(r2, Map::kInstanceTypeOffset));
603 __ cmp(r2, Operand(HEAP_NUMBER_TYPE));
604 __ b(ne, &miss);
605 __ bind(&fast);
606 // Check that the maps starting from the prototype haven't changed.
607 GenerateLoadGlobalFunctionPrototype(masm(),
608 Context::NUMBER_FUNCTION_INDEX,
609 r2);
610 __ CheckMaps(JSObject::cast(object->GetPrototype()),
611 r2, holder, r3, r1, &miss);
612 break;
613 }
614
615 case BOOLEAN_CHECK: {
616 Label fast;
617 // Check that the object is a boolean.
618 __ cmp(r1, Operand(Factory::true_value()));
619 __ b(eq, &fast);
620 __ cmp(r1, Operand(Factory::false_value()));
621 __ b(ne, &miss);
622 __ bind(&fast);
623 // Check that the maps starting from the prototype haven't changed.
624 GenerateLoadGlobalFunctionPrototype(masm(),
625 Context::BOOLEAN_FUNCTION_INDEX,
626 r2);
627 __ CheckMaps(JSObject::cast(object->GetPrototype()),
628 r2, holder, r3, r1, &miss);
629 break;
630 }
631
632 case JSARRAY_HAS_FAST_ELEMENTS_CHECK:
633 __ CheckMaps(JSObject::cast(object), r1, holder, r3, r2, &miss);
634 // Make sure object->elements()->map() != Heap::hash_table_map()
635 // Get the elements array of the object.
636 __ ldr(r3, FieldMemOperand(r1, JSObject::kElementsOffset));
637 // Check that the object is in fast mode (not dictionary).
638 __ ldr(r2, FieldMemOperand(r3, HeapObject::kMapOffset));
639 __ cmp(r2, Operand(Factory::hash_table_map()));
640 __ b(eq, &miss);
641 break;
642
643 default:
644 UNREACHABLE();
645 }
646
647 // Get the function and setup the context.
kasperl@chromium.orgb9123622008-09-17 14:05:56 +0000648 __ mov(r1, Operand(Handle<JSFunction>(function)));
649 __ ldr(cp, FieldMemOperand(r1, JSFunction::kContextOffset));
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000650
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000651 // Jump to the cached code (tail call).
652 Handle<Code> code(function->code());
mads.s.ager@gmail.com769cc962008-08-06 10:02:49 +0000653 ParameterCount expected(function->shared()->formal_parameter_count());
ager@chromium.org236ad962008-09-25 09:45:57 +0000654 __ InvokeCode(code, expected, arguments(),
655 RelocInfo::CODE_TARGET, JUMP_FUNCTION);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000656
657 // Handle call cache miss.
658 __ bind(&miss);
659 Handle<Code> ic = ComputeCallMiss(arguments().immediate());
ager@chromium.org236ad962008-09-25 09:45:57 +0000660 __ Jump(ic, RelocInfo::CODE_TARGET);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000661
662 // Return the generated code.
kasperl@chromium.org7be3c992009-03-12 07:19:55 +0000663 String* function_name = NULL;
664 if (function->shared()->name()->IsString()) {
665 function_name = String::cast(function->shared()->name());
666 }
667 return GetCode(CONSTANT_FUNCTION, function_name);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000668}
669
670
671Object* CallStubCompiler::CompileCallInterceptor(Object* object,
672 JSObject* holder,
673 String* name) {
674 // ----------- S t a t e -------------
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000675 // -- lr: return address
676 // -----------------------------------
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000677 Label miss;
678
679 // TODO(1224669): Implement.
680
681 // Handle call cache miss.
682 __ bind(&miss);
683 Handle<Code> ic = ComputeCallMiss(arguments().immediate());
ager@chromium.org236ad962008-09-25 09:45:57 +0000684 __ Jump(ic, RelocInfo::CODE_TARGET);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000685
686 // Return the generated code.
kasperl@chromium.org7be3c992009-03-12 07:19:55 +0000687 return GetCode(INTERCEPTOR, name);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000688}
689
690
691Object* StoreStubCompiler::CompileStoreField(JSObject* object,
692 int index,
693 Map* transition,
694 String* name) {
695 // ----------- S t a t e -------------
696 // -- r0 : value
697 // -- r2 : name
698 // -- lr : return address
699 // -- [sp] : receiver
700 // -----------------------------------
ager@chromium.orga74f0da2008-12-03 16:05:52 +0000701 Label miss;
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000702
703 // Get the receiver from the stack.
704 __ ldr(r3, MemOperand(sp, 0 * kPointerSize));
705
ager@chromium.orga74f0da2008-12-03 16:05:52 +0000706 // name register might be clobbered.
707 GenerateStoreField(masm(),
708 Builtins::StoreIC_ExtendStorage,
709 object,
710 index,
711 transition,
712 r3, r2, r1,
713 &miss);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000714 __ bind(&miss);
715 __ mov(r2, Operand(Handle<String>(name))); // restore name
716 Handle<Code> ic(Builtins::builtin(Builtins::StoreIC_Miss));
ager@chromium.org236ad962008-09-25 09:45:57 +0000717 __ Jump(ic, RelocInfo::CODE_TARGET);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000718
719 // Return the generated code.
kasperl@chromium.org7be3c992009-03-12 07:19:55 +0000720 return GetCode(transition == NULL ? FIELD : MAP_TRANSITION, name);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000721}
722
723
724Object* StoreStubCompiler::CompileStoreCallback(JSObject* object,
725 AccessorInfo* callback,
726 String* name) {
727 // ----------- S t a t e -------------
728 // -- r0 : value
729 // -- r2 : name
730 // -- lr : return address
731 // -- [sp] : receiver
732 // -----------------------------------
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000733 Label miss;
734
735 // Get the object from the stack.
736 __ ldr(r3, MemOperand(sp, 0 * kPointerSize));
737
738 // Check that the object isn't a smi.
739 __ tst(r3, Operand(kSmiTagMask));
740 __ b(eq, &miss);
741
742 // Check that the map of the object hasn't changed.
743 __ ldr(r1, FieldMemOperand(r3, HeapObject::kMapOffset));
744 __ cmp(r1, Operand(Handle<Map>(object->map())));
745 __ b(ne, &miss);
746
747 // Perform global security token check if needed.
kasperl@chromium.org5a8ca6c2008-10-23 13:57:19 +0000748 if (object->IsJSGlobalProxy()) {
749 __ CheckAccessGlobalProxy(r3, r1, &miss);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000750 }
751
752 // Stub never generated for non-global objects that require access
753 // checks.
kasperl@chromium.org5a8ca6c2008-10-23 13:57:19 +0000754 ASSERT(object->IsJSGlobalProxy() || !object->IsAccessCheckNeeded());
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000755
756 __ ldr(ip, MemOperand(sp)); // receiver
757 __ push(ip);
758 __ mov(ip, Operand(Handle<AccessorInfo>(callback))); // callback info
759 __ push(ip);
760 __ push(r2); // name
761 __ push(r0); // value
762
mads.s.ager31e71382008-08-13 09:32:07 +0000763 // Do tail-call to the runtime system.
764 ExternalReference store_callback_property =
765 ExternalReference(IC_Utility(IC::kStoreCallbackProperty));
766 __ TailCallRuntime(store_callback_property, 4);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000767
768 // Handle store cache miss.
769 __ bind(&miss);
770 __ mov(r2, Operand(Handle<String>(name))); // restore name
771 Handle<Code> ic(Builtins::builtin(Builtins::StoreIC_Miss));
ager@chromium.org236ad962008-09-25 09:45:57 +0000772 __ Jump(ic, RelocInfo::CODE_TARGET);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000773
774 // Return the generated code.
kasperl@chromium.org7be3c992009-03-12 07:19:55 +0000775 return GetCode(CALLBACKS, name);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000776}
777
778
779Object* StoreStubCompiler::CompileStoreInterceptor(JSObject* receiver,
780 String* name) {
781 // ----------- S t a t e -------------
782 // -- r0 : value
783 // -- r2 : name
784 // -- lr : return address
785 // -- [sp] : receiver
786 // -----------------------------------
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000787 Label miss;
788
789 // Get the object from the stack.
790 __ ldr(r3, MemOperand(sp, 0 * kPointerSize));
791
792 // Check that the object isn't a smi.
793 __ tst(r3, Operand(kSmiTagMask));
794 __ b(eq, &miss);
795
796 // Check that the map of the object hasn't changed.
797 __ ldr(r1, FieldMemOperand(r3, HeapObject::kMapOffset));
798 __ cmp(r1, Operand(Handle<Map>(receiver->map())));
799 __ b(ne, &miss);
800
801 // Perform global security token check if needed.
kasperl@chromium.org5a8ca6c2008-10-23 13:57:19 +0000802 if (receiver->IsJSGlobalProxy()) {
803 __ CheckAccessGlobalProxy(r3, r1, &miss);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000804 }
805
806 // Stub never generated for non-global objects that require access
807 // checks.
kasperl@chromium.org5a8ca6c2008-10-23 13:57:19 +0000808 ASSERT(receiver->IsJSGlobalProxy() || !receiver->IsAccessCheckNeeded());
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000809
810 __ ldr(ip, MemOperand(sp)); // receiver
811 __ push(ip);
812 __ push(r2); // name
813 __ push(r0); // value
814
mads.s.ager31e71382008-08-13 09:32:07 +0000815 // Do tail-call to the runtime system.
816 ExternalReference store_ic_property =
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000817 ExternalReference(IC_Utility(IC::kStoreInterceptorProperty));
mads.s.ager31e71382008-08-13 09:32:07 +0000818 __ TailCallRuntime(store_ic_property, 3);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000819
820 // Handle store cache miss.
821 __ bind(&miss);
822 __ mov(r2, Operand(Handle<String>(name))); // restore name
823 Handle<Code> ic(Builtins::builtin(Builtins::StoreIC_Miss));
ager@chromium.org236ad962008-09-25 09:45:57 +0000824 __ Jump(ic, RelocInfo::CODE_TARGET);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000825
826 // Return the generated code.
kasperl@chromium.org7be3c992009-03-12 07:19:55 +0000827 return GetCode(INTERCEPTOR, name);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000828}
829
830
831Object* LoadStubCompiler::CompileLoadField(JSObject* object,
832 JSObject* holder,
kasperl@chromium.org7be3c992009-03-12 07:19:55 +0000833 int index,
834 String* name) {
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000835 // ----------- S t a t e -------------
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000836 // -- r2 : name
837 // -- lr : return address
838 // -- [sp] : receiver
839 // -----------------------------------
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000840 Label miss;
841
mads.s.ager31e71382008-08-13 09:32:07 +0000842 __ ldr(r0, MemOperand(sp, 0));
843
ager@chromium.org3bf7b912008-11-17 09:09:45 +0000844 GenerateLoadField(masm(), object, holder, r0, r3, r1, index, &miss);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000845 __ bind(&miss);
ager@chromium.org3bf7b912008-11-17 09:09:45 +0000846 GenerateLoadMiss(masm(), Code::LOAD_IC);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000847
848 // Return the generated code.
kasperl@chromium.org7be3c992009-03-12 07:19:55 +0000849 return GetCode(FIELD, name);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000850}
851
852
853Object* LoadStubCompiler::CompileLoadCallback(JSObject* object,
854 JSObject* holder,
kasperl@chromium.org7be3c992009-03-12 07:19:55 +0000855 AccessorInfo* callback,
856 String* name) {
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000857 // ----------- S t a t e -------------
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000858 // -- r2 : name
859 // -- lr : return address
860 // -- [sp] : receiver
861 // -----------------------------------
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000862 Label miss;
863
mads.s.ager31e71382008-08-13 09:32:07 +0000864 __ ldr(r0, MemOperand(sp, 0));
ager@chromium.org3bf7b912008-11-17 09:09:45 +0000865 GenerateLoadCallback(masm(), object, holder, r0, r2, r3, r1, callback, &miss);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000866 __ bind(&miss);
ager@chromium.org3bf7b912008-11-17 09:09:45 +0000867 GenerateLoadMiss(masm(), Code::LOAD_IC);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000868
869 // Return the generated code.
kasperl@chromium.org7be3c992009-03-12 07:19:55 +0000870 return GetCode(CALLBACKS, name);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000871}
872
873
874Object* LoadStubCompiler::CompileLoadConstant(JSObject* object,
875 JSObject* holder,
kasperl@chromium.org7be3c992009-03-12 07:19:55 +0000876 Object* value,
877 String* name) {
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000878 // ----------- S t a t e -------------
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000879 // -- r2 : name
880 // -- lr : return address
881 // -- [sp] : receiver
882 // -----------------------------------
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000883 Label miss;
884
mads.s.ager31e71382008-08-13 09:32:07 +0000885 __ ldr(r0, MemOperand(sp, 0));
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000886
ager@chromium.org3bf7b912008-11-17 09:09:45 +0000887 GenerateLoadConstant(masm(), object, holder, r0, r3, r1, value, &miss);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000888 __ bind(&miss);
ager@chromium.org3bf7b912008-11-17 09:09:45 +0000889 GenerateLoadMiss(masm(), Code::LOAD_IC);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000890
891 // Return the generated code.
kasperl@chromium.org7be3c992009-03-12 07:19:55 +0000892 return GetCode(CONSTANT_FUNCTION, name);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000893}
894
895
896Object* LoadStubCompiler::CompileLoadInterceptor(JSObject* object,
897 JSObject* holder,
898 String* name) {
899 // ----------- S t a t e -------------
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000900 // -- r2 : name
901 // -- lr : return address
902 // -- [sp] : receiver
903 // -----------------------------------
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000904 Label miss;
905
mads.s.ager31e71382008-08-13 09:32:07 +0000906 __ ldr(r0, MemOperand(sp, 0));
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000907
ager@chromium.org3bf7b912008-11-17 09:09:45 +0000908 GenerateLoadInterceptor(masm(), object, holder, r0, r2, r3, r1, &miss);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000909 __ bind(&miss);
ager@chromium.org3bf7b912008-11-17 09:09:45 +0000910 GenerateLoadMiss(masm(), Code::LOAD_IC);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000911
912 // Return the generated code.
kasperl@chromium.org7be3c992009-03-12 07:19:55 +0000913 return GetCode(INTERCEPTOR, name);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000914}
915
916
917// TODO(1224671): IC stubs for keyed loads have not been implemented
918// for ARM.
919Object* KeyedLoadStubCompiler::CompileLoadField(String* name,
920 JSObject* receiver,
921 JSObject* holder,
922 int index) {
ager@chromium.org3bf7b912008-11-17 09:09:45 +0000923 // ----------- S t a t e -------------
924 // -- lr : return address
925 // -- sp[0] : key
926 // -- sp[4] : receiver
927 // -----------------------------------
ager@chromium.org3bf7b912008-11-17 09:09:45 +0000928 Label miss;
929
930 __ ldr(r2, MemOperand(sp, 0));
931 __ ldr(r0, MemOperand(sp, kPointerSize));
932
933 __ cmp(r2, Operand(Handle<String>(name)));
934 __ b(ne, &miss);
935
936 GenerateLoadField(masm(), receiver, holder, r0, r3, r1, index, &miss);
937 __ bind(&miss);
938 GenerateLoadMiss(masm(), Code::KEYED_LOAD_IC);
939
kasperl@chromium.org7be3c992009-03-12 07:19:55 +0000940 return GetCode(FIELD, name);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000941}
942
943
944Object* KeyedLoadStubCompiler::CompileLoadCallback(String* name,
945 JSObject* receiver,
946 JSObject* holder,
947 AccessorInfo* callback) {
ager@chromium.org3bf7b912008-11-17 09:09:45 +0000948 // ----------- S t a t e -------------
949 // -- lr : return address
950 // -- sp[0] : key
951 // -- sp[4] : receiver
952 // -----------------------------------
ager@chromium.org3bf7b912008-11-17 09:09:45 +0000953 Label miss;
954
955 __ ldr(r2, MemOperand(sp, 0));
956 __ ldr(r0, MemOperand(sp, kPointerSize));
957
958 __ cmp(r2, Operand(Handle<String>(name)));
959 __ b(ne, &miss);
960
961 GenerateLoadCallback(masm(), receiver, holder, r0, r2, r3,
962 r1, callback, &miss);
963 __ bind(&miss);
964 GenerateLoadMiss(masm(), Code::KEYED_LOAD_IC);
965
kasperl@chromium.org7be3c992009-03-12 07:19:55 +0000966 return GetCode(CALLBACKS, name);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000967}
968
969
970Object* KeyedLoadStubCompiler::CompileLoadConstant(String* name,
971 JSObject* receiver,
972 JSObject* holder,
973 Object* value) {
ager@chromium.org3bf7b912008-11-17 09:09:45 +0000974 // ----------- S t a t e -------------
975 // -- lr : return address
976 // -- sp[0] : key
977 // -- sp[4] : receiver
978 // -----------------------------------
ager@chromium.org3bf7b912008-11-17 09:09:45 +0000979 Label miss;
980
981 // Check the key is the cached one
982 __ ldr(r2, MemOperand(sp, 0));
983 __ ldr(r0, MemOperand(sp, kPointerSize));
984
985 __ cmp(r2, Operand(Handle<String>(name)));
986 __ b(ne, &miss);
987
988 GenerateLoadConstant(masm(), receiver, holder, r0, r3, r1, value, &miss);
989 __ bind(&miss);
990 GenerateLoadMiss(masm(), Code::KEYED_LOAD_IC);
991
992 // Return the generated code.
kasperl@chromium.org7be3c992009-03-12 07:19:55 +0000993 return GetCode(CONSTANT_FUNCTION, name);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000994}
995
996
997Object* KeyedLoadStubCompiler::CompileLoadInterceptor(JSObject* receiver,
998 JSObject* holder,
999 String* name) {
ager@chromium.org3bf7b912008-11-17 09:09:45 +00001000 // ----------- S t a t e -------------
1001 // -- lr : return address
1002 // -- sp[0] : key
1003 // -- sp[4] : receiver
1004 // -----------------------------------
ager@chromium.org3bf7b912008-11-17 09:09:45 +00001005 Label miss;
1006
1007 // Check the key is the cached one
1008 __ ldr(r2, MemOperand(sp, 0));
1009 __ ldr(r0, MemOperand(sp, kPointerSize));
1010
1011 __ cmp(r2, Operand(Handle<String>(name)));
1012 __ b(ne, &miss);
1013
1014 GenerateLoadInterceptor(masm(), receiver, holder, r0, r2, r3, r1, &miss);
1015 __ bind(&miss);
1016 GenerateLoadMiss(masm(), Code::KEYED_LOAD_IC);
1017
kasperl@chromium.org7be3c992009-03-12 07:19:55 +00001018 return GetCode(INTERCEPTOR, name);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001019}
1020
1021
1022Object* KeyedLoadStubCompiler::CompileLoadArrayLength(String* name) {
ager@chromium.org3bf7b912008-11-17 09:09:45 +00001023 // ----------- S t a t e -------------
1024 // -- lr : return address
1025 // -- sp[0] : key
1026 // -- sp[4] : receiver
1027 // -----------------------------------
ager@chromium.org3bf7b912008-11-17 09:09:45 +00001028 Label miss;
1029
1030 // Check the key is the cached one
1031 __ ldr(r2, MemOperand(sp, 0));
1032 __ ldr(r0, MemOperand(sp, kPointerSize));
1033
1034 __ cmp(r2, Operand(Handle<String>(name)));
1035 __ b(ne, &miss);
1036
1037 GenerateLoadArrayLength(masm(), r0, r3, &miss);
1038 __ bind(&miss);
1039 GenerateLoadMiss(masm(), Code::KEYED_LOAD_IC);
1040
kasperl@chromium.org7be3c992009-03-12 07:19:55 +00001041 return GetCode(CALLBACKS, name);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001042}
1043
1044
kasperl@chromium.org9fe21c62008-10-28 08:53:51 +00001045Object* KeyedLoadStubCompiler::CompileLoadStringLength(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.orga74f0da2008-12-03 16:05:52 +00001051 Label miss;
1052 __ IncrementCounter(&Counters::keyed_load_string_length, 1, r1, r3);
1053
1054 __ ldr(r2, MemOperand(sp));
1055 __ ldr(r0, MemOperand(sp, kPointerSize)); // receiver
1056
1057 __ cmp(r2, Operand(Handle<String>(name)));
1058 __ b(ne, &miss);
1059
1060 GenerateLoadStringLength2(masm(), r0, r1, r3, &miss);
1061 __ bind(&miss);
1062 __ DecrementCounter(&Counters::keyed_load_string_length, 1, r1, r3);
1063
ager@chromium.org3bf7b912008-11-17 09:09:45 +00001064 GenerateLoadMiss(masm(), Code::KEYED_LOAD_IC);
1065
kasperl@chromium.org7be3c992009-03-12 07:19:55 +00001066 return GetCode(CALLBACKS, name);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001067}
1068
1069
ager@chromium.org3bf7b912008-11-17 09:09:45 +00001070// TODO(1224671): implement the fast case.
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001071Object* KeyedLoadStubCompiler::CompileLoadFunctionPrototype(String* name) {
ager@chromium.org3bf7b912008-11-17 09:09:45 +00001072 // ----------- S t a t e -------------
1073 // -- lr : return address
1074 // -- sp[0] : key
1075 // -- sp[4] : receiver
1076 // -----------------------------------
ager@chromium.org3bf7b912008-11-17 09:09:45 +00001077 GenerateLoadMiss(masm(), Code::KEYED_LOAD_IC);
1078
kasperl@chromium.org7be3c992009-03-12 07:19:55 +00001079 return GetCode(CALLBACKS, name);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001080}
1081
1082
1083Object* KeyedStoreStubCompiler::CompileStoreField(JSObject* object,
1084 int index,
1085 Map* transition,
1086 String* name) {
ager@chromium.org3bf7b912008-11-17 09:09:45 +00001087 // ----------- S t a t e -------------
1088 // -- r0 : value
1089 // -- r2 : name
1090 // -- lr : return address
1091 // -- [sp] : receiver
1092 // -----------------------------------
ager@chromium.orga74f0da2008-12-03 16:05:52 +00001093 Label miss;
1094
1095 __ IncrementCounter(&Counters::keyed_store_field, 1, r1, r3);
1096
1097 // Check that the name has not changed.
1098 __ cmp(r2, Operand(Handle<String>(name)));
1099 __ b(ne, &miss);
1100
1101 // Load receiver from the stack.
1102 __ ldr(r3, MemOperand(sp));
1103 // r1 is used as scratch register, r3 and r2 might be clobbered.
1104 GenerateStoreField(masm(),
1105 Builtins::StoreIC_ExtendStorage,
1106 object,
1107 index,
1108 transition,
1109 r3, r2, r1,
1110 &miss);
1111 __ bind(&miss);
1112
1113 __ DecrementCounter(&Counters::keyed_store_field, 1, r1, r3);
1114 __ mov(r2, Operand(Handle<String>(name))); // restore name register.
ager@chromium.org3bf7b912008-11-17 09:09:45 +00001115 Handle<Code> ic(Builtins::builtin(Builtins::KeyedStoreIC_Miss));
1116 __ Jump(ic, RelocInfo::CODE_TARGET);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001117
ager@chromium.org3bf7b912008-11-17 09:09:45 +00001118 // Return the generated code.
kasperl@chromium.org7be3c992009-03-12 07:19:55 +00001119 return GetCode(transition == NULL ? FIELD : MAP_TRANSITION, name);
ager@chromium.org3bf7b912008-11-17 09:09:45 +00001120}
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001121
1122
1123#undef __
1124
1125} } // namespace v8::internal