blob: abf2f643cd3872a12056da27f038b2c1de8194fb [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,
kasperl@chromium.org86f77b72009-07-06 08:21:57 +000088 Register scratch,
89 Register extra) {
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +000090 Label miss;
91
92 // Make sure that code is valid. The shifting code relies on the
93 // entry size being 8.
94 ASSERT(sizeof(Entry) == 8);
95
96 // Make sure the flags does not name a specific type.
97 ASSERT(Code::ExtractTypeFromFlags(flags) == 0);
98
99 // Make sure that there are no register conflicts.
100 ASSERT(!scratch.is(receiver));
101 ASSERT(!scratch.is(name));
102
103 // Check that the receiver isn't a smi.
104 __ tst(receiver, Operand(kSmiTagMask));
105 __ b(eq, &miss);
106
107 // Get the map of the receiver and compute the hash.
sgjesse@chromium.orgac6aa172009-12-04 12:29:05 +0000108 __ ldr(scratch, FieldMemOperand(name, String::kHashFieldOffset));
ager@chromium.org7c537e22008-10-16 08:43:32 +0000109 __ ldr(ip, FieldMemOperand(receiver, HeapObject::kMapOffset));
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000110 __ add(scratch, scratch, Operand(ip));
111 __ eor(scratch, scratch, Operand(flags));
112 __ and_(scratch,
113 scratch,
114 Operand((kPrimaryTableSize - 1) << kHeapObjectTagSize));
115
116 // Probe the primary table.
117 ProbeTable(masm, flags, kPrimary, name, scratch);
118
119 // Primary miss: Compute hash for secondary probe.
120 __ sub(scratch, scratch, Operand(name));
121 __ add(scratch, scratch, Operand(flags));
122 __ and_(scratch,
123 scratch,
124 Operand((kSecondaryTableSize - 1) << kHeapObjectTagSize));
125
126 // Probe the secondary table.
127 ProbeTable(masm, flags, kSecondary, name, scratch);
128
129 // Cache miss: Fall-through and let caller handle the miss by
130 // entering the runtime system.
131 __ bind(&miss);
132}
133
134
135void StubCompiler::GenerateLoadGlobalFunctionPrototype(MacroAssembler* masm,
136 int index,
137 Register prototype) {
138 // Load the global or builtins object from the current context.
139 __ ldr(prototype, MemOperand(cp, Context::SlotOffset(Context::GLOBAL_INDEX)));
140 // Load the global context from the global or builtins object.
141 __ ldr(prototype,
142 FieldMemOperand(prototype, GlobalObject::kGlobalContextOffset));
143 // Load the function from the global context.
144 __ ldr(prototype, MemOperand(prototype, Context::SlotOffset(index)));
145 // Load the initial map. The global functions all have initial maps.
146 __ ldr(prototype,
147 FieldMemOperand(prototype, JSFunction::kPrototypeOrInitialMapOffset));
148 // Load the prototype from the initial map.
149 __ ldr(prototype, FieldMemOperand(prototype, Map::kPrototypeOffset));
150}
151
152
ager@chromium.org7c537e22008-10-16 08:43:32 +0000153// Load a fast property out of a holder object (src). In-object properties
154// are loaded directly otherwise the property is loaded from the properties
155// fixed array.
156void StubCompiler::GenerateFastPropertyLoad(MacroAssembler* masm,
157 Register dst, Register src,
158 JSObject* holder, int index) {
159 // Adjust for the number of properties stored in the holder.
160 index -= holder->map()->inobject_properties();
161 if (index < 0) {
162 // Get the property straight out of the holder.
163 int offset = holder->map()->instance_size() + (index * kPointerSize);
164 __ ldr(dst, FieldMemOperand(src, offset));
165 } else {
166 // Calculate the offset into the properties array.
kasperl@chromium.orge959c182009-07-27 08:59:04 +0000167 int offset = index * kPointerSize + FixedArray::kHeaderSize;
ager@chromium.org7c537e22008-10-16 08:43:32 +0000168 __ ldr(dst, FieldMemOperand(src, JSObject::kPropertiesOffset));
169 __ ldr(dst, FieldMemOperand(dst, offset));
170 }
171}
172
173
ager@chromium.org3bf7b912008-11-17 09:09:45 +0000174void StubCompiler::GenerateLoadArrayLength(MacroAssembler* masm,
175 Register receiver,
176 Register scratch,
177 Label* miss_label) {
178 // Check that the receiver isn't a smi.
179 __ tst(receiver, Operand(kSmiTagMask));
180 __ b(eq, miss_label);
181
182 // Check that the object is a JS array.
ager@chromium.orgeadaf222009-06-16 09:43:10 +0000183 __ CompareObjectType(receiver, scratch, scratch, JS_ARRAY_TYPE);
ager@chromium.org3bf7b912008-11-17 09:09:45 +0000184 __ b(ne, miss_label);
185
186 // Load length directly from the JS array.
187 __ ldr(r0, FieldMemOperand(receiver, JSArray::kLengthOffset));
188 __ Ret();
189}
190
191
ager@chromium.org5c838252010-02-19 08:53:10 +0000192// Generate code to check if an object is a string. If the object is a
193// heap object, its map's instance type is left in the scratch1 register.
194// If this is not needed, scratch1 and scratch2 may be the same register.
ager@chromium.orga74f0da2008-12-03 16:05:52 +0000195static void GenerateStringCheck(MacroAssembler* masm,
196 Register receiver,
197 Register scratch1,
198 Register scratch2,
199 Label* smi,
200 Label* non_string_object) {
201 // Check that the receiver isn't a smi.
202 __ tst(receiver, Operand(kSmiTagMask));
203 __ b(eq, smi);
204
205 // Check that the object is a string.
206 __ ldr(scratch1, FieldMemOperand(receiver, HeapObject::kMapOffset));
207 __ ldrb(scratch1, FieldMemOperand(scratch1, Map::kInstanceTypeOffset));
208 __ and_(scratch2, scratch1, Operand(kIsNotStringMask));
209 // The cast is to resolve the overload for the argument of 0x0.
210 __ cmp(scratch2, Operand(static_cast<int32_t>(kStringTag)));
211 __ b(ne, non_string_object);
212}
213
214
ager@chromium.org32912102009-01-16 10:38:43 +0000215// Generate code to load the length from a string object and return the length.
216// If the receiver object is not a string or a wrapped string object the
217// execution continues at the miss label. The register containing the
218// receiver is potentially clobbered.
ager@chromium.org5c838252010-02-19 08:53:10 +0000219void StubCompiler::GenerateLoadStringLength(MacroAssembler* masm,
220 Register receiver,
221 Register scratch1,
222 Register scratch2,
223 Label* miss) {
224 Label check_wrapper;
ager@chromium.orga74f0da2008-12-03 16:05:52 +0000225
226 // Check if the object is a string leaving the instance type in the
227 // scratch1 register.
ager@chromium.org5c838252010-02-19 08:53:10 +0000228 GenerateStringCheck(masm, receiver, scratch1, scratch2, miss, &check_wrapper);
ager@chromium.orga74f0da2008-12-03 16:05:52 +0000229
230 // Load length directly from the string.
ager@chromium.orga74f0da2008-12-03 16:05:52 +0000231 __ ldr(r0, FieldMemOperand(receiver, String::kLengthOffset));
ager@chromium.orga74f0da2008-12-03 16:05:52 +0000232 __ mov(r0, Operand(r0, LSL, kSmiTagSize));
233 __ Ret();
234
235 // Check if the object is a JSValue wrapper.
236 __ bind(&check_wrapper);
237 __ cmp(scratch1, Operand(JS_VALUE_TYPE));
238 __ b(ne, miss);
239
ager@chromium.org5c838252010-02-19 08:53:10 +0000240 // Unwrap the value and check if the wrapped value is a string.
241 __ ldr(scratch1, FieldMemOperand(receiver, JSValue::kValueOffset));
242 GenerateStringCheck(masm, scratch1, scratch2, scratch2, miss, miss);
243 __ ldr(r0, FieldMemOperand(scratch1, String::kLengthOffset));
244 __ mov(r0, Operand(r0, LSL, kSmiTagSize));
245 __ Ret();
ager@chromium.orga74f0da2008-12-03 16:05:52 +0000246}
247
248
kasperl@chromium.orgdefbd102009-07-13 14:04:26 +0000249void StubCompiler::GenerateLoadFunctionPrototype(MacroAssembler* masm,
250 Register receiver,
251 Register scratch1,
252 Register scratch2,
253 Label* miss_label) {
254 __ TryGetFunctionPrototype(receiver, scratch1, scratch2, miss_label);
255 __ mov(r0, scratch1);
256 __ Ret();
257}
258
259
ager@chromium.orga74f0da2008-12-03 16:05:52 +0000260// Generate StoreField code, value is passed in r0 register.
ager@chromium.org5c838252010-02-19 08:53:10 +0000261// When leaving generated code after success, the receiver_reg and name_reg
262// may be clobbered. Upon branch to miss_label, the receiver and name
263// registers have their original values.
ager@chromium.orga74f0da2008-12-03 16:05:52 +0000264void StubCompiler::GenerateStoreField(MacroAssembler* masm,
ager@chromium.orga74f0da2008-12-03 16:05:52 +0000265 JSObject* object,
266 int index,
267 Map* transition,
268 Register receiver_reg,
269 Register name_reg,
270 Register scratch,
271 Label* miss_label) {
272 // r0 : value
273 Label exit;
274
275 // Check that the receiver isn't a smi.
276 __ tst(receiver_reg, Operand(kSmiTagMask));
277 __ b(eq, miss_label);
278
279 // Check that the map of the receiver hasn't changed.
280 __ ldr(scratch, FieldMemOperand(receiver_reg, HeapObject::kMapOffset));
281 __ cmp(scratch, Operand(Handle<Map>(object->map())));
282 __ b(ne, miss_label);
283
284 // Perform global security token check if needed.
285 if (object->IsJSGlobalProxy()) {
286 __ CheckAccessGlobalProxy(receiver_reg, scratch, miss_label);
287 }
288
289 // Stub never generated for non-global objects that require access
290 // checks.
291 ASSERT(object->IsJSGlobalProxy() || !object->IsAccessCheckNeeded());
292
293 // Perform map transition for the receiver if necessary.
294 if ((transition != NULL) && (object->map()->unused_property_fields() == 0)) {
295 // The properties must be extended before we can store the value.
ager@chromium.org32912102009-01-16 10:38:43 +0000296 // We jump to a runtime call that extends the properties array.
ager@chromium.org5c838252010-02-19 08:53:10 +0000297 __ push(receiver_reg);
ager@chromium.orga74f0da2008-12-03 16:05:52 +0000298 __ mov(r2, Operand(Handle<Map>(transition)));
ager@chromium.org5c838252010-02-19 08:53:10 +0000299 __ stm(db_w, sp, r2.bit() | r0.bit());
ager@chromium.orgce5e87b2010-03-10 10:24:18 +0000300 __ TailCallExternalReference(
ager@chromium.org5c838252010-02-19 08:53:10 +0000301 ExternalReference(IC_Utility(IC::kSharedStoreIC_ExtendStorage)),
302 3, 1);
ager@chromium.orga74f0da2008-12-03 16:05:52 +0000303 return;
304 }
305
306 if (transition != NULL) {
307 // Update the map of the object; no write barrier updating is
308 // needed because the map is never in new space.
309 __ mov(ip, Operand(Handle<Map>(transition)));
310 __ str(ip, FieldMemOperand(receiver_reg, HeapObject::kMapOffset));
311 }
312
313 // Adjust for the number of properties stored in the object. Even in the
314 // face of a transition we can use the old map here because the size of the
315 // object and the number of in-object properties is not going to change.
316 index -= object->map()->inobject_properties();
317
318 if (index < 0) {
319 // Set the property straight into the object.
320 int offset = object->map()->instance_size() + (index * kPointerSize);
321 __ str(r0, FieldMemOperand(receiver_reg, offset));
322
323 // Skip updating write barrier if storing a smi.
324 __ tst(r0, Operand(kSmiTagMask));
325 __ b(eq, &exit);
326
327 // Update the write barrier for the array address.
328 // Pass the value being stored in the now unused name_reg.
329 __ mov(name_reg, Operand(offset));
330 __ RecordWrite(receiver_reg, name_reg, scratch);
331 } else {
332 // Write to the properties array.
kasperl@chromium.orge959c182009-07-27 08:59:04 +0000333 int offset = index * kPointerSize + FixedArray::kHeaderSize;
ager@chromium.orga74f0da2008-12-03 16:05:52 +0000334 // Get the properties array
335 __ ldr(scratch, FieldMemOperand(receiver_reg, JSObject::kPropertiesOffset));
336 __ str(r0, FieldMemOperand(scratch, offset));
337
338 // Skip updating write barrier if storing a smi.
339 __ tst(r0, Operand(kSmiTagMask));
340 __ b(eq, &exit);
341
342 // Update the write barrier for the array address.
343 // Ok to clobber receiver_reg and name_reg, since we return.
344 __ mov(name_reg, Operand(offset));
345 __ RecordWrite(scratch, name_reg, receiver_reg);
346 }
347
348 // Return the value (register r0).
349 __ bind(&exit);
350 __ Ret();
351}
352
353
ager@chromium.org3bf7b912008-11-17 09:09:45 +0000354void StubCompiler::GenerateLoadMiss(MacroAssembler* masm, Code::Kind kind) {
355 ASSERT(kind == Code::LOAD_IC || kind == Code::KEYED_LOAD_IC);
356 Code* code = NULL;
357 if (kind == Code::LOAD_IC) {
358 code = Builtins::builtin(Builtins::LoadIC_Miss);
359 } else {
360 code = Builtins::builtin(Builtins::KeyedLoadIC_Miss);
361 }
362
363 Handle<Code> ic(code);
364 __ Jump(ic, RelocInfo::CODE_TARGET);
365}
366
367
sgjesse@chromium.orgb302e562010-02-03 11:26:59 +0000368static void GenerateCallFunction(MacroAssembler* masm,
369 Object* object,
370 const ParameterCount& arguments,
371 Label* miss) {
372 // ----------- S t a t e -------------
373 // -- r0: receiver
374 // -- r1: function to call
375 // -----------------------------------
376
377 // Check that the function really is a function.
378 __ BranchOnSmi(r1, miss);
ager@chromium.org5c838252010-02-19 08:53:10 +0000379 __ CompareObjectType(r1, r3, r3, JS_FUNCTION_TYPE);
sgjesse@chromium.orgb302e562010-02-03 11:26:59 +0000380 __ b(ne, miss);
381
382 // Patch the receiver on the stack with the global proxy if
383 // necessary.
384 if (object->IsGlobalObject()) {
385 __ ldr(r3, FieldMemOperand(r0, GlobalObject::kGlobalReceiverOffset));
386 __ str(r3, MemOperand(sp, arguments.immediate() * kPointerSize));
387 }
388
389 // Invoke the function.
390 __ InvokeFunction(r1, arguments, JUMP_FUNCTION);
391}
392
393
sgjesse@chromium.orgb302e562010-02-03 11:26:59 +0000394static void PushInterceptorArguments(MacroAssembler* masm,
395 Register receiver,
396 Register holder,
397 Register name,
398 JSObject* holder_obj) {
399 __ push(receiver);
400 __ push(holder);
401 __ push(name);
402 InterceptorInfo* interceptor = holder_obj->GetNamedInterceptor();
403 ASSERT(!Heap::InNewSpace(interceptor));
404
405 Register scratch = receiver;
406 __ mov(scratch, Operand(Handle<Object>(interceptor)));
407 __ push(scratch);
408 __ ldr(scratch, FieldMemOperand(scratch, InterceptorInfo::kDataOffset));
409 __ push(scratch);
410}
411
412
413static void CompileCallLoadPropertyWithInterceptor(MacroAssembler* masm,
414 Register receiver,
415 Register holder,
416 Register name,
417 JSObject* holder_obj) {
418 PushInterceptorArguments(masm, receiver, holder, name, holder_obj);
419
420 ExternalReference ref =
421 ExternalReference(IC_Utility(IC::kLoadPropertyWithInterceptorOnly));
422 __ mov(r0, Operand(5));
423 __ mov(r1, Operand(ref));
424
425 CEntryStub stub(1);
426 __ CallStub(&stub);
427}
428
429
430class LoadInterceptorCompiler BASE_EMBEDDED {
431 public:
432 explicit LoadInterceptorCompiler(Register name) : name_(name) {}
433
434 void CompileCacheable(MacroAssembler* masm,
435 StubCompiler* stub_compiler,
436 Register receiver,
437 Register holder,
438 Register scratch1,
439 Register scratch2,
440 JSObject* holder_obj,
441 LookupResult* lookup,
442 String* name,
443 Label* miss_label) {
ager@chromium.org5c838252010-02-19 08:53:10 +0000444 AccessorInfo* callback = NULL;
sgjesse@chromium.orgb302e562010-02-03 11:26:59 +0000445 bool optimize = false;
446 // So far the most popular follow ups for interceptor loads are FIELD
447 // and CALLBACKS, so inline only them, other cases may be added
448 // later.
449 if (lookup->type() == FIELD) {
450 optimize = true;
451 } else if (lookup->type() == CALLBACKS) {
452 Object* callback_object = lookup->GetCallbackObject();
453 if (callback_object->IsAccessorInfo()) {
454 callback = AccessorInfo::cast(callback_object);
455 optimize = callback->getter() != NULL;
456 }
457 }
458
459 if (!optimize) {
460 CompileRegular(masm, receiver, holder, scratch2, holder_obj, miss_label);
461 return;
462 }
463
464 // Note: starting a frame here makes GC aware of pointers pushed below.
465 __ EnterInternalFrame();
466
ager@chromium.org5c838252010-02-19 08:53:10 +0000467 __ push(receiver);
sgjesse@chromium.orgb302e562010-02-03 11:26:59 +0000468 __ push(holder);
469 __ push(name_);
470
471 CompileCallLoadPropertyWithInterceptor(masm,
472 receiver,
473 holder,
474 name_,
475 holder_obj);
476
477 Label interceptor_failed;
478 // Compare with no_interceptor_result_sentinel.
479 __ LoadRoot(scratch1, Heap::kNoInterceptorResultSentinelRootIndex);
480 __ cmp(r0, scratch1);
481 __ b(eq, &interceptor_failed);
482 __ LeaveInternalFrame();
483 __ Ret();
484
485 __ bind(&interceptor_failed);
486 __ pop(name_);
487 __ pop(holder);
ager@chromium.org5c838252010-02-19 08:53:10 +0000488 __ pop(receiver);
sgjesse@chromium.orgb302e562010-02-03 11:26:59 +0000489
490 __ LeaveInternalFrame();
491
492 if (lookup->type() == FIELD) {
493 holder = stub_compiler->CheckPrototypes(holder_obj,
494 holder,
495 lookup->holder(),
496 scratch1,
497 scratch2,
498 name,
499 miss_label);
500 stub_compiler->GenerateFastPropertyLoad(masm,
501 r0,
502 holder,
503 lookup->holder(),
504 lookup->GetFieldIndex());
505 __ Ret();
506 } else {
507 ASSERT(lookup->type() == CALLBACKS);
508 ASSERT(lookup->GetCallbackObject()->IsAccessorInfo());
509 ASSERT(callback != NULL);
510 ASSERT(callback->getter() != NULL);
511
512 Label cleanup;
513 __ pop(scratch2);
514 __ push(receiver);
515 __ push(scratch2);
516
517 holder = stub_compiler->CheckPrototypes(holder_obj, holder,
518 lookup->holder(), scratch1,
519 scratch2,
520 name,
521 &cleanup);
522
523 __ push(holder);
524 __ Move(holder, Handle<AccessorInfo>(callback));
525 __ push(holder);
526 __ ldr(scratch1, FieldMemOperand(holder, AccessorInfo::kDataOffset));
527 __ push(scratch1);
528 __ push(name_);
529
530 ExternalReference ref =
531 ExternalReference(IC_Utility(IC::kLoadCallbackProperty));
ager@chromium.orgce5e87b2010-03-10 10:24:18 +0000532 __ TailCallExternalReference(ref, 5, 1);
sgjesse@chromium.orgb302e562010-02-03 11:26:59 +0000533
534 __ bind(&cleanup);
535 __ pop(scratch1);
536 __ pop(scratch2);
537 __ push(scratch1);
538 }
539 }
540
541
542 void CompileRegular(MacroAssembler* masm,
543 Register receiver,
544 Register holder,
545 Register scratch,
546 JSObject* holder_obj,
547 Label* miss_label) {
548 PushInterceptorArguments(masm, receiver, holder, name_, holder_obj);
549
550 ExternalReference ref = ExternalReference(
551 IC_Utility(IC::kLoadPropertyWithInterceptorForLoad));
ager@chromium.orgce5e87b2010-03-10 10:24:18 +0000552 __ TailCallExternalReference(ref, 5, 1);
sgjesse@chromium.orgb302e562010-02-03 11:26:59 +0000553 }
554
555 private:
556 Register name_;
557};
558
559
ager@chromium.org5c838252010-02-19 08:53:10 +0000560static void CompileLoadInterceptor(LoadInterceptorCompiler* compiler,
561 StubCompiler* stub_compiler,
562 MacroAssembler* masm,
563 JSObject* object,
564 JSObject* holder,
565 String* name,
566 LookupResult* lookup,
567 Register receiver,
568 Register scratch1,
569 Register scratch2,
570 Label* miss) {
571 ASSERT(holder->HasNamedInterceptor());
572 ASSERT(!holder->GetNamedInterceptor()->getter()->IsUndefined());
sgjesse@chromium.orgb302e562010-02-03 11:26:59 +0000573
ager@chromium.org5c838252010-02-19 08:53:10 +0000574 // Check that the receiver isn't a smi.
575 __ BranchOnSmi(receiver, miss);
sgjesse@chromium.orgb302e562010-02-03 11:26:59 +0000576
ager@chromium.org5c838252010-02-19 08:53:10 +0000577 // Check that the maps haven't changed.
578 Register reg =
579 stub_compiler->CheckPrototypes(object, receiver, holder,
580 scratch1, scratch2, name, miss);
sgjesse@chromium.orgb302e562010-02-03 11:26:59 +0000581
ager@chromium.org5c838252010-02-19 08:53:10 +0000582 if (lookup->IsProperty() && lookup->IsCacheable()) {
583 compiler->CompileCacheable(masm,
584 stub_compiler,
585 receiver,
586 reg,
587 scratch1,
588 scratch2,
589 holder,
590 lookup,
591 name,
592 miss);
593 } else {
594 compiler->CompileRegular(masm,
sgjesse@chromium.orgb302e562010-02-03 11:26:59 +0000595 receiver,
ager@chromium.org5c838252010-02-19 08:53:10 +0000596 reg,
597 scratch2,
sgjesse@chromium.orgb302e562010-02-03 11:26:59 +0000598 holder,
ager@chromium.org5c838252010-02-19 08:53:10 +0000599 miss);
sgjesse@chromium.orgb302e562010-02-03 11:26:59 +0000600 }
ager@chromium.org5c838252010-02-19 08:53:10 +0000601}
sgjesse@chromium.orgb302e562010-02-03 11:26:59 +0000602
603
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000604#undef __
ager@chromium.org65dad4b2009-04-23 08:48:43 +0000605#define __ ACCESS_MASM(masm())
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000606
607
kasperl@chromium.orgdefbd102009-07-13 14:04:26 +0000608Register StubCompiler::CheckPrototypes(JSObject* object,
609 Register object_reg,
610 JSObject* holder,
611 Register holder_reg,
612 Register scratch,
613 String* name,
ager@chromium.org5c838252010-02-19 08:53:10 +0000614 int save_at_depth,
kasperl@chromium.orgdefbd102009-07-13 14:04:26 +0000615 Label* miss) {
ager@chromium.org5c838252010-02-19 08:53:10 +0000616 // TODO(602): support object saving.
617 ASSERT(save_at_depth == kInvalidProtoDepth);
618
kasperl@chromium.orgdefbd102009-07-13 14:04:26 +0000619 // Check that the maps haven't changed.
620 Register result =
621 masm()->CheckMaps(object, object_reg, holder, holder_reg, scratch, miss);
622
623 // If we've skipped any global objects, it's not enough to verify
624 // that their maps haven't changed.
625 while (object != holder) {
626 if (object->IsGlobalObject()) {
627 GlobalObject* global = GlobalObject::cast(object);
628 Object* probe = global->EnsurePropertyCell(name);
629 if (probe->IsFailure()) {
630 set_failure(Failure::cast(probe));
631 return result;
632 }
633 JSGlobalPropertyCell* cell = JSGlobalPropertyCell::cast(probe);
634 ASSERT(cell->value()->IsTheHole());
635 __ mov(scratch, Operand(Handle<Object>(cell)));
636 __ ldr(scratch,
637 FieldMemOperand(scratch, JSGlobalPropertyCell::kValueOffset));
ager@chromium.orgab99eea2009-08-25 07:05:41 +0000638 __ LoadRoot(ip, Heap::kTheHoleValueRootIndex);
639 __ cmp(scratch, ip);
kasperl@chromium.orgdefbd102009-07-13 14:04:26 +0000640 __ b(ne, miss);
641 }
642 object = JSObject::cast(object->GetPrototype());
643 }
644
ager@chromium.org5c838252010-02-19 08:53:10 +0000645 // Return the register containing the holder.
kasperl@chromium.orgdefbd102009-07-13 14:04:26 +0000646 return result;
647}
648
649
650void StubCompiler::GenerateLoadField(JSObject* object,
651 JSObject* holder,
652 Register receiver,
653 Register scratch1,
654 Register scratch2,
655 int index,
656 String* name,
657 Label* miss) {
658 // Check that the receiver isn't a smi.
659 __ tst(receiver, Operand(kSmiTagMask));
660 __ b(eq, miss);
661
662 // Check that the maps haven't changed.
663 Register reg =
664 CheckPrototypes(object, receiver, holder, scratch1, scratch2, name, miss);
665 GenerateFastPropertyLoad(masm(), r0, reg, holder, index);
666 __ Ret();
667}
668
669
670void StubCompiler::GenerateLoadConstant(JSObject* object,
671 JSObject* holder,
672 Register receiver,
673 Register scratch1,
674 Register scratch2,
675 Object* value,
676 String* name,
677 Label* miss) {
678 // Check that the receiver isn't a smi.
679 __ tst(receiver, Operand(kSmiTagMask));
680 __ b(eq, miss);
681
682 // Check that the maps haven't changed.
683 Register reg =
684 CheckPrototypes(object, receiver, holder, scratch1, scratch2, name, miss);
685
686 // Return the constant value.
687 __ mov(r0, Operand(Handle<Object>(value)));
688 __ Ret();
689}
690
691
kmillikin@chromium.org13bd2942009-12-16 15:36:05 +0000692bool StubCompiler::GenerateLoadCallback(JSObject* object,
kasperl@chromium.orgdefbd102009-07-13 14:04:26 +0000693 JSObject* holder,
694 Register receiver,
695 Register name_reg,
696 Register scratch1,
697 Register scratch2,
698 AccessorInfo* callback,
699 String* name,
kmillikin@chromium.org13bd2942009-12-16 15:36:05 +0000700 Label* miss,
701 Failure** failure) {
kasperl@chromium.orgdefbd102009-07-13 14:04:26 +0000702 // Check that the receiver isn't a smi.
703 __ tst(receiver, Operand(kSmiTagMask));
704 __ b(eq, miss);
705
706 // Check that the maps haven't changed.
707 Register reg =
708 CheckPrototypes(object, receiver, holder, scratch1, scratch2, name, miss);
709
710 // Push the arguments on the JS stack of the caller.
711 __ push(receiver); // receiver
sgjesse@chromium.org0b6db592009-07-30 14:48:31 +0000712 __ push(reg); // holder
kasperl@chromium.orgdefbd102009-07-13 14:04:26 +0000713 __ mov(ip, Operand(Handle<AccessorInfo>(callback))); // callback data
714 __ push(ip);
sgjesse@chromium.org0b6db592009-07-30 14:48:31 +0000715 __ ldr(reg, FieldMemOperand(ip, AccessorInfo::kDataOffset));
716 __ push(reg);
kasperl@chromium.orgdefbd102009-07-13 14:04:26 +0000717 __ push(name_reg); // name
kasperl@chromium.orgdefbd102009-07-13 14:04:26 +0000718
719 // Do tail-call to the runtime system.
720 ExternalReference load_callback_property =
721 ExternalReference(IC_Utility(IC::kLoadCallbackProperty));
ager@chromium.orgce5e87b2010-03-10 10:24:18 +0000722 __ TailCallExternalReference(load_callback_property, 5, 1);
kmillikin@chromium.org13bd2942009-12-16 15:36:05 +0000723
724 return true;
kasperl@chromium.orgdefbd102009-07-13 14:04:26 +0000725}
726
727
728void StubCompiler::GenerateLoadInterceptor(JSObject* object,
729 JSObject* holder,
sgjesse@chromium.org0b6db592009-07-30 14:48:31 +0000730 LookupResult* lookup,
kasperl@chromium.orgdefbd102009-07-13 14:04:26 +0000731 Register receiver,
732 Register name_reg,
733 Register scratch1,
734 Register scratch2,
735 String* name,
736 Label* miss) {
sgjesse@chromium.orgb302e562010-02-03 11:26:59 +0000737 LoadInterceptorCompiler compiler(name_reg);
738 CompileLoadInterceptor(&compiler,
739 this,
740 masm(),
741 object,
742 holder,
743 name,
744 lookup,
745 receiver,
746 scratch1,
747 scratch2,
748 miss);
kasperl@chromium.orgdefbd102009-07-13 14:04:26 +0000749}
750
751
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000752Object* StubCompiler::CompileLazyCompile(Code::Flags flags) {
kasperl@chromium.orgb9123622008-09-17 14:05:56 +0000753 // ----------- S t a t e -------------
754 // -- r1: function
755 // -- lr: return address
756 // -----------------------------------
757
kasperl@chromium.orgb9123622008-09-17 14:05:56 +0000758 // Enter an internal frame.
759 __ EnterInternalFrame();
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000760
kasperl@chromium.orgb9123622008-09-17 14:05:56 +0000761 // Preserve the function.
762 __ push(r1);
763
764 // Push the function on the stack as the argument to the runtime function.
765 __ push(r1);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000766 __ CallRuntime(Runtime::kLazyCompile, 1);
767
kasperl@chromium.orgb9123622008-09-17 14:05:56 +0000768 // Calculate the entry point.
769 __ add(r2, r0, Operand(Code::kHeaderSize - kHeapObjectTag));
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000770
kasperl@chromium.orgb9123622008-09-17 14:05:56 +0000771 // Restore saved function.
772 __ pop(r1);
773
774 // Tear down temporary frame.
ager@chromium.org236ad962008-09-25 09:45:57 +0000775 __ LeaveInternalFrame();
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000776
777 // Do a tail-call of the compiled function.
kasperl@chromium.orgb9123622008-09-17 14:05:56 +0000778 __ Jump(r2);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000779
kasperl@chromium.org7be3c992009-03-12 07:19:55 +0000780 return GetCodeWithFlags(flags, "LazyCompileStub");
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000781}
782
783
ager@chromium.org5c838252010-02-19 08:53:10 +0000784Object* CallStubCompiler::CompileCallField(JSObject* object,
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000785 JSObject* holder,
kasperl@chromium.org7be3c992009-03-12 07:19:55 +0000786 int index,
kasperl@chromium.org2abc4502009-07-02 07:00:29 +0000787 String* name) {
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000788 // ----------- S t a t e -------------
ager@chromium.org5c838252010-02-19 08:53:10 +0000789 // -- r2 : name
790 // -- lr : return address
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000791 // -----------------------------------
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000792 Label miss;
793
mads.s.ager31e71382008-08-13 09:32:07 +0000794 const int argc = arguments().immediate();
795
kasperl@chromium.org9fe21c62008-10-28 08:53:51 +0000796 // Get the receiver of the function from the stack into r0.
797 __ ldr(r0, MemOperand(sp, argc * kPointerSize));
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000798 // Check that the receiver isn't a smi.
kasperl@chromium.org9fe21c62008-10-28 08:53:51 +0000799 __ tst(r0, Operand(kSmiTagMask));
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000800 __ b(eq, &miss);
801
802 // Do the right check and compute the holder register.
ager@chromium.org5c838252010-02-19 08:53:10 +0000803 Register reg = CheckPrototypes(object, r0, holder, r1, r3, name, &miss);
ager@chromium.org7c537e22008-10-16 08:43:32 +0000804 GenerateFastPropertyLoad(masm(), r1, reg, holder, index);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000805
sgjesse@chromium.orgb302e562010-02-03 11:26:59 +0000806 GenerateCallFunction(masm(), object, arguments(), &miss);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000807
808 // Handle call cache miss.
809 __ bind(&miss);
810 Handle<Code> ic = ComputeCallMiss(arguments().immediate());
ager@chromium.org236ad962008-09-25 09:45:57 +0000811 __ Jump(ic, RelocInfo::CODE_TARGET);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000812
813 // Return the generated code.
kasperl@chromium.org2abc4502009-07-02 07:00:29 +0000814 return GetCode(FIELD, name);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000815}
816
817
vegorov@chromium.orgf8372902010-03-15 10:26:20 +0000818Object* CallStubCompiler::CompileArrayPushCall(Object* object,
819 JSObject* holder,
820 JSFunction* function,
821 String* name,
822 CheckType check) {
823 // ----------- S t a t e -------------
824 // -- r2 : name
825 // -- lr : return address
826 // -----------------------------------
827
828 // TODO(639): faster implementation.
829 ASSERT(check == RECEIVER_MAP_CHECK);
830
831 Label miss;
832
833 // Get the receiver from the stack
834 const int argc = arguments().immediate();
835 __ ldr(r1, MemOperand(sp, argc * kPointerSize));
836
837 // Check that the receiver isn't a smi.
838 __ tst(r1, Operand(kSmiTagMask));
839 __ b(eq, &miss);
840
841 // Check that the maps haven't changed.
842 CheckPrototypes(JSObject::cast(object), r1, holder, r3, r0, name, &miss);
843
844 if (object->IsGlobalObject()) {
845 __ ldr(r3, FieldMemOperand(r1, GlobalObject::kGlobalReceiverOffset));
846 __ str(r3, MemOperand(sp, argc * kPointerSize));
847 }
848
849 __ TailCallExternalReference(ExternalReference(Builtins::c_ArrayPush),
850 argc + 1,
851 1);
852
853 // Handle call cache miss.
854 __ bind(&miss);
855 Handle<Code> ic = ComputeCallMiss(arguments().immediate());
856 __ Jump(ic, RelocInfo::CODE_TARGET);
857
858 // Return the generated code.
859 String* function_name = NULL;
860 if (function->shared()->name()->IsString()) {
861 function_name = String::cast(function->shared()->name());
862 }
863 return GetCode(CONSTANT_FUNCTION, function_name);
864}
865
866
867Object* CallStubCompiler::CompileArrayPopCall(Object* object,
868 JSObject* holder,
869 JSFunction* function,
870 String* name,
871 CheckType check) {
872 // ----------- S t a t e -------------
873 // -- r2 : name
874 // -- lr : return address
875 // -----------------------------------
876
877 // TODO(642): faster implementation.
878 ASSERT(check == RECEIVER_MAP_CHECK);
879
880 Label miss;
881
882 // Get the receiver from the stack
883 const int argc = arguments().immediate();
884 __ ldr(r1, MemOperand(sp, argc * kPointerSize));
885
886 // Check that the receiver isn't a smi.
887 __ tst(r1, Operand(kSmiTagMask));
888 __ b(eq, &miss);
889
890 // Check that the maps haven't changed.
891 CheckPrototypes(JSObject::cast(object), r1, holder, r3, r0, name, &miss);
892
893 if (object->IsGlobalObject()) {
894 __ ldr(r3, FieldMemOperand(r1, GlobalObject::kGlobalReceiverOffset));
895 __ str(r3, MemOperand(sp, argc * kPointerSize));
896 }
897
898 __ TailCallExternalReference(ExternalReference(Builtins::c_ArrayPop),
899 argc + 1,
900 1);
901
902 // Handle call cache miss.
903 __ bind(&miss);
904 Handle<Code> ic = ComputeCallMiss(arguments().immediate());
905 __ Jump(ic, RelocInfo::CODE_TARGET);
906
907 // Return the generated code.
908 String* function_name = NULL;
909 if (function->shared()->name()->IsString()) {
910 function_name = String::cast(function->shared()->name());
911 }
912 return GetCode(CONSTANT_FUNCTION, function_name);
913}
914
915
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000916Object* CallStubCompiler::CompileCallConstant(Object* object,
917 JSObject* holder,
918 JSFunction* function,
kasperl@chromium.orgdefbd102009-07-13 14:04:26 +0000919 String* name,
kasperl@chromium.org2abc4502009-07-02 07:00:29 +0000920 CheckType check) {
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000921 // ----------- S t a t e -------------
ager@chromium.org5c838252010-02-19 08:53:10 +0000922 // -- r2 : name
923 // -- lr : return address
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000924 // -----------------------------------
vegorov@chromium.orgf8372902010-03-15 10:26:20 +0000925 SharedFunctionInfo* function_info = function->shared();
926 if (function_info->HasCustomCallGenerator()) {
927 CustomCallGenerator generator =
928 ToCData<CustomCallGenerator>(function_info->function_data());
929 return generator(this, object, holder, function, name, check);
930 }
931
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000932 Label miss;
933
mads.s.ager31e71382008-08-13 09:32:07 +0000934 // Get the receiver from the stack
935 const int argc = arguments().immediate();
936 __ ldr(r1, MemOperand(sp, argc * kPointerSize));
937
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000938 // Check that the receiver isn't a smi.
939 if (check != NUMBER_CHECK) {
940 __ tst(r1, Operand(kSmiTagMask));
941 __ b(eq, &miss);
942 }
943
kasperl@chromium.org9fe21c62008-10-28 08:53:51 +0000944 // Make sure that it's okay not to patch the on stack receiver
945 // unless we're doing a receiver map check.
946 ASSERT(!object->IsGlobalObject() || check == RECEIVER_MAP_CHECK);
947
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000948 switch (check) {
949 case RECEIVER_MAP_CHECK:
950 // Check that the maps haven't changed.
ager@chromium.org5c838252010-02-19 08:53:10 +0000951 CheckPrototypes(JSObject::cast(object), r1, holder, r3, r0, name, &miss);
kasperl@chromium.org9fe21c62008-10-28 08:53:51 +0000952
953 // Patch the receiver on the stack with the global proxy if
954 // necessary.
955 if (object->IsGlobalObject()) {
956 __ ldr(r3, FieldMemOperand(r1, GlobalObject::kGlobalReceiverOffset));
957 __ str(r3, MemOperand(sp, argc * kPointerSize));
958 }
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000959 break;
960
961 case STRING_CHECK:
sgjesse@chromium.orgb302e562010-02-03 11:26:59 +0000962 if (!function->IsBuiltin()) {
963 // Calling non-builtins with a value as receiver requires boxing.
964 __ jmp(&miss);
965 } else {
966 // Check that the object is a two-byte string or a symbol.
ager@chromium.org5c838252010-02-19 08:53:10 +0000967 __ CompareObjectType(r1, r3, r3, FIRST_NONSTRING_TYPE);
sgjesse@chromium.orgb302e562010-02-03 11:26:59 +0000968 __ b(hs, &miss);
969 // Check that the maps starting from the prototype haven't changed.
970 GenerateLoadGlobalFunctionPrototype(masm(),
971 Context::STRING_FUNCTION_INDEX,
ager@chromium.org5c838252010-02-19 08:53:10 +0000972 r0);
973 CheckPrototypes(JSObject::cast(object->GetPrototype()), r0, holder, r3,
sgjesse@chromium.orgb302e562010-02-03 11:26:59 +0000974 r1, name, &miss);
975 }
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000976 break;
977
978 case NUMBER_CHECK: {
sgjesse@chromium.orgb302e562010-02-03 11:26:59 +0000979 if (!function->IsBuiltin()) {
980 // Calling non-builtins with a value as receiver requires boxing.
981 __ jmp(&miss);
982 } else {
983 Label fast;
984 // Check that the object is a smi or a heap number.
985 __ tst(r1, Operand(kSmiTagMask));
986 __ b(eq, &fast);
ager@chromium.org5c838252010-02-19 08:53:10 +0000987 __ CompareObjectType(r1, r0, r0, HEAP_NUMBER_TYPE);
sgjesse@chromium.orgb302e562010-02-03 11:26:59 +0000988 __ b(ne, &miss);
989 __ bind(&fast);
990 // Check that the maps starting from the prototype haven't changed.
991 GenerateLoadGlobalFunctionPrototype(masm(),
992 Context::NUMBER_FUNCTION_INDEX,
ager@chromium.org5c838252010-02-19 08:53:10 +0000993 r0);
994 CheckPrototypes(JSObject::cast(object->GetPrototype()), r0, holder, r3,
sgjesse@chromium.orgb302e562010-02-03 11:26:59 +0000995 r1, name, &miss);
996 }
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000997 break;
998 }
999
1000 case BOOLEAN_CHECK: {
sgjesse@chromium.orgb302e562010-02-03 11:26:59 +00001001 if (!function->IsBuiltin()) {
1002 // Calling non-builtins with a value as receiver requires boxing.
1003 __ jmp(&miss);
1004 } else {
1005 Label fast;
1006 // Check that the object is a boolean.
1007 __ LoadRoot(ip, Heap::kTrueValueRootIndex);
1008 __ cmp(r1, ip);
1009 __ b(eq, &fast);
1010 __ LoadRoot(ip, Heap::kFalseValueRootIndex);
1011 __ cmp(r1, ip);
1012 __ b(ne, &miss);
1013 __ bind(&fast);
1014 // Check that the maps starting from the prototype haven't changed.
1015 GenerateLoadGlobalFunctionPrototype(masm(),
1016 Context::BOOLEAN_FUNCTION_INDEX,
ager@chromium.org5c838252010-02-19 08:53:10 +00001017 r0);
1018 CheckPrototypes(JSObject::cast(object->GetPrototype()), r0, holder, r3,
sgjesse@chromium.orgb302e562010-02-03 11:26:59 +00001019 r1, name, &miss);
1020 }
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001021 break;
1022 }
1023
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001024 default:
1025 UNREACHABLE();
1026 }
1027
ager@chromium.org5c838252010-02-19 08:53:10 +00001028 __ InvokeFunction(function, arguments(), JUMP_FUNCTION);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001029
1030 // Handle call cache miss.
1031 __ bind(&miss);
1032 Handle<Code> ic = ComputeCallMiss(arguments().immediate());
ager@chromium.org236ad962008-09-25 09:45:57 +00001033 __ Jump(ic, RelocInfo::CODE_TARGET);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001034
1035 // Return the generated code.
kasperl@chromium.org7be3c992009-03-12 07:19:55 +00001036 String* function_name = NULL;
1037 if (function->shared()->name()->IsString()) {
1038 function_name = String::cast(function->shared()->name());
1039 }
kasperl@chromium.org2abc4502009-07-02 07:00:29 +00001040 return GetCode(CONSTANT_FUNCTION, function_name);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001041}
1042
1043
ager@chromium.org5c838252010-02-19 08:53:10 +00001044Object* CallStubCompiler::CompileCallInterceptor(JSObject* object,
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001045 JSObject* holder,
1046 String* name) {
1047 // ----------- S t a t e -------------
ager@chromium.org5c838252010-02-19 08:53:10 +00001048 // -- r2 : name
1049 // -- lr : return address
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001050 // -----------------------------------
ager@chromium.org5c838252010-02-19 08:53:10 +00001051 ASSERT(holder->HasNamedInterceptor());
1052 ASSERT(!holder->GetNamedInterceptor()->getter()->IsUndefined());
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001053 Label miss;
1054
ager@chromium.org5c838252010-02-19 08:53:10 +00001055 const Register receiver = r0;
1056 const Register holder_reg = r1;
1057 const Register name_reg = r2;
1058 const Register scratch = r3;
1059
sgjesse@chromium.orgb302e562010-02-03 11:26:59 +00001060 // Get the number of arguments.
1061 const int argc = arguments().immediate();
1062
1063 LookupResult lookup;
1064 LookupPostInterceptor(holder, name, &lookup);
1065
1066 // Get the receiver from the stack into r0.
1067 __ ldr(r0, MemOperand(sp, argc * kPointerSize));
sgjesse@chromium.orgb302e562010-02-03 11:26:59 +00001068
ager@chromium.org5c838252010-02-19 08:53:10 +00001069 // Check that the receiver isn't a smi.
1070 __ BranchOnSmi(receiver, &miss);
sgjesse@chromium.orgb302e562010-02-03 11:26:59 +00001071
ager@chromium.org5c838252010-02-19 08:53:10 +00001072 // Check that the maps haven't changed.
1073 Register reg = CheckPrototypes(object, receiver, holder, holder_reg,
1074 scratch, name, &miss);
1075 if (!reg.is(holder_reg)) {
1076 __ mov(holder_reg, reg);
1077 }
1078
1079 // If we call a constant function when the interceptor returns
1080 // the no-result sentinel, generate code that optimizes this case.
1081 if (lookup.IsProperty() &&
1082 lookup.IsCacheable() &&
1083 lookup.type() == CONSTANT_FUNCTION &&
1084 lookup.GetConstantFunction()->is_compiled() &&
1085 !holder->IsJSArray()) {
1086 // Constant functions cannot sit on global object.
1087 ASSERT(!lookup.holder()->IsGlobalObject());
1088
1089 // Call the interceptor.
1090 __ EnterInternalFrame();
1091 __ push(holder_reg);
1092 __ push(name_reg);
1093 CompileCallLoadPropertyWithInterceptor(masm(),
1094 receiver,
1095 holder_reg,
1096 name_reg,
1097 holder);
1098 __ pop(name_reg);
1099 __ pop(holder_reg);
1100 __ LeaveInternalFrame();
1101 // r0 no longer contains the receiver.
1102
1103 // If interceptor returns no-result sentinal, call the constant function.
1104 __ LoadRoot(scratch, Heap::kNoInterceptorResultSentinelRootIndex);
1105 __ cmp(r0, scratch);
1106 Label invoke;
1107 __ b(ne, &invoke);
1108 // Check the prototypes between the interceptor's holder and the
1109 // constant function's holder.
1110 CheckPrototypes(holder, holder_reg,
1111 lookup.holder(), r0,
1112 scratch,
1113 name,
1114 &miss);
1115
1116 __ InvokeFunction(lookup.GetConstantFunction(),
1117 arguments(),
1118 JUMP_FUNCTION);
1119
1120 __ bind(&invoke);
1121
1122 } else {
1123 // Call a runtime function to load the interceptor property.
1124 __ EnterInternalFrame();
1125 __ push(name_reg);
1126
1127 PushInterceptorArguments(masm(), receiver, holder_reg, name_reg, holder);
1128
1129 __ CallExternalReference(
1130 ExternalReference(IC_Utility(IC::kLoadPropertyWithInterceptorForCall)),
1131 5);
1132
1133 __ pop(name_reg);
1134 __ LeaveInternalFrame();
1135 }
1136
1137 // Move returned value, the function to call, to r1.
1138 __ mov(r1, r0);
sgjesse@chromium.orgb302e562010-02-03 11:26:59 +00001139 // Restore receiver.
ager@chromium.org5c838252010-02-19 08:53:10 +00001140 __ ldr(receiver, MemOperand(sp, argc * kPointerSize));
sgjesse@chromium.orgb302e562010-02-03 11:26:59 +00001141
1142 GenerateCallFunction(masm(), object, arguments(), &miss);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001143
1144 // Handle call cache miss.
1145 __ bind(&miss);
1146 Handle<Code> ic = ComputeCallMiss(arguments().immediate());
ager@chromium.org236ad962008-09-25 09:45:57 +00001147 __ Jump(ic, RelocInfo::CODE_TARGET);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001148
1149 // Return the generated code.
kasperl@chromium.org7be3c992009-03-12 07:19:55 +00001150 return GetCode(INTERCEPTOR, name);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001151}
1152
1153
kasperl@chromium.orgdefbd102009-07-13 14:04:26 +00001154Object* CallStubCompiler::CompileCallGlobal(JSObject* object,
1155 GlobalObject* holder,
kasperl@chromium.org2abc4502009-07-02 07:00:29 +00001156 JSGlobalPropertyCell* cell,
1157 JSFunction* function,
1158 String* name) {
1159 // ----------- S t a t e -------------
ager@chromium.org5c838252010-02-19 08:53:10 +00001160 // -- r2 : name
1161 // -- lr : return address
kasperl@chromium.org2abc4502009-07-02 07:00:29 +00001162 // -----------------------------------
1163 Label miss;
1164
kasperl@chromium.org2abc4502009-07-02 07:00:29 +00001165 // Get the number of arguments.
1166 const int argc = arguments().immediate();
1167
kasperl@chromium.orgdefbd102009-07-13 14:04:26 +00001168 // Get the receiver from the stack.
1169 __ ldr(r0, MemOperand(sp, argc * kPointerSize));
1170
1171 // If the object is the holder then we know that it's a global
1172 // object which can only happen for contextual calls. In this case,
1173 // the receiver cannot be a smi.
1174 if (object != holder) {
1175 __ tst(r0, Operand(kSmiTagMask));
1176 __ b(eq, &miss);
1177 }
1178
1179 // Check that the maps haven't changed.
ager@chromium.org5c838252010-02-19 08:53:10 +00001180 CheckPrototypes(object, r0, holder, r3, r1, name, &miss);
kasperl@chromium.org2abc4502009-07-02 07:00:29 +00001181
1182 // Get the value from the cell.
1183 __ mov(r3, Operand(Handle<JSGlobalPropertyCell>(cell)));
1184 __ ldr(r1, FieldMemOperand(r3, JSGlobalPropertyCell::kValueOffset));
1185
1186 // Check that the cell contains the same function.
sgjesse@chromium.org846fb742009-12-18 08:56:33 +00001187 if (Heap::InNewSpace(function)) {
1188 // We can't embed a pointer to a function in new space so we have
1189 // to verify that the shared function info is unchanged. This has
1190 // the nice side effect that multiple closures based on the same
1191 // function can all use this call IC. Before we load through the
1192 // function, we have to verify that it still is a function.
1193 __ tst(r1, Operand(kSmiTagMask));
1194 __ b(eq, &miss);
1195 __ CompareObjectType(r1, r3, r3, JS_FUNCTION_TYPE);
1196 __ b(ne, &miss);
1197
1198 // Check the shared function info. Make sure it hasn't changed.
1199 __ mov(r3, Operand(Handle<SharedFunctionInfo>(function->shared())));
ager@chromium.org5c838252010-02-19 08:53:10 +00001200 __ ldr(r4, FieldMemOperand(r1, JSFunction::kSharedFunctionInfoOffset));
1201 __ cmp(r4, r3);
sgjesse@chromium.org846fb742009-12-18 08:56:33 +00001202 __ b(ne, &miss);
1203 } else {
1204 __ cmp(r1, Operand(Handle<JSFunction>(function)));
1205 __ b(ne, &miss);
1206 }
kasperl@chromium.org2abc4502009-07-02 07:00:29 +00001207
1208 // Patch the receiver on the stack with the global proxy if
1209 // necessary.
kasperl@chromium.orgdefbd102009-07-13 14:04:26 +00001210 if (object->IsGlobalObject()) {
1211 __ ldr(r3, FieldMemOperand(r0, GlobalObject::kGlobalReceiverOffset));
1212 __ str(r3, MemOperand(sp, argc * kPointerSize));
1213 }
kasperl@chromium.org2abc4502009-07-02 07:00:29 +00001214
1215 // Setup the context (function already in r1).
1216 __ ldr(cp, FieldMemOperand(r1, JSFunction::kContextOffset));
1217
1218 // Jump to the cached code (tail call).
ager@chromium.org5c838252010-02-19 08:53:10 +00001219 __ IncrementCounter(&Counters::call_global_inline, 1, r1, r3);
kasperl@chromium.org2abc4502009-07-02 07:00:29 +00001220 ASSERT(function->is_compiled());
1221 Handle<Code> code(function->code());
1222 ParameterCount expected(function->shared()->formal_parameter_count());
1223 __ InvokeCode(code, expected, arguments(),
1224 RelocInfo::CODE_TARGET, JUMP_FUNCTION);
1225
1226 // Handle call cache miss.
1227 __ bind(&miss);
kasperl@chromium.org2abc4502009-07-02 07:00:29 +00001228 __ IncrementCounter(&Counters::call_global_inline_miss, 1, r1, r3);
1229 Handle<Code> ic = ComputeCallMiss(arguments().immediate());
1230 __ Jump(ic, RelocInfo::CODE_TARGET);
1231
1232 // Return the generated code.
1233 return GetCode(NORMAL, name);
1234}
1235
1236
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001237Object* StoreStubCompiler::CompileStoreField(JSObject* object,
1238 int index,
1239 Map* transition,
1240 String* name) {
1241 // ----------- S t a t e -------------
1242 // -- r0 : value
ager@chromium.org5c838252010-02-19 08:53:10 +00001243 // -- r1 : receiver
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001244 // -- r2 : name
1245 // -- lr : return address
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001246 // -----------------------------------
ager@chromium.orga74f0da2008-12-03 16:05:52 +00001247 Label miss;
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001248
ager@chromium.orga74f0da2008-12-03 16:05:52 +00001249 GenerateStoreField(masm(),
ager@chromium.orga74f0da2008-12-03 16:05:52 +00001250 object,
1251 index,
1252 transition,
ager@chromium.org5c838252010-02-19 08:53:10 +00001253 r1, r2, r3,
ager@chromium.orga74f0da2008-12-03 16:05:52 +00001254 &miss);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001255 __ bind(&miss);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001256 Handle<Code> ic(Builtins::builtin(Builtins::StoreIC_Miss));
ager@chromium.org236ad962008-09-25 09:45:57 +00001257 __ Jump(ic, RelocInfo::CODE_TARGET);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001258
1259 // Return the generated code.
kasperl@chromium.org7be3c992009-03-12 07:19:55 +00001260 return GetCode(transition == NULL ? FIELD : MAP_TRANSITION, name);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001261}
1262
1263
1264Object* StoreStubCompiler::CompileStoreCallback(JSObject* object,
1265 AccessorInfo* callback,
1266 String* name) {
1267 // ----------- S t a t e -------------
1268 // -- r0 : value
ager@chromium.org5c838252010-02-19 08:53:10 +00001269 // -- r1 : receiver
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001270 // -- r2 : name
1271 // -- lr : return address
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001272 // -----------------------------------
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001273 Label miss;
1274
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001275 // Check that the object isn't a smi.
ager@chromium.org5c838252010-02-19 08:53:10 +00001276 __ tst(r1, Operand(kSmiTagMask));
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001277 __ b(eq, &miss);
1278
1279 // Check that the map of the object hasn't changed.
ager@chromium.org5c838252010-02-19 08:53:10 +00001280 __ ldr(r3, FieldMemOperand(r1, HeapObject::kMapOffset));
1281 __ cmp(r3, Operand(Handle<Map>(object->map())));
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001282 __ b(ne, &miss);
1283
1284 // Perform global security token check if needed.
kasperl@chromium.org5a8ca6c2008-10-23 13:57:19 +00001285 if (object->IsJSGlobalProxy()) {
ager@chromium.org5c838252010-02-19 08:53:10 +00001286 __ CheckAccessGlobalProxy(r1, r3, &miss);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001287 }
1288
1289 // Stub never generated for non-global objects that require access
1290 // checks.
kasperl@chromium.org5a8ca6c2008-10-23 13:57:19 +00001291 ASSERT(object->IsJSGlobalProxy() || !object->IsAccessCheckNeeded());
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001292
ager@chromium.org5c838252010-02-19 08:53:10 +00001293 __ push(r1); // receiver
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001294 __ mov(ip, Operand(Handle<AccessorInfo>(callback))); // callback info
ager@chromium.org5c838252010-02-19 08:53:10 +00001295 __ stm(db_w, sp, ip.bit() | r2.bit() | r0.bit());
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001296
mads.s.ager31e71382008-08-13 09:32:07 +00001297 // Do tail-call to the runtime system.
1298 ExternalReference store_callback_property =
1299 ExternalReference(IC_Utility(IC::kStoreCallbackProperty));
ager@chromium.orgce5e87b2010-03-10 10:24:18 +00001300 __ TailCallExternalReference(store_callback_property, 4, 1);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001301
1302 // Handle store cache miss.
1303 __ bind(&miss);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001304 Handle<Code> ic(Builtins::builtin(Builtins::StoreIC_Miss));
ager@chromium.org236ad962008-09-25 09:45:57 +00001305 __ Jump(ic, RelocInfo::CODE_TARGET);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001306
1307 // Return the generated code.
kasperl@chromium.org7be3c992009-03-12 07:19:55 +00001308 return GetCode(CALLBACKS, name);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001309}
1310
1311
1312Object* StoreStubCompiler::CompileStoreInterceptor(JSObject* receiver,
1313 String* name) {
1314 // ----------- S t a t e -------------
1315 // -- r0 : value
ager@chromium.org5c838252010-02-19 08:53:10 +00001316 // -- r1 : receiver
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001317 // -- r2 : name
1318 // -- lr : return address
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001319 // -----------------------------------
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001320 Label miss;
1321
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001322 // Check that the object isn't a smi.
ager@chromium.org5c838252010-02-19 08:53:10 +00001323 __ tst(r1, Operand(kSmiTagMask));
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001324 __ b(eq, &miss);
1325
1326 // Check that the map of the object hasn't changed.
ager@chromium.org5c838252010-02-19 08:53:10 +00001327 __ ldr(r3, FieldMemOperand(r1, HeapObject::kMapOffset));
1328 __ cmp(r3, Operand(Handle<Map>(receiver->map())));
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001329 __ b(ne, &miss);
1330
1331 // Perform global security token check if needed.
kasperl@chromium.org5a8ca6c2008-10-23 13:57:19 +00001332 if (receiver->IsJSGlobalProxy()) {
ager@chromium.org5c838252010-02-19 08:53:10 +00001333 __ CheckAccessGlobalProxy(r1, r3, &miss);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001334 }
1335
ager@chromium.org5c838252010-02-19 08:53:10 +00001336 // Stub is never generated for non-global objects that require access
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001337 // checks.
kasperl@chromium.org5a8ca6c2008-10-23 13:57:19 +00001338 ASSERT(receiver->IsJSGlobalProxy() || !receiver->IsAccessCheckNeeded());
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001339
ager@chromium.org5c838252010-02-19 08:53:10 +00001340 __ push(r1); // receiver.
1341 __ push(r2); // name.
1342 __ push(r0); // value.
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001343
mads.s.ager31e71382008-08-13 09:32:07 +00001344 // Do tail-call to the runtime system.
1345 ExternalReference store_ic_property =
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001346 ExternalReference(IC_Utility(IC::kStoreInterceptorProperty));
ager@chromium.orgce5e87b2010-03-10 10:24:18 +00001347 __ TailCallExternalReference(store_ic_property, 3, 1);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001348
1349 // Handle store cache miss.
1350 __ bind(&miss);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001351 Handle<Code> ic(Builtins::builtin(Builtins::StoreIC_Miss));
ager@chromium.org236ad962008-09-25 09:45:57 +00001352 __ Jump(ic, RelocInfo::CODE_TARGET);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001353
1354 // Return the generated code.
kasperl@chromium.org7be3c992009-03-12 07:19:55 +00001355 return GetCode(INTERCEPTOR, name);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001356}
1357
1358
kasperl@chromium.org2abc4502009-07-02 07:00:29 +00001359Object* StoreStubCompiler::CompileStoreGlobal(GlobalObject* object,
1360 JSGlobalPropertyCell* cell,
1361 String* name) {
1362 // ----------- S t a t e -------------
1363 // -- r0 : value
ager@chromium.org5c838252010-02-19 08:53:10 +00001364 // -- r1 : receiver
kasperl@chromium.org2abc4502009-07-02 07:00:29 +00001365 // -- r2 : name
1366 // -- lr : return address
kasperl@chromium.org2abc4502009-07-02 07:00:29 +00001367 // -----------------------------------
1368 Label miss;
1369
kasperl@chromium.org2abc4502009-07-02 07:00:29 +00001370 // Check that the map of the global has not changed.
kasperl@chromium.org2abc4502009-07-02 07:00:29 +00001371 __ ldr(r3, FieldMemOperand(r1, HeapObject::kMapOffset));
1372 __ cmp(r3, Operand(Handle<Map>(object->map())));
1373 __ b(ne, &miss);
1374
1375 // Store the value in the cell.
1376 __ mov(r2, Operand(Handle<JSGlobalPropertyCell>(cell)));
1377 __ str(r0, FieldMemOperand(r2, JSGlobalPropertyCell::kValueOffset));
kasperl@chromium.org2abc4502009-07-02 07:00:29 +00001378
ager@chromium.org5c838252010-02-19 08:53:10 +00001379 __ IncrementCounter(&Counters::named_store_global_inline, 1, r4, r3);
kasperl@chromium.org2abc4502009-07-02 07:00:29 +00001380 __ Ret();
1381
1382 // Handle store cache miss.
1383 __ bind(&miss);
ager@chromium.org5c838252010-02-19 08:53:10 +00001384 __ IncrementCounter(&Counters::named_store_global_inline_miss, 1, r4, r3);
kasperl@chromium.org2abc4502009-07-02 07:00:29 +00001385 Handle<Code> ic(Builtins::builtin(Builtins::StoreIC_Miss));
1386 __ Jump(ic, RelocInfo::CODE_TARGET);
1387
1388 // Return the generated code.
1389 return GetCode(NORMAL, name);
1390}
1391
1392
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001393Object* LoadStubCompiler::CompileLoadField(JSObject* object,
1394 JSObject* holder,
kasperl@chromium.org7be3c992009-03-12 07:19:55 +00001395 int index,
1396 String* name) {
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001397 // ----------- S t a t e -------------
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001398 // -- r2 : name
1399 // -- lr : return address
1400 // -- [sp] : receiver
1401 // -----------------------------------
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001402 Label miss;
1403
mads.s.ager31e71382008-08-13 09:32:07 +00001404 __ ldr(r0, MemOperand(sp, 0));
1405
kasperl@chromium.orgdefbd102009-07-13 14:04:26 +00001406 GenerateLoadField(object, holder, r0, r3, r1, index, name, &miss);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001407 __ bind(&miss);
ager@chromium.org3bf7b912008-11-17 09:09:45 +00001408 GenerateLoadMiss(masm(), Code::LOAD_IC);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001409
1410 // Return the generated code.
kasperl@chromium.org7be3c992009-03-12 07:19:55 +00001411 return GetCode(FIELD, name);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001412}
1413
1414
kmillikin@chromium.org13bd2942009-12-16 15:36:05 +00001415Object* LoadStubCompiler::CompileLoadCallback(String* name,
1416 JSObject* object,
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001417 JSObject* holder,
kmillikin@chromium.org13bd2942009-12-16 15:36:05 +00001418 AccessorInfo* callback) {
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001419 // ----------- S t a t e -------------
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001420 // -- r2 : name
1421 // -- lr : return address
1422 // -- [sp] : receiver
1423 // -----------------------------------
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001424 Label miss;
1425
mads.s.ager31e71382008-08-13 09:32:07 +00001426 __ ldr(r0, MemOperand(sp, 0));
kmillikin@chromium.org13bd2942009-12-16 15:36:05 +00001427 Failure* failure = Failure::InternalError();
1428 bool success = GenerateLoadCallback(object, holder, r0, r2, r3, r1,
1429 callback, name, &miss, &failure);
1430 if (!success) return failure;
1431
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001432 __ bind(&miss);
ager@chromium.org3bf7b912008-11-17 09:09:45 +00001433 GenerateLoadMiss(masm(), Code::LOAD_IC);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001434
1435 // Return the generated code.
kasperl@chromium.org7be3c992009-03-12 07:19:55 +00001436 return GetCode(CALLBACKS, name);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001437}
1438
1439
1440Object* LoadStubCompiler::CompileLoadConstant(JSObject* object,
1441 JSObject* holder,
kasperl@chromium.org7be3c992009-03-12 07:19:55 +00001442 Object* value,
1443 String* name) {
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001444 // ----------- S t a t e -------------
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001445 // -- r2 : name
1446 // -- lr : return address
1447 // -- [sp] : receiver
1448 // -----------------------------------
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001449 Label miss;
1450
mads.s.ager31e71382008-08-13 09:32:07 +00001451 __ ldr(r0, MemOperand(sp, 0));
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001452
kasperl@chromium.orgdefbd102009-07-13 14:04:26 +00001453 GenerateLoadConstant(object, holder, r0, r3, r1, value, name, &miss);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001454 __ bind(&miss);
ager@chromium.org3bf7b912008-11-17 09:09:45 +00001455 GenerateLoadMiss(masm(), Code::LOAD_IC);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001456
1457 // Return the generated code.
kasperl@chromium.org7be3c992009-03-12 07:19:55 +00001458 return GetCode(CONSTANT_FUNCTION, name);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001459}
1460
1461
1462Object* LoadStubCompiler::CompileLoadInterceptor(JSObject* object,
1463 JSObject* holder,
1464 String* name) {
1465 // ----------- S t a t e -------------
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001466 // -- r2 : name
1467 // -- lr : return address
1468 // -- [sp] : receiver
1469 // -----------------------------------
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001470 Label miss;
1471
mads.s.ager31e71382008-08-13 09:32:07 +00001472 __ ldr(r0, MemOperand(sp, 0));
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001473
sgjesse@chromium.org0b6db592009-07-30 14:48:31 +00001474 LookupResult lookup;
sgjesse@chromium.orgb302e562010-02-03 11:26:59 +00001475 LookupPostInterceptor(holder, name, &lookup);
kasperl@chromium.orgdefbd102009-07-13 14:04:26 +00001476 GenerateLoadInterceptor(object,
ager@chromium.orge2902be2009-06-08 12:21:35 +00001477 holder,
sgjesse@chromium.org0b6db592009-07-30 14:48:31 +00001478 &lookup,
ager@chromium.orge2902be2009-06-08 12:21:35 +00001479 r0,
1480 r2,
1481 r3,
1482 r1,
kasperl@chromium.orgdefbd102009-07-13 14:04:26 +00001483 name,
ager@chromium.orge2902be2009-06-08 12:21:35 +00001484 &miss);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001485 __ bind(&miss);
ager@chromium.org3bf7b912008-11-17 09:09:45 +00001486 GenerateLoadMiss(masm(), Code::LOAD_IC);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001487
1488 // Return the generated code.
kasperl@chromium.org7be3c992009-03-12 07:19:55 +00001489 return GetCode(INTERCEPTOR, name);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001490}
1491
1492
kasperl@chromium.orgdefbd102009-07-13 14:04:26 +00001493Object* LoadStubCompiler::CompileLoadGlobal(JSObject* object,
1494 GlobalObject* holder,
kasperl@chromium.org2abc4502009-07-02 07:00:29 +00001495 JSGlobalPropertyCell* cell,
1496 String* name,
1497 bool is_dont_delete) {
1498 // ----------- S t a t e -------------
1499 // -- r2 : name
1500 // -- lr : return address
1501 // -- [sp] : receiver
1502 // -----------------------------------
1503 Label miss;
1504
kasperl@chromium.orgdefbd102009-07-13 14:04:26 +00001505 // Get the receiver from the stack.
kasperl@chromium.org2abc4502009-07-02 07:00:29 +00001506 __ ldr(r1, MemOperand(sp, 0 * kPointerSize));
kasperl@chromium.orgdefbd102009-07-13 14:04:26 +00001507
1508 // If the object is the holder then we know that it's a global
1509 // object which can only happen for contextual calls. In this case,
1510 // the receiver cannot be a smi.
1511 if (object != holder) {
1512 __ tst(r1, Operand(kSmiTagMask));
1513 __ b(eq, &miss);
1514 }
1515
1516 // Check that the map of the global has not changed.
1517 CheckPrototypes(object, r1, holder, r3, r0, name, &miss);
kasperl@chromium.org2abc4502009-07-02 07:00:29 +00001518
1519 // Get the value from the cell.
1520 __ mov(r3, Operand(Handle<JSGlobalPropertyCell>(cell)));
1521 __ ldr(r0, FieldMemOperand(r3, JSGlobalPropertyCell::kValueOffset));
1522
1523 // Check for deleted property if property can actually be deleted.
1524 if (!is_dont_delete) {
ager@chromium.orgab99eea2009-08-25 07:05:41 +00001525 __ LoadRoot(ip, Heap::kTheHoleValueRootIndex);
1526 __ cmp(r0, ip);
kasperl@chromium.org2abc4502009-07-02 07:00:29 +00001527 __ b(eq, &miss);
1528 }
1529
sgjesse@chromium.org0b6db592009-07-30 14:48:31 +00001530 __ IncrementCounter(&Counters::named_load_global_inline, 1, r1, r3);
kasperl@chromium.org2abc4502009-07-02 07:00:29 +00001531 __ Ret();
1532
1533 __ bind(&miss);
kasperl@chromium.org2abc4502009-07-02 07:00:29 +00001534 __ IncrementCounter(&Counters::named_load_global_inline_miss, 1, r1, r3);
1535 GenerateLoadMiss(masm(), Code::LOAD_IC);
1536
1537 // Return the generated code.
1538 return GetCode(NORMAL, name);
1539}
1540
1541
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001542Object* KeyedLoadStubCompiler::CompileLoadField(String* name,
1543 JSObject* receiver,
1544 JSObject* holder,
1545 int index) {
ager@chromium.org3bf7b912008-11-17 09:09:45 +00001546 // ----------- S t a t e -------------
1547 // -- lr : return address
1548 // -- sp[0] : key
1549 // -- sp[4] : receiver
1550 // -----------------------------------
ager@chromium.org3bf7b912008-11-17 09:09:45 +00001551 Label miss;
1552
1553 __ ldr(r2, MemOperand(sp, 0));
1554 __ ldr(r0, MemOperand(sp, kPointerSize));
1555
1556 __ cmp(r2, Operand(Handle<String>(name)));
1557 __ b(ne, &miss);
1558
kasperl@chromium.orgdefbd102009-07-13 14:04:26 +00001559 GenerateLoadField(receiver, holder, r0, r3, r1, index, name, &miss);
ager@chromium.org3bf7b912008-11-17 09:09:45 +00001560 __ bind(&miss);
1561 GenerateLoadMiss(masm(), Code::KEYED_LOAD_IC);
1562
kasperl@chromium.org7be3c992009-03-12 07:19:55 +00001563 return GetCode(FIELD, name);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001564}
1565
1566
1567Object* KeyedLoadStubCompiler::CompileLoadCallback(String* name,
1568 JSObject* receiver,
1569 JSObject* holder,
1570 AccessorInfo* callback) {
ager@chromium.org3bf7b912008-11-17 09:09:45 +00001571 // ----------- S t a t e -------------
1572 // -- lr : return address
1573 // -- sp[0] : key
1574 // -- sp[4] : receiver
1575 // -----------------------------------
ager@chromium.org3bf7b912008-11-17 09:09:45 +00001576 Label miss;
1577
1578 __ ldr(r2, MemOperand(sp, 0));
1579 __ ldr(r0, MemOperand(sp, kPointerSize));
1580
1581 __ cmp(r2, Operand(Handle<String>(name)));
1582 __ b(ne, &miss);
1583
kmillikin@chromium.org13bd2942009-12-16 15:36:05 +00001584 Failure* failure = Failure::InternalError();
1585 bool success = GenerateLoadCallback(receiver, holder, r0, r2, r3, r1,
1586 callback, name, &miss, &failure);
1587 if (!success) return failure;
1588
ager@chromium.org3bf7b912008-11-17 09:09:45 +00001589 __ bind(&miss);
1590 GenerateLoadMiss(masm(), Code::KEYED_LOAD_IC);
1591
kasperl@chromium.org7be3c992009-03-12 07:19:55 +00001592 return GetCode(CALLBACKS, name);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001593}
1594
1595
1596Object* KeyedLoadStubCompiler::CompileLoadConstant(String* name,
1597 JSObject* receiver,
1598 JSObject* holder,
1599 Object* value) {
ager@chromium.org3bf7b912008-11-17 09:09:45 +00001600 // ----------- S t a t e -------------
1601 // -- lr : return address
1602 // -- sp[0] : key
1603 // -- sp[4] : receiver
1604 // -----------------------------------
ager@chromium.org3bf7b912008-11-17 09:09:45 +00001605 Label miss;
1606
1607 // Check the key is the cached one
1608 __ ldr(r2, MemOperand(sp, 0));
1609 __ ldr(r0, MemOperand(sp, kPointerSize));
1610
1611 __ cmp(r2, Operand(Handle<String>(name)));
1612 __ b(ne, &miss);
1613
kasperl@chromium.orgdefbd102009-07-13 14:04:26 +00001614 GenerateLoadConstant(receiver, holder, r0, r3, r1, value, name, &miss);
ager@chromium.org3bf7b912008-11-17 09:09:45 +00001615 __ bind(&miss);
1616 GenerateLoadMiss(masm(), Code::KEYED_LOAD_IC);
1617
1618 // Return the generated code.
kasperl@chromium.org7be3c992009-03-12 07:19:55 +00001619 return GetCode(CONSTANT_FUNCTION, name);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001620}
1621
1622
1623Object* KeyedLoadStubCompiler::CompileLoadInterceptor(JSObject* receiver,
1624 JSObject* holder,
1625 String* name) {
ager@chromium.org3bf7b912008-11-17 09:09:45 +00001626 // ----------- S t a t e -------------
1627 // -- lr : return address
1628 // -- sp[0] : key
1629 // -- sp[4] : receiver
1630 // -----------------------------------
ager@chromium.org3bf7b912008-11-17 09:09:45 +00001631 Label miss;
1632
1633 // Check the key is the cached one
1634 __ ldr(r2, MemOperand(sp, 0));
1635 __ ldr(r0, MemOperand(sp, kPointerSize));
1636
1637 __ cmp(r2, Operand(Handle<String>(name)));
1638 __ b(ne, &miss);
1639
sgjesse@chromium.org0b6db592009-07-30 14:48:31 +00001640 LookupResult lookup;
sgjesse@chromium.orgb302e562010-02-03 11:26:59 +00001641 LookupPostInterceptor(holder, name, &lookup);
kasperl@chromium.orgdefbd102009-07-13 14:04:26 +00001642 GenerateLoadInterceptor(receiver,
ager@chromium.orge2902be2009-06-08 12:21:35 +00001643 holder,
sgjesse@chromium.org0b6db592009-07-30 14:48:31 +00001644 &lookup,
ager@chromium.orge2902be2009-06-08 12:21:35 +00001645 r0,
1646 r2,
1647 r3,
1648 r1,
kasperl@chromium.orgdefbd102009-07-13 14:04:26 +00001649 name,
ager@chromium.orge2902be2009-06-08 12:21:35 +00001650 &miss);
ager@chromium.org3bf7b912008-11-17 09:09:45 +00001651 __ bind(&miss);
1652 GenerateLoadMiss(masm(), Code::KEYED_LOAD_IC);
1653
kasperl@chromium.org7be3c992009-03-12 07:19:55 +00001654 return GetCode(INTERCEPTOR, name);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001655}
1656
1657
1658Object* KeyedLoadStubCompiler::CompileLoadArrayLength(String* name) {
ager@chromium.org3bf7b912008-11-17 09:09:45 +00001659 // ----------- S t a t e -------------
1660 // -- lr : return address
1661 // -- sp[0] : key
1662 // -- sp[4] : receiver
1663 // -----------------------------------
ager@chromium.org3bf7b912008-11-17 09:09:45 +00001664 Label miss;
1665
1666 // Check the key is the cached one
1667 __ ldr(r2, MemOperand(sp, 0));
1668 __ ldr(r0, MemOperand(sp, kPointerSize));
1669
1670 __ cmp(r2, Operand(Handle<String>(name)));
1671 __ b(ne, &miss);
1672
1673 GenerateLoadArrayLength(masm(), r0, r3, &miss);
1674 __ bind(&miss);
1675 GenerateLoadMiss(masm(), Code::KEYED_LOAD_IC);
1676
kasperl@chromium.org7be3c992009-03-12 07:19:55 +00001677 return GetCode(CALLBACKS, name);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001678}
1679
1680
kasperl@chromium.org9fe21c62008-10-28 08:53:51 +00001681Object* KeyedLoadStubCompiler::CompileLoadStringLength(String* name) {
ager@chromium.org3bf7b912008-11-17 09:09:45 +00001682 // ----------- S t a t e -------------
1683 // -- lr : return address
1684 // -- sp[0] : key
1685 // -- sp[4] : receiver
1686 // -----------------------------------
ager@chromium.orga74f0da2008-12-03 16:05:52 +00001687 Label miss;
1688 __ IncrementCounter(&Counters::keyed_load_string_length, 1, r1, r3);
1689
1690 __ ldr(r2, MemOperand(sp));
1691 __ ldr(r0, MemOperand(sp, kPointerSize)); // receiver
1692
1693 __ cmp(r2, Operand(Handle<String>(name)));
1694 __ b(ne, &miss);
1695
ager@chromium.org5c838252010-02-19 08:53:10 +00001696 GenerateLoadStringLength(masm(), r0, r1, r3, &miss);
ager@chromium.orga74f0da2008-12-03 16:05:52 +00001697 __ bind(&miss);
1698 __ DecrementCounter(&Counters::keyed_load_string_length, 1, r1, r3);
1699
ager@chromium.org3bf7b912008-11-17 09:09:45 +00001700 GenerateLoadMiss(masm(), Code::KEYED_LOAD_IC);
1701
kasperl@chromium.org7be3c992009-03-12 07:19:55 +00001702 return GetCode(CALLBACKS, name);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001703}
1704
1705
ager@chromium.org3bf7b912008-11-17 09:09:45 +00001706// TODO(1224671): implement the fast case.
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001707Object* KeyedLoadStubCompiler::CompileLoadFunctionPrototype(String* name) {
ager@chromium.org3bf7b912008-11-17 09:09:45 +00001708 // ----------- S t a t e -------------
1709 // -- lr : return address
1710 // -- sp[0] : key
1711 // -- sp[4] : receiver
1712 // -----------------------------------
ager@chromium.org3bf7b912008-11-17 09:09:45 +00001713 GenerateLoadMiss(masm(), Code::KEYED_LOAD_IC);
1714
kasperl@chromium.org7be3c992009-03-12 07:19:55 +00001715 return GetCode(CALLBACKS, name);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001716}
1717
1718
1719Object* KeyedStoreStubCompiler::CompileStoreField(JSObject* object,
1720 int index,
1721 Map* transition,
1722 String* name) {
ager@chromium.org3bf7b912008-11-17 09:09:45 +00001723 // ----------- S t a t e -------------
1724 // -- r0 : value
1725 // -- r2 : name
1726 // -- lr : return address
1727 // -- [sp] : receiver
1728 // -----------------------------------
ager@chromium.orga74f0da2008-12-03 16:05:52 +00001729 Label miss;
1730
1731 __ IncrementCounter(&Counters::keyed_store_field, 1, r1, r3);
1732
1733 // Check that the name has not changed.
1734 __ cmp(r2, Operand(Handle<String>(name)));
1735 __ b(ne, &miss);
1736
1737 // Load receiver from the stack.
1738 __ ldr(r3, MemOperand(sp));
1739 // r1 is used as scratch register, r3 and r2 might be clobbered.
1740 GenerateStoreField(masm(),
ager@chromium.orga74f0da2008-12-03 16:05:52 +00001741 object,
1742 index,
1743 transition,
1744 r3, r2, r1,
1745 &miss);
1746 __ bind(&miss);
1747
1748 __ DecrementCounter(&Counters::keyed_store_field, 1, r1, r3);
1749 __ mov(r2, Operand(Handle<String>(name))); // restore name register.
ager@chromium.org3bf7b912008-11-17 09:09:45 +00001750 Handle<Code> ic(Builtins::builtin(Builtins::KeyedStoreIC_Miss));
1751 __ Jump(ic, RelocInfo::CODE_TARGET);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001752
ager@chromium.org3bf7b912008-11-17 09:09:45 +00001753 // Return the generated code.
kasperl@chromium.org7be3c992009-03-12 07:19:55 +00001754 return GetCode(transition == NULL ? FIELD : MAP_TRANSITION, name);
ager@chromium.org3bf7b912008-11-17 09:09:45 +00001755}
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001756
1757
ager@chromium.org18ad94b2009-09-02 08:22:29 +00001758Object* ConstructStubCompiler::CompileConstructStub(
1759 SharedFunctionInfo* shared) {
ager@chromium.orga1645e22009-09-09 19:27:10 +00001760 // ----------- S t a t e -------------
1761 // -- r0 : argc
1762 // -- r1 : constructor
1763 // -- lr : return address
1764 // -- [sp] : last argument
1765 // -----------------------------------
1766 Label generic_stub_call;
1767
1768 // Use r7 for holding undefined which is used in several places below.
1769 __ LoadRoot(r7, Heap::kUndefinedValueRootIndex);
1770
1771#ifdef ENABLE_DEBUGGER_SUPPORT
1772 // Check to see whether there are any break points in the function code. If
1773 // there are jump to the generic constructor stub which calls the actual
1774 // code for the function thereby hitting the break points.
1775 __ ldr(r2, FieldMemOperand(r1, JSFunction::kSharedFunctionInfoOffset));
1776 __ ldr(r2, FieldMemOperand(r2, SharedFunctionInfo::kDebugInfoOffset));
1777 __ cmp(r2, r7);
1778 __ b(ne, &generic_stub_call);
1779#endif
1780
1781 // Load the initial map and verify that it is in fact a map.
1782 // r1: constructor function
1783 // r7: undefined
1784 __ ldr(r2, FieldMemOperand(r1, JSFunction::kPrototypeOrInitialMapOffset));
1785 __ tst(r2, Operand(kSmiTagMask));
1786 __ b(eq, &generic_stub_call);
1787 __ CompareObjectType(r2, r3, r4, MAP_TYPE);
1788 __ b(ne, &generic_stub_call);
1789
1790#ifdef DEBUG
1791 // Cannot construct functions this way.
1792 // r0: argc
1793 // r1: constructor function
1794 // r2: initial map
1795 // r7: undefined
1796 __ CompareInstanceType(r2, r3, JS_FUNCTION_TYPE);
1797 __ Check(ne, "Function constructed by construct stub.");
1798#endif
1799
1800 // Now allocate the JSObject in new space.
1801 // r0: argc
1802 // r1: constructor function
1803 // r2: initial map
1804 // r7: undefined
1805 __ ldrb(r3, FieldMemOperand(r2, Map::kInstanceSizeOffset));
sgjesse@chromium.orgc5145742009-10-07 09:00:33 +00001806 __ AllocateInNewSpace(r3,
1807 r4,
1808 r5,
1809 r6,
1810 &generic_stub_call,
1811 NO_ALLOCATION_FLAGS);
ager@chromium.orga1645e22009-09-09 19:27:10 +00001812
1813 // Allocated the JSObject, now initialize the fields. Map is set to initial
1814 // map and properties and elements are set to empty fixed array.
1815 // r0: argc
1816 // r1: constructor function
1817 // r2: initial map
1818 // r3: object size (in words)
1819 // r4: JSObject (not tagged)
1820 // r7: undefined
1821 __ LoadRoot(r6, Heap::kEmptyFixedArrayRootIndex);
1822 __ mov(r5, r4);
1823 ASSERT_EQ(0 * kPointerSize, JSObject::kMapOffset);
1824 __ str(r2, MemOperand(r5, kPointerSize, PostIndex));
1825 ASSERT_EQ(1 * kPointerSize, JSObject::kPropertiesOffset);
1826 __ str(r6, MemOperand(r5, kPointerSize, PostIndex));
1827 ASSERT_EQ(2 * kPointerSize, JSObject::kElementsOffset);
1828 __ str(r6, MemOperand(r5, kPointerSize, PostIndex));
1829
1830 // Calculate the location of the first argument. The stack contains only the
1831 // argc arguments.
1832 __ add(r1, sp, Operand(r0, LSL, kPointerSizeLog2));
1833
1834 // Fill all the in-object properties with undefined.
1835 // r0: argc
1836 // r1: first argument
1837 // r3: object size (in words)
1838 // r4: JSObject (not tagged)
1839 // r5: First in-object property of JSObject (not tagged)
1840 // r7: undefined
1841 // Fill the initialized properties with a constant value or a passed argument
1842 // depending on the this.x = ...; assignment in the function.
1843 for (int i = 0; i < shared->this_property_assignments_count(); i++) {
1844 if (shared->IsThisPropertyAssignmentArgument(i)) {
1845 Label not_passed, next;
1846 // Check if the argument assigned to the property is actually passed.
1847 int arg_number = shared->GetThisPropertyAssignmentArgument(i);
1848 __ cmp(r0, Operand(arg_number));
1849 __ b(le, &not_passed);
1850 // Argument passed - find it on the stack.
1851 __ ldr(r2, MemOperand(r1, (arg_number + 1) * -kPointerSize));
1852 __ str(r2, MemOperand(r5, kPointerSize, PostIndex));
1853 __ b(&next);
1854 __ bind(&not_passed);
1855 // Set the property to undefined.
1856 __ str(r7, MemOperand(r5, kPointerSize, PostIndex));
1857 __ bind(&next);
1858 } else {
1859 // Set the property to the constant value.
1860 Handle<Object> constant(shared->GetThisPropertyAssignmentConstant(i));
1861 __ mov(r2, Operand(constant));
1862 __ str(r2, MemOperand(r5, kPointerSize, PostIndex));
1863 }
1864 }
1865
1866 // Fill the unused in-object property fields with undefined.
1867 for (int i = shared->this_property_assignments_count();
1868 i < shared->CalculateInObjectProperties();
1869 i++) {
1870 __ str(r7, MemOperand(r5, kPointerSize, PostIndex));
1871 }
1872
1873 // r0: argc
1874 // r4: JSObject (not tagged)
1875 // Move argc to r1 and the JSObject to return to r0 and tag it.
1876 __ mov(r1, r0);
1877 __ mov(r0, r4);
1878 __ orr(r0, r0, Operand(kHeapObjectTag));
1879
1880 // r0: JSObject
1881 // r1: argc
1882 // Remove caller arguments and receiver from the stack and return.
1883 __ add(sp, sp, Operand(r1, LSL, kPointerSizeLog2));
1884 __ add(sp, sp, Operand(kPointerSize));
1885 __ IncrementCounter(&Counters::constructed_objects, 1, r1, r2);
1886 __ IncrementCounter(&Counters::constructed_objects_stub, 1, r1, r2);
1887 __ Jump(lr);
1888
1889 // Jump to the generic stub in case the specialized code cannot handle the
1890 // construction.
1891 __ bind(&generic_stub_call);
ager@chromium.org18ad94b2009-09-02 08:22:29 +00001892 Code* code = Builtins::builtin(Builtins::JSConstructStubGeneric);
1893 Handle<Code> generic_construct_stub(code);
1894 __ Jump(generic_construct_stub, RelocInfo::CODE_TARGET);
1895
1896 // Return the generated code.
1897 return GetCode();
1898}
1899
1900
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001901#undef __
1902
1903} } // namespace v8::internal