Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(187)

Side by Side Diff: src/stub-cache-arm.cc

Issue 92068: Move backend specific files to separate directories. (Closed)
Patch Set: Added CPPPATH flag and made all includes use same base path. Created 11 years, 8 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
« no previous file with comments | « src/simulator-ia32.cc ('k') | src/stub-cache-ia32.cc » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
(Empty)
1 // Copyright 2006-2008 the V8 project authors. All rights reserved.
2 // 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
34 namespace v8 { namespace internal {
35
36 #define __ ACCESS_MASM(masm)
37
38
39 static 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
83 void 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.
106 __ ldr(scratch, FieldMemOperand(name, String::kLengthOffset));
107 __ ldr(ip, FieldMemOperand(receiver, HeapObject::kMapOffset));
108 __ 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
133 void 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
151 // 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.
154 void 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
172 void 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 masm->CheckMaps(object, receiver, holder, scratch1, scratch2, miss_label);
187 GenerateFastPropertyLoad(masm, r0, reg, holder, index);
188 __ Ret();
189 }
190
191
192 void 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 masm->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
214 void 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 masm->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
245 void 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 masm->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
273 void 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
293 // 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.
295 static 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
315 // 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.
319 void StubCompiler::GenerateLoadStringLength2(MacroAssembler* masm,
320 Register receiver,
321 Register scratch1,
322 Register scratch2,
323 Label* miss) {
324 Label check_string, check_wrapper;
325
326 __ bind(&check_string);
327 // 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.
333 __ 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
345 // 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);
348 }
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.
354 void 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.
387 // We jump to a runtime call that extends the properties array.
388 __ 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
444 void 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
458 #undef __
459 #define __ ACCESS_MASM(masm())
460
461
462 Object* StubCompiler::CompileLazyCompile(Code::Flags flags) {
463 // ----------- S t a t e -------------
464 // -- r1: function
465 // -- lr: return address
466 // -----------------------------------
467
468 // Enter an internal frame.
469 __ EnterInternalFrame();
470
471 // Preserve the function.
472 __ push(r1);
473
474 // Push the function on the stack as the argument to the runtime function.
475 __ push(r1);
476 __ CallRuntime(Runtime::kLazyCompile, 1);
477
478 // Calculate the entry point.
479 __ add(r2, r0, Operand(Code::kHeaderSize - kHeapObjectTag));
480
481 // Restore saved function.
482 __ pop(r1);
483
484 // Tear down temporary frame.
485 __ LeaveInternalFrame();
486
487 // Do a tail-call of the compiled function.
488 __ Jump(r2);
489
490 return GetCodeWithFlags(flags, "LazyCompileStub");
491 }
492
493
494 Object* CallStubCompiler::CompileCallField(Object* object,
495 JSObject* holder,
496 int index,
497 String* name) {
498 // ----------- S t a t e -------------
499 // -- lr: return address
500 // -----------------------------------
501 Label miss;
502
503 const int argc = arguments().immediate();
504
505 // Get the receiver of the function from the stack into r0.
506 __ ldr(r0, MemOperand(sp, argc * kPointerSize));
507 // Check that the receiver isn't a smi.
508 __ tst(r0, Operand(kSmiTagMask));
509 __ b(eq, &miss);
510
511 // Do the right check and compute the holder register.
512 Register reg =
513 masm()->CheckMaps(JSObject::cast(object), r0, holder, r3, r2, &miss);
514 GenerateFastPropertyLoad(masm(), r1, reg, holder, index);
515
516 // Check that the function really is a function.
517 __ tst(r1, Operand(kSmiTagMask));
518 __ b(eq, &miss);
519 // Get the map.
520 __ ldr(r2, FieldMemOperand(r1, HeapObject::kMapOffset));
521 __ ldrb(r2, FieldMemOperand(r2, Map::kInstanceTypeOffset));
522 __ cmp(r2, Operand(JS_FUNCTION_TYPE));
523 __ b(ne, &miss);
524
525 // Patch the receiver on the stack with the global proxy if
526 // necessary.
527 if (object->IsGlobalObject()) {
528 __ ldr(r3, FieldMemOperand(r0, GlobalObject::kGlobalReceiverOffset));
529 __ str(r3, MemOperand(sp, argc * kPointerSize));
530 }
531
532 // Invoke the function.
533 __ InvokeFunction(r1, arguments(), JUMP_FUNCTION);
534
535 // Handle call cache miss.
536 __ bind(&miss);
537 Handle<Code> ic = ComputeCallMiss(arguments().immediate());
538 __ Jump(ic, RelocInfo::CODE_TARGET);
539
540 // Return the generated code.
541 return GetCode(FIELD, name);
542 }
543
544
545 Object* CallStubCompiler::CompileCallConstant(Object* object,
546 JSObject* holder,
547 JSFunction* function,
548 CheckType check) {
549 // ----------- S t a t e -------------
550 // -- lr: return address
551 // -----------------------------------
552 Label miss;
553
554 // Get the receiver from the stack
555 const int argc = arguments().immediate();
556 __ ldr(r1, MemOperand(sp, argc * kPointerSize));
557
558 // Check that the receiver isn't a smi.
559 if (check != NUMBER_CHECK) {
560 __ tst(r1, Operand(kSmiTagMask));
561 __ b(eq, &miss);
562 }
563
564 // Make sure that it's okay not to patch the on stack receiver
565 // unless we're doing a receiver map check.
566 ASSERT(!object->IsGlobalObject() || check == RECEIVER_MAP_CHECK);
567
568 switch (check) {
569 case RECEIVER_MAP_CHECK:
570 // Check that the maps haven't changed.
571 __ CheckMaps(JSObject::cast(object), r1, holder, r3, r2, &miss);
572
573 // Patch the receiver on the stack with the global proxy if
574 // necessary.
575 if (object->IsGlobalObject()) {
576 __ ldr(r3, FieldMemOperand(r1, GlobalObject::kGlobalReceiverOffset));
577 __ str(r3, MemOperand(sp, argc * kPointerSize));
578 }
579 break;
580
581 case STRING_CHECK:
582 // Check that the object is a two-byte string or a symbol.
583 __ ldr(r2, FieldMemOperand(r1, HeapObject::kMapOffset));
584 __ ldrb(r2, FieldMemOperand(r2, Map::kInstanceTypeOffset));
585 __ cmp(r2, Operand(FIRST_NONSTRING_TYPE));
586 __ b(hs, &miss);
587 // Check that the maps starting from the prototype haven't changed.
588 GenerateLoadGlobalFunctionPrototype(masm(),
589 Context::STRING_FUNCTION_INDEX,
590 r2);
591 __ CheckMaps(JSObject::cast(object->GetPrototype()),
592 r2, holder, r3, r1, &miss);
593 break;
594
595 case NUMBER_CHECK: {
596 Label fast;
597 // Check that the object is a smi or a heap number.
598 __ tst(r1, Operand(kSmiTagMask));
599 __ b(eq, &fast);
600 __ ldr(r2, FieldMemOperand(r1, HeapObject::kMapOffset));
601 __ ldrb(r2, FieldMemOperand(r2, Map::kInstanceTypeOffset));
602 __ cmp(r2, Operand(HEAP_NUMBER_TYPE));
603 __ b(ne, &miss);
604 __ bind(&fast);
605 // Check that the maps starting from the prototype haven't changed.
606 GenerateLoadGlobalFunctionPrototype(masm(),
607 Context::NUMBER_FUNCTION_INDEX,
608 r2);
609 __ CheckMaps(JSObject::cast(object->GetPrototype()),
610 r2, holder, r3, r1, &miss);
611 break;
612 }
613
614 case BOOLEAN_CHECK: {
615 Label fast;
616 // Check that the object is a boolean.
617 __ cmp(r1, Operand(Factory::true_value()));
618 __ b(eq, &fast);
619 __ cmp(r1, Operand(Factory::false_value()));
620 __ b(ne, &miss);
621 __ bind(&fast);
622 // Check that the maps starting from the prototype haven't changed.
623 GenerateLoadGlobalFunctionPrototype(masm(),
624 Context::BOOLEAN_FUNCTION_INDEX,
625 r2);
626 __ CheckMaps(JSObject::cast(object->GetPrototype()),
627 r2, holder, r3, r1, &miss);
628 break;
629 }
630
631 case JSARRAY_HAS_FAST_ELEMENTS_CHECK:
632 __ CheckMaps(JSObject::cast(object), r1, holder, r3, r2, &miss);
633 // Make sure object->elements()->map() != Heap::hash_table_map()
634 // Get the elements array of the object.
635 __ ldr(r3, FieldMemOperand(r1, JSObject::kElementsOffset));
636 // Check that the object is in fast mode (not dictionary).
637 __ ldr(r2, FieldMemOperand(r3, HeapObject::kMapOffset));
638 __ cmp(r2, Operand(Factory::hash_table_map()));
639 __ b(eq, &miss);
640 break;
641
642 default:
643 UNREACHABLE();
644 }
645
646 // Get the function and setup the context.
647 __ mov(r1, Operand(Handle<JSFunction>(function)));
648 __ ldr(cp, FieldMemOperand(r1, JSFunction::kContextOffset));
649
650 // Jump to the cached code (tail call).
651 Handle<Code> code(function->code());
652 ParameterCount expected(function->shared()->formal_parameter_count());
653 __ InvokeCode(code, expected, arguments(),
654 RelocInfo::CODE_TARGET, JUMP_FUNCTION);
655
656 // Handle call cache miss.
657 __ bind(&miss);
658 Handle<Code> ic = ComputeCallMiss(arguments().immediate());
659 __ Jump(ic, RelocInfo::CODE_TARGET);
660
661 // Return the generated code.
662 String* function_name = NULL;
663 if (function->shared()->name()->IsString()) {
664 function_name = String::cast(function->shared()->name());
665 }
666 return GetCode(CONSTANT_FUNCTION, function_name);
667 }
668
669
670 Object* CallStubCompiler::CompileCallInterceptor(Object* object,
671 JSObject* holder,
672 String* name) {
673 // ----------- S t a t e -------------
674 // -- lr: return address
675 // -----------------------------------
676 Label miss;
677
678 // TODO(1224669): Implement.
679
680 // Handle call cache miss.
681 __ bind(&miss);
682 Handle<Code> ic = ComputeCallMiss(arguments().immediate());
683 __ Jump(ic, RelocInfo::CODE_TARGET);
684
685 // Return the generated code.
686 return GetCode(INTERCEPTOR, name);
687 }
688
689
690 Object* StoreStubCompiler::CompileStoreField(JSObject* object,
691 int index,
692 Map* transition,
693 String* name) {
694 // ----------- S t a t e -------------
695 // -- r0 : value
696 // -- r2 : name
697 // -- lr : return address
698 // -- [sp] : receiver
699 // -----------------------------------
700 Label miss;
701
702 // Get the receiver from the stack.
703 __ ldr(r3, MemOperand(sp, 0 * kPointerSize));
704
705 // name register might be clobbered.
706 GenerateStoreField(masm(),
707 Builtins::StoreIC_ExtendStorage,
708 object,
709 index,
710 transition,
711 r3, r2, r1,
712 &miss);
713 __ bind(&miss);
714 __ mov(r2, Operand(Handle<String>(name))); // restore name
715 Handle<Code> ic(Builtins::builtin(Builtins::StoreIC_Miss));
716 __ Jump(ic, RelocInfo::CODE_TARGET);
717
718 // Return the generated code.
719 return GetCode(transition == NULL ? FIELD : MAP_TRANSITION, name);
720 }
721
722
723 Object* StoreStubCompiler::CompileStoreCallback(JSObject* object,
724 AccessorInfo* callback,
725 String* name) {
726 // ----------- S t a t e -------------
727 // -- r0 : value
728 // -- r2 : name
729 // -- lr : return address
730 // -- [sp] : receiver
731 // -----------------------------------
732 Label miss;
733
734 // Get the object from the stack.
735 __ ldr(r3, MemOperand(sp, 0 * kPointerSize));
736
737 // Check that the object isn't a smi.
738 __ tst(r3, Operand(kSmiTagMask));
739 __ b(eq, &miss);
740
741 // Check that the map of the object hasn't changed.
742 __ ldr(r1, FieldMemOperand(r3, HeapObject::kMapOffset));
743 __ cmp(r1, Operand(Handle<Map>(object->map())));
744 __ b(ne, &miss);
745
746 // Perform global security token check if needed.
747 if (object->IsJSGlobalProxy()) {
748 __ CheckAccessGlobalProxy(r3, r1, &miss);
749 }
750
751 // Stub never generated for non-global objects that require access
752 // checks.
753 ASSERT(object->IsJSGlobalProxy() || !object->IsAccessCheckNeeded());
754
755 __ ldr(ip, MemOperand(sp)); // receiver
756 __ push(ip);
757 __ mov(ip, Operand(Handle<AccessorInfo>(callback))); // callback info
758 __ push(ip);
759 __ push(r2); // name
760 __ push(r0); // value
761
762 // Do tail-call to the runtime system.
763 ExternalReference store_callback_property =
764 ExternalReference(IC_Utility(IC::kStoreCallbackProperty));
765 __ TailCallRuntime(store_callback_property, 4);
766
767 // Handle store cache miss.
768 __ bind(&miss);
769 __ mov(r2, Operand(Handle<String>(name))); // restore name
770 Handle<Code> ic(Builtins::builtin(Builtins::StoreIC_Miss));
771 __ Jump(ic, RelocInfo::CODE_TARGET);
772
773 // Return the generated code.
774 return GetCode(CALLBACKS, name);
775 }
776
777
778 Object* StoreStubCompiler::CompileStoreInterceptor(JSObject* receiver,
779 String* name) {
780 // ----------- S t a t e -------------
781 // -- r0 : value
782 // -- r2 : name
783 // -- lr : return address
784 // -- [sp] : receiver
785 // -----------------------------------
786 Label miss;
787
788 // Get the object from the stack.
789 __ ldr(r3, MemOperand(sp, 0 * kPointerSize));
790
791 // Check that the object isn't a smi.
792 __ tst(r3, Operand(kSmiTagMask));
793 __ b(eq, &miss);
794
795 // Check that the map of the object hasn't changed.
796 __ ldr(r1, FieldMemOperand(r3, HeapObject::kMapOffset));
797 __ cmp(r1, Operand(Handle<Map>(receiver->map())));
798 __ b(ne, &miss);
799
800 // Perform global security token check if needed.
801 if (receiver->IsJSGlobalProxy()) {
802 __ CheckAccessGlobalProxy(r3, r1, &miss);
803 }
804
805 // Stub never generated for non-global objects that require access
806 // checks.
807 ASSERT(receiver->IsJSGlobalProxy() || !receiver->IsAccessCheckNeeded());
808
809 __ ldr(ip, MemOperand(sp)); // receiver
810 __ push(ip);
811 __ push(r2); // name
812 __ push(r0); // value
813
814 // Do tail-call to the runtime system.
815 ExternalReference store_ic_property =
816 ExternalReference(IC_Utility(IC::kStoreInterceptorProperty));
817 __ TailCallRuntime(store_ic_property, 3);
818
819 // Handle store cache miss.
820 __ bind(&miss);
821 __ mov(r2, Operand(Handle<String>(name))); // restore name
822 Handle<Code> ic(Builtins::builtin(Builtins::StoreIC_Miss));
823 __ Jump(ic, RelocInfo::CODE_TARGET);
824
825 // Return the generated code.
826 return GetCode(INTERCEPTOR, name);
827 }
828
829
830 Object* LoadStubCompiler::CompileLoadField(JSObject* object,
831 JSObject* holder,
832 int index,
833 String* name) {
834 // ----------- S t a t e -------------
835 // -- r2 : name
836 // -- lr : return address
837 // -- [sp] : receiver
838 // -----------------------------------
839 Label miss;
840
841 __ ldr(r0, MemOperand(sp, 0));
842
843 GenerateLoadField(masm(), object, holder, r0, r3, r1, index, &miss);
844 __ bind(&miss);
845 GenerateLoadMiss(masm(), Code::LOAD_IC);
846
847 // Return the generated code.
848 return GetCode(FIELD, name);
849 }
850
851
852 Object* LoadStubCompiler::CompileLoadCallback(JSObject* object,
853 JSObject* holder,
854 AccessorInfo* callback,
855 String* name) {
856 // ----------- S t a t e -------------
857 // -- r2 : name
858 // -- lr : return address
859 // -- [sp] : receiver
860 // -----------------------------------
861 Label miss;
862
863 __ ldr(r0, MemOperand(sp, 0));
864 GenerateLoadCallback(masm(), object, holder, r0, r2, r3, r1, callback, &miss);
865 __ bind(&miss);
866 GenerateLoadMiss(masm(), Code::LOAD_IC);
867
868 // Return the generated code.
869 return GetCode(CALLBACKS, name);
870 }
871
872
873 Object* LoadStubCompiler::CompileLoadConstant(JSObject* object,
874 JSObject* holder,
875 Object* value,
876 String* name) {
877 // ----------- S t a t e -------------
878 // -- r2 : name
879 // -- lr : return address
880 // -- [sp] : receiver
881 // -----------------------------------
882 Label miss;
883
884 __ ldr(r0, MemOperand(sp, 0));
885
886 GenerateLoadConstant(masm(), object, holder, r0, r3, r1, value, &miss);
887 __ bind(&miss);
888 GenerateLoadMiss(masm(), Code::LOAD_IC);
889
890 // Return the generated code.
891 return GetCode(CONSTANT_FUNCTION, name);
892 }
893
894
895 Object* LoadStubCompiler::CompileLoadInterceptor(JSObject* object,
896 JSObject* holder,
897 String* name) {
898 // ----------- S t a t e -------------
899 // -- r2 : name
900 // -- lr : return address
901 // -- [sp] : receiver
902 // -----------------------------------
903 Label miss;
904
905 __ ldr(r0, MemOperand(sp, 0));
906
907 GenerateLoadInterceptor(masm(), object, holder, r0, r2, r3, r1, &miss);
908 __ bind(&miss);
909 GenerateLoadMiss(masm(), Code::LOAD_IC);
910
911 // Return the generated code.
912 return GetCode(INTERCEPTOR, name);
913 }
914
915
916 // TODO(1224671): IC stubs for keyed loads have not been implemented
917 // for ARM.
918 Object* KeyedLoadStubCompiler::CompileLoadField(String* name,
919 JSObject* receiver,
920 JSObject* holder,
921 int index) {
922 // ----------- S t a t e -------------
923 // -- lr : return address
924 // -- sp[0] : key
925 // -- sp[4] : receiver
926 // -----------------------------------
927 Label miss;
928
929 __ ldr(r2, MemOperand(sp, 0));
930 __ ldr(r0, MemOperand(sp, kPointerSize));
931
932 __ cmp(r2, Operand(Handle<String>(name)));
933 __ b(ne, &miss);
934
935 GenerateLoadField(masm(), receiver, holder, r0, r3, r1, index, &miss);
936 __ bind(&miss);
937 GenerateLoadMiss(masm(), Code::KEYED_LOAD_IC);
938
939 return GetCode(FIELD, name);
940 }
941
942
943 Object* KeyedLoadStubCompiler::CompileLoadCallback(String* name,
944 JSObject* receiver,
945 JSObject* holder,
946 AccessorInfo* callback) {
947 // ----------- S t a t e -------------
948 // -- lr : return address
949 // -- sp[0] : key
950 // -- sp[4] : receiver
951 // -----------------------------------
952 Label miss;
953
954 __ ldr(r2, MemOperand(sp, 0));
955 __ ldr(r0, MemOperand(sp, kPointerSize));
956
957 __ cmp(r2, Operand(Handle<String>(name)));
958 __ b(ne, &miss);
959
960 GenerateLoadCallback(masm(), receiver, holder, r0, r2, r3,
961 r1, callback, &miss);
962 __ bind(&miss);
963 GenerateLoadMiss(masm(), Code::KEYED_LOAD_IC);
964
965 return GetCode(CALLBACKS, name);
966 }
967
968
969 Object* KeyedLoadStubCompiler::CompileLoadConstant(String* name,
970 JSObject* receiver,
971 JSObject* holder,
972 Object* value) {
973 // ----------- S t a t e -------------
974 // -- lr : return address
975 // -- sp[0] : key
976 // -- sp[4] : receiver
977 // -----------------------------------
978 Label miss;
979
980 // Check the key is the cached one
981 __ ldr(r2, MemOperand(sp, 0));
982 __ ldr(r0, MemOperand(sp, kPointerSize));
983
984 __ cmp(r2, Operand(Handle<String>(name)));
985 __ b(ne, &miss);
986
987 GenerateLoadConstant(masm(), receiver, holder, r0, r3, r1, value, &miss);
988 __ bind(&miss);
989 GenerateLoadMiss(masm(), Code::KEYED_LOAD_IC);
990
991 // Return the generated code.
992 return GetCode(CONSTANT_FUNCTION, name);
993 }
994
995
996 Object* KeyedLoadStubCompiler::CompileLoadInterceptor(JSObject* receiver,
997 JSObject* holder,
998 String* name) {
999 // ----------- S t a t e -------------
1000 // -- lr : return address
1001 // -- sp[0] : key
1002 // -- sp[4] : receiver
1003 // -----------------------------------
1004 Label miss;
1005
1006 // Check the key is the cached one
1007 __ ldr(r2, MemOperand(sp, 0));
1008 __ ldr(r0, MemOperand(sp, kPointerSize));
1009
1010 __ cmp(r2, Operand(Handle<String>(name)));
1011 __ b(ne, &miss);
1012
1013 GenerateLoadInterceptor(masm(), receiver, holder, r0, r2, r3, r1, &miss);
1014 __ bind(&miss);
1015 GenerateLoadMiss(masm(), Code::KEYED_LOAD_IC);
1016
1017 return GetCode(INTERCEPTOR, name);
1018 }
1019
1020
1021 Object* KeyedLoadStubCompiler::CompileLoadArrayLength(String* name) {
1022 // ----------- S t a t e -------------
1023 // -- lr : return address
1024 // -- sp[0] : key
1025 // -- sp[4] : receiver
1026 // -----------------------------------
1027 Label miss;
1028
1029 // Check the key is the cached one
1030 __ ldr(r2, MemOperand(sp, 0));
1031 __ ldr(r0, MemOperand(sp, kPointerSize));
1032
1033 __ cmp(r2, Operand(Handle<String>(name)));
1034 __ b(ne, &miss);
1035
1036 GenerateLoadArrayLength(masm(), r0, r3, &miss);
1037 __ bind(&miss);
1038 GenerateLoadMiss(masm(), Code::KEYED_LOAD_IC);
1039
1040 return GetCode(CALLBACKS, name);
1041 }
1042
1043
1044 Object* KeyedLoadStubCompiler::CompileLoadStringLength(String* name) {
1045 // ----------- S t a t e -------------
1046 // -- lr : return address
1047 // -- sp[0] : key
1048 // -- sp[4] : receiver
1049 // -----------------------------------
1050 Label miss;
1051 __ IncrementCounter(&Counters::keyed_load_string_length, 1, r1, r3);
1052
1053 __ ldr(r2, MemOperand(sp));
1054 __ ldr(r0, MemOperand(sp, kPointerSize)); // receiver
1055
1056 __ cmp(r2, Operand(Handle<String>(name)));
1057 __ b(ne, &miss);
1058
1059 GenerateLoadStringLength2(masm(), r0, r1, r3, &miss);
1060 __ bind(&miss);
1061 __ DecrementCounter(&Counters::keyed_load_string_length, 1, r1, r3);
1062
1063 GenerateLoadMiss(masm(), Code::KEYED_LOAD_IC);
1064
1065 return GetCode(CALLBACKS, name);
1066 }
1067
1068
1069 // TODO(1224671): implement the fast case.
1070 Object* KeyedLoadStubCompiler::CompileLoadFunctionPrototype(String* name) {
1071 // ----------- S t a t e -------------
1072 // -- lr : return address
1073 // -- sp[0] : key
1074 // -- sp[4] : receiver
1075 // -----------------------------------
1076 GenerateLoadMiss(masm(), Code::KEYED_LOAD_IC);
1077
1078 return GetCode(CALLBACKS, name);
1079 }
1080
1081
1082 Object* KeyedStoreStubCompiler::CompileStoreField(JSObject* object,
1083 int index,
1084 Map* transition,
1085 String* name) {
1086 // ----------- S t a t e -------------
1087 // -- r0 : value
1088 // -- r2 : name
1089 // -- lr : return address
1090 // -- [sp] : receiver
1091 // -----------------------------------
1092 Label miss;
1093
1094 __ IncrementCounter(&Counters::keyed_store_field, 1, r1, r3);
1095
1096 // Check that the name has not changed.
1097 __ cmp(r2, Operand(Handle<String>(name)));
1098 __ b(ne, &miss);
1099
1100 // Load receiver from the stack.
1101 __ ldr(r3, MemOperand(sp));
1102 // r1 is used as scratch register, r3 and r2 might be clobbered.
1103 GenerateStoreField(masm(),
1104 Builtins::StoreIC_ExtendStorage,
1105 object,
1106 index,
1107 transition,
1108 r3, r2, r1,
1109 &miss);
1110 __ bind(&miss);
1111
1112 __ DecrementCounter(&Counters::keyed_store_field, 1, r1, r3);
1113 __ mov(r2, Operand(Handle<String>(name))); // restore name register.
1114 Handle<Code> ic(Builtins::builtin(Builtins::KeyedStoreIC_Miss));
1115 __ Jump(ic, RelocInfo::CODE_TARGET);
1116
1117 // Return the generated code.
1118 return GetCode(transition == NULL ? FIELD : MAP_TRANSITION, name);
1119 }
1120
1121
1122 #undef __
1123
1124 } } // namespace v8::internal
OLDNEW
« no previous file with comments | « src/simulator-ia32.cc ('k') | src/stub-cache-ia32.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698