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

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

Issue 660095: Merge revision 3813 to 3930 from bleeding_edge to partial snapshots branch. (Closed) Base URL: http://v8.googlecode.com/svn/branches/experimental/partial_snapshots/
Patch Set: '' Created 10 years, 9 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 | Annotate | Revision Log
« no previous file with comments | « src/arm/macro-assembler-arm.cc ('k') | src/arm/virtual-frame-arm.h » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 // Copyright 2006-2009 the V8 project authors. All rights reserved. 1 // Copyright 2006-2009 the V8 project authors. All rights reserved.
2 // Redistribution and use in source and binary forms, with or without 2 // Redistribution and use in source and binary forms, with or without
3 // modification, are permitted provided that the following conditions are 3 // modification, are permitted provided that the following conditions are
4 // met: 4 // met:
5 // 5 //
6 // * Redistributions of source code must retain the above copyright 6 // * Redistributions of source code must retain the above copyright
7 // notice, this list of conditions and the following disclaimer. 7 // notice, this list of conditions and the following disclaimer.
8 // * Redistributions in binary form must reproduce the above 8 // * Redistributions in binary form must reproduce the above
9 // copyright notice, this list of conditions and the following 9 // copyright notice, this list of conditions and the following
10 // disclaimer in the documentation and/or other materials provided 10 // disclaimer in the documentation and/or other materials provided
(...skipping 171 matching lines...) Expand 10 before | Expand all | Expand 10 after
182 // Check that the object is a JS array. 182 // Check that the object is a JS array.
183 __ CompareObjectType(receiver, scratch, scratch, JS_ARRAY_TYPE); 183 __ CompareObjectType(receiver, scratch, scratch, JS_ARRAY_TYPE);
184 __ b(ne, miss_label); 184 __ b(ne, miss_label);
185 185
186 // Load length directly from the JS array. 186 // Load length directly from the JS array.
187 __ ldr(r0, FieldMemOperand(receiver, JSArray::kLengthOffset)); 187 __ ldr(r0, FieldMemOperand(receiver, JSArray::kLengthOffset));
188 __ Ret(); 188 __ Ret();
189 } 189 }
190 190
191 191
192 // Generate code to check if an object is a string. If the object is 192 // Generate code to check if an object is a string. If the object is a
193 // a string, the map's instance type is left in the scratch1 register. 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.
194 static void GenerateStringCheck(MacroAssembler* masm, 195 static void GenerateStringCheck(MacroAssembler* masm,
195 Register receiver, 196 Register receiver,
196 Register scratch1, 197 Register scratch1,
197 Register scratch2, 198 Register scratch2,
198 Label* smi, 199 Label* smi,
199 Label* non_string_object) { 200 Label* non_string_object) {
200 // Check that the receiver isn't a smi. 201 // Check that the receiver isn't a smi.
201 __ tst(receiver, Operand(kSmiTagMask)); 202 __ tst(receiver, Operand(kSmiTagMask));
202 __ b(eq, smi); 203 __ b(eq, smi);
203 204
204 // Check that the object is a string. 205 // Check that the object is a string.
205 __ ldr(scratch1, FieldMemOperand(receiver, HeapObject::kMapOffset)); 206 __ ldr(scratch1, FieldMemOperand(receiver, HeapObject::kMapOffset));
206 __ ldrb(scratch1, FieldMemOperand(scratch1, Map::kInstanceTypeOffset)); 207 __ ldrb(scratch1, FieldMemOperand(scratch1, Map::kInstanceTypeOffset));
207 __ and_(scratch2, scratch1, Operand(kIsNotStringMask)); 208 __ and_(scratch2, scratch1, Operand(kIsNotStringMask));
208 // The cast is to resolve the overload for the argument of 0x0. 209 // The cast is to resolve the overload for the argument of 0x0.
209 __ cmp(scratch2, Operand(static_cast<int32_t>(kStringTag))); 210 __ cmp(scratch2, Operand(static_cast<int32_t>(kStringTag)));
210 __ b(ne, non_string_object); 211 __ b(ne, non_string_object);
211 } 212 }
212 213
213 214
214 // Generate code to load the length from a string object and return the length. 215 // Generate code to load the length from a string object and return the length.
215 // If the receiver object is not a string or a wrapped string object the 216 // If the receiver object is not a string or a wrapped string object the
216 // execution continues at the miss label. The register containing the 217 // execution continues at the miss label. The register containing the
217 // receiver is potentially clobbered. 218 // receiver is potentially clobbered.
218 void StubCompiler::GenerateLoadStringLength2(MacroAssembler* masm, 219 void StubCompiler::GenerateLoadStringLength(MacroAssembler* masm,
219 Register receiver, 220 Register receiver,
220 Register scratch1, 221 Register scratch1,
221 Register scratch2, 222 Register scratch2,
222 Label* miss) { 223 Label* miss) {
223 Label check_string, check_wrapper; 224 Label check_wrapper;
224 225
225 __ bind(&check_string);
226 // Check if the object is a string leaving the instance type in the 226 // Check if the object is a string leaving the instance type in the
227 // scratch1 register. 227 // scratch1 register.
228 GenerateStringCheck(masm, receiver, scratch1, scratch2, 228 GenerateStringCheck(masm, receiver, scratch1, scratch2, miss, &check_wrapper);
229 miss, &check_wrapper);
230 229
231 // Load length directly from the string. 230 // Load length directly from the string.
232 __ ldr(r0, FieldMemOperand(receiver, String::kLengthOffset)); 231 __ ldr(r0, FieldMemOperand(receiver, String::kLengthOffset));
233 __ mov(r0, Operand(r0, LSL, kSmiTagSize)); 232 __ mov(r0, Operand(r0, LSL, kSmiTagSize));
234 __ Ret(); 233 __ Ret();
235 234
236 // Check if the object is a JSValue wrapper. 235 // Check if the object is a JSValue wrapper.
237 __ bind(&check_wrapper); 236 __ bind(&check_wrapper);
238 __ cmp(scratch1, Operand(JS_VALUE_TYPE)); 237 __ cmp(scratch1, Operand(JS_VALUE_TYPE));
239 __ b(ne, miss); 238 __ b(ne, miss);
240 239
241 // Unwrap the value in place and check if the wrapped value is a string. 240 // Unwrap the value and check if the wrapped value is a string.
242 __ ldr(receiver, FieldMemOperand(receiver, JSValue::kValueOffset)); 241 __ ldr(scratch1, FieldMemOperand(receiver, JSValue::kValueOffset));
243 __ b(&check_string); 242 GenerateStringCheck(masm, scratch1, scratch2, scratch2, miss, miss);
243 __ ldr(r0, FieldMemOperand(scratch1, String::kLengthOffset));
244 __ mov(r0, Operand(r0, LSL, kSmiTagSize));
245 __ Ret();
244 } 246 }
245 247
246 248
247 void StubCompiler::GenerateLoadFunctionPrototype(MacroAssembler* masm, 249 void StubCompiler::GenerateLoadFunctionPrototype(MacroAssembler* masm,
248 Register receiver, 250 Register receiver,
249 Register scratch1, 251 Register scratch1,
250 Register scratch2, 252 Register scratch2,
251 Label* miss_label) { 253 Label* miss_label) {
252 __ TryGetFunctionPrototype(receiver, scratch1, scratch2, miss_label); 254 __ TryGetFunctionPrototype(receiver, scratch1, scratch2, miss_label);
253 __ mov(r0, scratch1); 255 __ mov(r0, scratch1);
254 __ Ret(); 256 __ Ret();
255 } 257 }
256 258
257 259
258 // Generate StoreField code, value is passed in r0 register. 260 // Generate StoreField code, value is passed in r0 register.
259 // After executing generated code, the receiver_reg and name_reg 261 // When leaving generated code after success, the receiver_reg and name_reg
260 // may be clobbered. 262 // may be clobbered. Upon branch to miss_label, the receiver and name
263 // registers have their original values.
261 void StubCompiler::GenerateStoreField(MacroAssembler* masm, 264 void StubCompiler::GenerateStoreField(MacroAssembler* masm,
262 Builtins::Name storage_extend,
263 JSObject* object, 265 JSObject* object,
264 int index, 266 int index,
265 Map* transition, 267 Map* transition,
266 Register receiver_reg, 268 Register receiver_reg,
267 Register name_reg, 269 Register name_reg,
268 Register scratch, 270 Register scratch,
269 Label* miss_label) { 271 Label* miss_label) {
270 // r0 : value 272 // r0 : value
271 Label exit; 273 Label exit;
272 274
(...skipping 12 matching lines...) Expand all
285 } 287 }
286 288
287 // Stub never generated for non-global objects that require access 289 // Stub never generated for non-global objects that require access
288 // checks. 290 // checks.
289 ASSERT(object->IsJSGlobalProxy() || !object->IsAccessCheckNeeded()); 291 ASSERT(object->IsJSGlobalProxy() || !object->IsAccessCheckNeeded());
290 292
291 // Perform map transition for the receiver if necessary. 293 // Perform map transition for the receiver if necessary.
292 if ((transition != NULL) && (object->map()->unused_property_fields() == 0)) { 294 if ((transition != NULL) && (object->map()->unused_property_fields() == 0)) {
293 // The properties must be extended before we can store the value. 295 // The properties must be extended before we can store the value.
294 // We jump to a runtime call that extends the properties array. 296 // We jump to a runtime call that extends the properties array.
297 __ push(receiver_reg);
295 __ mov(r2, Operand(Handle<Map>(transition))); 298 __ mov(r2, Operand(Handle<Map>(transition)));
296 // Please note, if we implement keyed store for arm we need 299 __ stm(db_w, sp, r2.bit() | r0.bit());
297 // to call the Builtins::KeyedStoreIC_ExtendStorage. 300 __ TailCallRuntime(
298 Handle<Code> ic(Builtins::builtin(Builtins::StoreIC_ExtendStorage)); 301 ExternalReference(IC_Utility(IC::kSharedStoreIC_ExtendStorage)),
299 __ Jump(ic, RelocInfo::CODE_TARGET); 302 3, 1);
300 return; 303 return;
301 } 304 }
302 305
303 if (transition != NULL) { 306 if (transition != NULL) {
304 // Update the map of the object; no write barrier updating is 307 // Update the map of the object; no write barrier updating is
305 // needed because the map is never in new space. 308 // needed because the map is never in new space.
306 __ mov(ip, Operand(Handle<Map>(transition))); 309 __ mov(ip, Operand(Handle<Map>(transition)));
307 __ str(ip, FieldMemOperand(receiver_reg, HeapObject::kMapOffset)); 310 __ str(ip, FieldMemOperand(receiver_reg, HeapObject::kMapOffset));
308 } 311 }
309 312
(...skipping 56 matching lines...) Expand 10 before | Expand all | Expand 10 after
366 Object* object, 369 Object* object,
367 const ParameterCount& arguments, 370 const ParameterCount& arguments,
368 Label* miss) { 371 Label* miss) {
369 // ----------- S t a t e ------------- 372 // ----------- S t a t e -------------
370 // -- r0: receiver 373 // -- r0: receiver
371 // -- r1: function to call 374 // -- r1: function to call
372 // ----------------------------------- 375 // -----------------------------------
373 376
374 // Check that the function really is a function. 377 // Check that the function really is a function.
375 __ BranchOnSmi(r1, miss); 378 __ BranchOnSmi(r1, miss);
376 __ CompareObjectType(r1, r2, r2, JS_FUNCTION_TYPE); 379 __ CompareObjectType(r1, r3, r3, JS_FUNCTION_TYPE);
377 __ b(ne, miss); 380 __ b(ne, miss);
378 381
379 // Patch the receiver on the stack with the global proxy if 382 // Patch the receiver on the stack with the global proxy if
380 // necessary. 383 // necessary.
381 if (object->IsGlobalObject()) { 384 if (object->IsGlobalObject()) {
382 __ ldr(r3, FieldMemOperand(r0, GlobalObject::kGlobalReceiverOffset)); 385 __ ldr(r3, FieldMemOperand(r0, GlobalObject::kGlobalReceiverOffset));
383 __ str(r3, MemOperand(sp, arguments.immediate() * kPointerSize)); 386 __ str(r3, MemOperand(sp, arguments.immediate() * kPointerSize));
384 } 387 }
385 388
386 // Invoke the function. 389 // Invoke the function.
387 __ InvokeFunction(r1, arguments, JUMP_FUNCTION); 390 __ InvokeFunction(r1, arguments, JUMP_FUNCTION);
388 } 391 }
389 392
390 393
391 static void GenerateCallConstFunction(MacroAssembler* masm,
392 JSFunction* function,
393 const ParameterCount& arguments) {
394 ASSERT(function->is_compiled());
395
396 // Get the function and setup the context.
397 __ mov(r1, Operand(Handle<JSFunction>(function)));
398 __ ldr(cp, FieldMemOperand(r1, JSFunction::kContextOffset));
399
400 // Jump to the cached code (tail call).
401 Handle<Code> code(function->code());
402 ParameterCount expected(function->shared()->formal_parameter_count());
403 __ InvokeCode(code, expected, arguments,
404 RelocInfo::CODE_TARGET, JUMP_FUNCTION);
405 }
406
407
408 template <class Compiler>
409 static void CompileLoadInterceptor(Compiler* compiler,
410 StubCompiler* stub_compiler,
411 MacroAssembler* masm,
412 JSObject* object,
413 JSObject* holder,
414 String* name,
415 LookupResult* lookup,
416 Register receiver,
417 Register scratch1,
418 Register scratch2,
419 Label* miss) {
420 ASSERT(holder->HasNamedInterceptor());
421 ASSERT(!holder->GetNamedInterceptor()->getter()->IsUndefined());
422
423 // Check that the receiver isn't a smi.
424 __ BranchOnSmi(receiver, miss);
425
426 // Check that the maps haven't changed.
427 Register reg =
428 stub_compiler->CheckPrototypes(object, receiver, holder,
429 scratch1, scratch2, name, miss);
430
431 if (lookup->IsValid() && lookup->IsCacheable()) {
432 compiler->CompileCacheable(masm,
433 stub_compiler,
434 receiver,
435 reg,
436 scratch1,
437 scratch2,
438 holder,
439 lookup,
440 name,
441 miss);
442 } else {
443 compiler->CompileRegular(masm,
444 receiver,
445 reg,
446 scratch2,
447 holder,
448 miss);
449 }
450 }
451
452
453 static void PushInterceptorArguments(MacroAssembler* masm, 394 static void PushInterceptorArguments(MacroAssembler* masm,
454 Register receiver, 395 Register receiver,
455 Register holder, 396 Register holder,
456 Register name, 397 Register name,
457 JSObject* holder_obj) { 398 JSObject* holder_obj) {
458 __ push(receiver); 399 __ push(receiver);
459 __ push(holder); 400 __ push(holder);
460 __ push(name); 401 __ push(name);
461 InterceptorInfo* interceptor = holder_obj->GetNamedInterceptor(); 402 InterceptorInfo* interceptor = holder_obj->GetNamedInterceptor();
462 ASSERT(!Heap::InNewSpace(interceptor)); 403 ASSERT(!Heap::InNewSpace(interceptor));
(...skipping 30 matching lines...) Expand all
493 void CompileCacheable(MacroAssembler* masm, 434 void CompileCacheable(MacroAssembler* masm,
494 StubCompiler* stub_compiler, 435 StubCompiler* stub_compiler,
495 Register receiver, 436 Register receiver,
496 Register holder, 437 Register holder,
497 Register scratch1, 438 Register scratch1,
498 Register scratch2, 439 Register scratch2,
499 JSObject* holder_obj, 440 JSObject* holder_obj,
500 LookupResult* lookup, 441 LookupResult* lookup,
501 String* name, 442 String* name,
502 Label* miss_label) { 443 Label* miss_label) {
503 AccessorInfo* callback = 0; 444 AccessorInfo* callback = NULL;
504 bool optimize = false; 445 bool optimize = false;
505 // So far the most popular follow ups for interceptor loads are FIELD 446 // So far the most popular follow ups for interceptor loads are FIELD
506 // and CALLBACKS, so inline only them, other cases may be added 447 // and CALLBACKS, so inline only them, other cases may be added
507 // later. 448 // later.
508 if (lookup->type() == FIELD) { 449 if (lookup->type() == FIELD) {
509 optimize = true; 450 optimize = true;
510 } else if (lookup->type() == CALLBACKS) { 451 } else if (lookup->type() == CALLBACKS) {
511 Object* callback_object = lookup->GetCallbackObject(); 452 Object* callback_object = lookup->GetCallbackObject();
512 if (callback_object->IsAccessorInfo()) { 453 if (callback_object->IsAccessorInfo()) {
513 callback = AccessorInfo::cast(callback_object); 454 callback = AccessorInfo::cast(callback_object);
514 optimize = callback->getter() != NULL; 455 optimize = callback->getter() != NULL;
515 } 456 }
516 } 457 }
517 458
518 if (!optimize) { 459 if (!optimize) {
519 CompileRegular(masm, receiver, holder, scratch2, holder_obj, miss_label); 460 CompileRegular(masm, receiver, holder, scratch2, holder_obj, miss_label);
520 return; 461 return;
521 } 462 }
522 463
523 // Note: starting a frame here makes GC aware of pointers pushed below. 464 // Note: starting a frame here makes GC aware of pointers pushed below.
524 __ EnterInternalFrame(); 465 __ EnterInternalFrame();
525 466
526 if (lookup->type() == CALLBACKS) { 467 __ push(receiver);
527 __ push(receiver);
528 }
529 __ push(holder); 468 __ push(holder);
530 __ push(name_); 469 __ push(name_);
531 470
532 CompileCallLoadPropertyWithInterceptor(masm, 471 CompileCallLoadPropertyWithInterceptor(masm,
533 receiver, 472 receiver,
534 holder, 473 holder,
535 name_, 474 name_,
536 holder_obj); 475 holder_obj);
537 476
538 Label interceptor_failed; 477 Label interceptor_failed;
539 // Compare with no_interceptor_result_sentinel. 478 // Compare with no_interceptor_result_sentinel.
540 __ LoadRoot(scratch1, Heap::kNoInterceptorResultSentinelRootIndex); 479 __ LoadRoot(scratch1, Heap::kNoInterceptorResultSentinelRootIndex);
541 __ cmp(r0, scratch1); 480 __ cmp(r0, scratch1);
542 __ b(eq, &interceptor_failed); 481 __ b(eq, &interceptor_failed);
543 __ LeaveInternalFrame(); 482 __ LeaveInternalFrame();
544 __ Ret(); 483 __ Ret();
545 484
546 __ bind(&interceptor_failed); 485 __ bind(&interceptor_failed);
547 __ pop(name_); 486 __ pop(name_);
548 __ pop(holder); 487 __ pop(holder);
549 488 __ pop(receiver);
550 if (lookup->type() == CALLBACKS) {
551 __ pop(receiver);
552 }
553 489
554 __ LeaveInternalFrame(); 490 __ LeaveInternalFrame();
555 491
556 if (lookup->type() == FIELD) { 492 if (lookup->type() == FIELD) {
557 holder = stub_compiler->CheckPrototypes(holder_obj, 493 holder = stub_compiler->CheckPrototypes(holder_obj,
558 holder, 494 holder,
559 lookup->holder(), 495 lookup->holder(),
560 scratch1, 496 scratch1,
561 scratch2, 497 scratch2,
562 name, 498 name,
(...skipping 51 matching lines...) Expand 10 before | Expand all | Expand 10 after
614 ExternalReference ref = ExternalReference( 550 ExternalReference ref = ExternalReference(
615 IC_Utility(IC::kLoadPropertyWithInterceptorForLoad)); 551 IC_Utility(IC::kLoadPropertyWithInterceptorForLoad));
616 __ TailCallRuntime(ref, 5, 1); 552 __ TailCallRuntime(ref, 5, 1);
617 } 553 }
618 554
619 private: 555 private:
620 Register name_; 556 Register name_;
621 }; 557 };
622 558
623 559
624 class CallInterceptorCompiler BASE_EMBEDDED { 560 static void CompileLoadInterceptor(LoadInterceptorCompiler* compiler,
625 public: 561 StubCompiler* stub_compiler,
626 CallInterceptorCompiler(const ParameterCount& arguments, Register name) 562 MacroAssembler* masm,
627 : arguments_(arguments), argc_(arguments.immediate()), name_(name) {} 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());
628 573
629 void CompileCacheable(MacroAssembler* masm, 574 // Check that the receiver isn't a smi.
630 StubCompiler* stub_compiler, 575 __ BranchOnSmi(receiver, miss);
631 Register receiver,
632 Register holder,
633 Register scratch1,
634 Register scratch2,
635 JSObject* holder_obj,
636 LookupResult* lookup,
637 String* name,
638 Label* miss_label) {
639 JSFunction* function = 0;
640 bool optimize = false;
641 // So far the most popular case for failed interceptor is
642 // CONSTANT_FUNCTION sitting below.
643 if (lookup->type() == CONSTANT_FUNCTION) {
644 function = lookup->GetConstantFunction();
645 // JSArray holder is a special case for call constant function
646 // (see the corresponding code).
647 if (function->is_compiled() && !holder_obj->IsJSArray()) {
648 optimize = true;
649 }
650 }
651 576
652 if (!optimize) { 577 // Check that the maps haven't changed.
653 CompileRegular(masm, receiver, holder, scratch2, holder_obj, miss_label); 578 Register reg =
654 return; 579 stub_compiler->CheckPrototypes(object, receiver, holder,
655 } 580 scratch1, scratch2, name, miss);
656 581
657 // Constant functions cannot sit on global object. 582 if (lookup->IsProperty() && lookup->IsCacheable()) {
658 ASSERT(!lookup->holder()->IsGlobalObject()); 583 compiler->CompileCacheable(masm,
659 584 stub_compiler,
660 __ EnterInternalFrame(); 585 receiver,
661 __ push(holder); // Save the holder. 586 reg,
662 __ push(name_); // Save the name. 587 scratch1,
663 588 scratch2,
664 CompileCallLoadPropertyWithInterceptor(masm, 589 holder,
665 receiver, 590 lookup,
666 holder, 591 name,
667 name_, 592 miss);
668 holder_obj); 593 } else {
669 594 compiler->CompileRegular(masm,
670 ASSERT(!r0.is(name_)); 595 receiver,
671 ASSERT(!r0.is(scratch1)); 596 reg,
672 __ pop(name_); // Restore the name. 597 scratch2,
673 __ pop(scratch1); // Restore the holder. 598 holder,
674 __ LeaveInternalFrame(); 599 miss);
675
676 // Compare with no_interceptor_result_sentinel.
677 __ LoadRoot(scratch2, Heap::kNoInterceptorResultSentinelRootIndex);
678 __ cmp(r0, scratch2);
679 Label invoke;
680 __ b(ne, &invoke);
681
682 stub_compiler->CheckPrototypes(holder_obj, scratch1,
683 lookup->holder(), scratch1,
684 scratch2,
685 name,
686 miss_label);
687 GenerateCallConstFunction(masm, function, arguments_);
688
689 __ bind(&invoke);
690 } 600 }
691 601 }
692 void CompileRegular(MacroAssembler* masm,
693 Register receiver,
694 Register holder,
695 Register scratch,
696 JSObject* holder_obj,
697 Label* miss_label) {
698 __ EnterInternalFrame();
699 // Save the name_ register across the call.
700 __ push(name_);
701
702 PushInterceptorArguments(masm,
703 receiver,
704 holder,
705 name_,
706 holder_obj);
707
708 ExternalReference ref = ExternalReference(
709 IC_Utility(IC::kLoadPropertyWithInterceptorForCall));
710 __ mov(r0, Operand(5));
711 __ mov(r1, Operand(ref));
712
713 CEntryStub stub(1);
714 __ CallStub(&stub);
715
716 // Restore the name_ register.
717 __ pop(name_);
718 __ LeaveInternalFrame();
719 }
720
721 private:
722 const ParameterCount& arguments_;
723 int argc_;
724 Register name_;
725 };
726 602
727 603
728 #undef __ 604 #undef __
729 #define __ ACCESS_MASM(masm()) 605 #define __ ACCESS_MASM(masm())
730 606
731 607
732 Register StubCompiler::CheckPrototypes(JSObject* object, 608 Register StubCompiler::CheckPrototypes(JSObject* object,
733 Register object_reg, 609 Register object_reg,
734 JSObject* holder, 610 JSObject* holder,
735 Register holder_reg, 611 Register holder_reg,
736 Register scratch, 612 Register scratch,
737 String* name, 613 String* name,
614 int save_at_depth,
738 Label* miss) { 615 Label* miss) {
616 // TODO(602): support object saving.
617 ASSERT(save_at_depth == kInvalidProtoDepth);
618
739 // Check that the maps haven't changed. 619 // Check that the maps haven't changed.
740 Register result = 620 Register result =
741 masm()->CheckMaps(object, object_reg, holder, holder_reg, scratch, miss); 621 masm()->CheckMaps(object, object_reg, holder, holder_reg, scratch, miss);
742 622
743 // If we've skipped any global objects, it's not enough to verify 623 // If we've skipped any global objects, it's not enough to verify
744 // that their maps haven't changed. 624 // that their maps haven't changed.
745 while (object != holder) { 625 while (object != holder) {
746 if (object->IsGlobalObject()) { 626 if (object->IsGlobalObject()) {
747 GlobalObject* global = GlobalObject::cast(object); 627 GlobalObject* global = GlobalObject::cast(object);
748 Object* probe = global->EnsurePropertyCell(name); 628 Object* probe = global->EnsurePropertyCell(name);
749 if (probe->IsFailure()) { 629 if (probe->IsFailure()) {
750 set_failure(Failure::cast(probe)); 630 set_failure(Failure::cast(probe));
751 return result; 631 return result;
752 } 632 }
753 JSGlobalPropertyCell* cell = JSGlobalPropertyCell::cast(probe); 633 JSGlobalPropertyCell* cell = JSGlobalPropertyCell::cast(probe);
754 ASSERT(cell->value()->IsTheHole()); 634 ASSERT(cell->value()->IsTheHole());
755 __ mov(scratch, Operand(Handle<Object>(cell))); 635 __ mov(scratch, Operand(Handle<Object>(cell)));
756 __ ldr(scratch, 636 __ ldr(scratch,
757 FieldMemOperand(scratch, JSGlobalPropertyCell::kValueOffset)); 637 FieldMemOperand(scratch, JSGlobalPropertyCell::kValueOffset));
758 __ LoadRoot(ip, Heap::kTheHoleValueRootIndex); 638 __ LoadRoot(ip, Heap::kTheHoleValueRootIndex);
759 __ cmp(scratch, ip); 639 __ cmp(scratch, ip);
760 __ b(ne, miss); 640 __ b(ne, miss);
761 } 641 }
762 object = JSObject::cast(object->GetPrototype()); 642 object = JSObject::cast(object->GetPrototype());
763 } 643 }
764 644
765 // Return the register containin the holder. 645 // Return the register containing the holder.
766 return result; 646 return result;
767 } 647 }
768 648
769 649
770 void StubCompiler::GenerateLoadField(JSObject* object, 650 void StubCompiler::GenerateLoadField(JSObject* object,
771 JSObject* holder, 651 JSObject* holder,
772 Register receiver, 652 Register receiver,
773 Register scratch1, 653 Register scratch1,
774 Register scratch2, 654 Register scratch2,
775 int index, 655 int index,
(...skipping 118 matching lines...) Expand 10 before | Expand all | Expand 10 after
894 // Tear down temporary frame. 774 // Tear down temporary frame.
895 __ LeaveInternalFrame(); 775 __ LeaveInternalFrame();
896 776
897 // Do a tail-call of the compiled function. 777 // Do a tail-call of the compiled function.
898 __ Jump(r2); 778 __ Jump(r2);
899 779
900 return GetCodeWithFlags(flags, "LazyCompileStub"); 780 return GetCodeWithFlags(flags, "LazyCompileStub");
901 } 781 }
902 782
903 783
904 Object* CallStubCompiler::CompileCallField(Object* object, 784 Object* CallStubCompiler::CompileCallField(JSObject* object,
905 JSObject* holder, 785 JSObject* holder,
906 int index, 786 int index,
907 String* name) { 787 String* name) {
908 // ----------- S t a t e ------------- 788 // ----------- S t a t e -------------
909 // -- lr: return address 789 // -- r2 : name
790 // -- lr : return address
910 // ----------------------------------- 791 // -----------------------------------
911 Label miss; 792 Label miss;
912 793
913 const int argc = arguments().immediate(); 794 const int argc = arguments().immediate();
914 795
915 // Get the receiver of the function from the stack into r0. 796 // Get the receiver of the function from the stack into r0.
916 __ ldr(r0, MemOperand(sp, argc * kPointerSize)); 797 __ ldr(r0, MemOperand(sp, argc * kPointerSize));
917 // Check that the receiver isn't a smi. 798 // Check that the receiver isn't a smi.
918 __ tst(r0, Operand(kSmiTagMask)); 799 __ tst(r0, Operand(kSmiTagMask));
919 __ b(eq, &miss); 800 __ b(eq, &miss);
920 801
921 // Do the right check and compute the holder register. 802 // Do the right check and compute the holder register.
922 Register reg = 803 Register reg = CheckPrototypes(object, r0, holder, r1, r3, name, &miss);
923 CheckPrototypes(JSObject::cast(object), r0, holder, r3, r2, name, &miss);
924 GenerateFastPropertyLoad(masm(), r1, reg, holder, index); 804 GenerateFastPropertyLoad(masm(), r1, reg, holder, index);
925 805
926 GenerateCallFunction(masm(), object, arguments(), &miss); 806 GenerateCallFunction(masm(), object, arguments(), &miss);
927 807
928 // Handle call cache miss. 808 // Handle call cache miss.
929 __ bind(&miss); 809 __ bind(&miss);
930 Handle<Code> ic = ComputeCallMiss(arguments().immediate()); 810 Handle<Code> ic = ComputeCallMiss(arguments().immediate());
931 __ Jump(ic, RelocInfo::CODE_TARGET); 811 __ Jump(ic, RelocInfo::CODE_TARGET);
932 812
933 // Return the generated code. 813 // Return the generated code.
934 return GetCode(FIELD, name); 814 return GetCode(FIELD, name);
935 } 815 }
936 816
937 817
938 Object* CallStubCompiler::CompileCallConstant(Object* object, 818 Object* CallStubCompiler::CompileCallConstant(Object* object,
939 JSObject* holder, 819 JSObject* holder,
940 JSFunction* function, 820 JSFunction* function,
941 String* name, 821 String* name,
942 CheckType check) { 822 CheckType check) {
943 // ----------- S t a t e ------------- 823 // ----------- S t a t e -------------
944 // -- lr: return address 824 // -- r2 : name
825 // -- lr : return address
945 // ----------------------------------- 826 // -----------------------------------
946 Label miss; 827 Label miss;
947 828
948 // Get the receiver from the stack 829 // Get the receiver from the stack
949 const int argc = arguments().immediate(); 830 const int argc = arguments().immediate();
950 __ ldr(r1, MemOperand(sp, argc * kPointerSize)); 831 __ ldr(r1, MemOperand(sp, argc * kPointerSize));
951 832
952 // Check that the receiver isn't a smi. 833 // Check that the receiver isn't a smi.
953 if (check != NUMBER_CHECK) { 834 if (check != NUMBER_CHECK) {
954 __ tst(r1, Operand(kSmiTagMask)); 835 __ tst(r1, Operand(kSmiTagMask));
955 __ b(eq, &miss); 836 __ b(eq, &miss);
956 } 837 }
957 838
958 // Make sure that it's okay not to patch the on stack receiver 839 // Make sure that it's okay not to patch the on stack receiver
959 // unless we're doing a receiver map check. 840 // unless we're doing a receiver map check.
960 ASSERT(!object->IsGlobalObject() || check == RECEIVER_MAP_CHECK); 841 ASSERT(!object->IsGlobalObject() || check == RECEIVER_MAP_CHECK);
961 842
962 switch (check) { 843 switch (check) {
963 case RECEIVER_MAP_CHECK: 844 case RECEIVER_MAP_CHECK:
964 // Check that the maps haven't changed. 845 // Check that the maps haven't changed.
965 CheckPrototypes(JSObject::cast(object), r1, holder, r3, r2, name, &miss); 846 CheckPrototypes(JSObject::cast(object), r1, holder, r3, r0, name, &miss);
966 847
967 // Patch the receiver on the stack with the global proxy if 848 // Patch the receiver on the stack with the global proxy if
968 // necessary. 849 // necessary.
969 if (object->IsGlobalObject()) { 850 if (object->IsGlobalObject()) {
970 __ ldr(r3, FieldMemOperand(r1, GlobalObject::kGlobalReceiverOffset)); 851 __ ldr(r3, FieldMemOperand(r1, GlobalObject::kGlobalReceiverOffset));
971 __ str(r3, MemOperand(sp, argc * kPointerSize)); 852 __ str(r3, MemOperand(sp, argc * kPointerSize));
972 } 853 }
973 break; 854 break;
974 855
975 case STRING_CHECK: 856 case STRING_CHECK:
976 if (!function->IsBuiltin()) { 857 if (!function->IsBuiltin()) {
977 // Calling non-builtins with a value as receiver requires boxing. 858 // Calling non-builtins with a value as receiver requires boxing.
978 __ jmp(&miss); 859 __ jmp(&miss);
979 } else { 860 } else {
980 // Check that the object is a two-byte string or a symbol. 861 // Check that the object is a two-byte string or a symbol.
981 __ CompareObjectType(r1, r2, r2, FIRST_NONSTRING_TYPE); 862 __ CompareObjectType(r1, r3, r3, FIRST_NONSTRING_TYPE);
982 __ b(hs, &miss); 863 __ b(hs, &miss);
983 // Check that the maps starting from the prototype haven't changed. 864 // Check that the maps starting from the prototype haven't changed.
984 GenerateLoadGlobalFunctionPrototype(masm(), 865 GenerateLoadGlobalFunctionPrototype(masm(),
985 Context::STRING_FUNCTION_INDEX, 866 Context::STRING_FUNCTION_INDEX,
986 r2); 867 r0);
987 CheckPrototypes(JSObject::cast(object->GetPrototype()), r2, holder, r3, 868 CheckPrototypes(JSObject::cast(object->GetPrototype()), r0, holder, r3,
988 r1, name, &miss); 869 r1, name, &miss);
989 } 870 }
990 break; 871 break;
991 872
992 case NUMBER_CHECK: { 873 case NUMBER_CHECK: {
993 if (!function->IsBuiltin()) { 874 if (!function->IsBuiltin()) {
994 // Calling non-builtins with a value as receiver requires boxing. 875 // Calling non-builtins with a value as receiver requires boxing.
995 __ jmp(&miss); 876 __ jmp(&miss);
996 } else { 877 } else {
997 Label fast; 878 Label fast;
998 // Check that the object is a smi or a heap number. 879 // Check that the object is a smi or a heap number.
999 __ tst(r1, Operand(kSmiTagMask)); 880 __ tst(r1, Operand(kSmiTagMask));
1000 __ b(eq, &fast); 881 __ b(eq, &fast);
1001 __ CompareObjectType(r1, r2, r2, HEAP_NUMBER_TYPE); 882 __ CompareObjectType(r1, r0, r0, HEAP_NUMBER_TYPE);
1002 __ b(ne, &miss); 883 __ b(ne, &miss);
1003 __ bind(&fast); 884 __ bind(&fast);
1004 // Check that the maps starting from the prototype haven't changed. 885 // Check that the maps starting from the prototype haven't changed.
1005 GenerateLoadGlobalFunctionPrototype(masm(), 886 GenerateLoadGlobalFunctionPrototype(masm(),
1006 Context::NUMBER_FUNCTION_INDEX, 887 Context::NUMBER_FUNCTION_INDEX,
1007 r2); 888 r0);
1008 CheckPrototypes(JSObject::cast(object->GetPrototype()), r2, holder, r3, 889 CheckPrototypes(JSObject::cast(object->GetPrototype()), r0, holder, r3,
1009 r1, name, &miss); 890 r1, name, &miss);
1010 } 891 }
1011 break; 892 break;
1012 } 893 }
1013 894
1014 case BOOLEAN_CHECK: { 895 case BOOLEAN_CHECK: {
1015 if (!function->IsBuiltin()) { 896 if (!function->IsBuiltin()) {
1016 // Calling non-builtins with a value as receiver requires boxing. 897 // Calling non-builtins with a value as receiver requires boxing.
1017 __ jmp(&miss); 898 __ jmp(&miss);
1018 } else { 899 } else {
1019 Label fast; 900 Label fast;
1020 // Check that the object is a boolean. 901 // Check that the object is a boolean.
1021 __ LoadRoot(ip, Heap::kTrueValueRootIndex); 902 __ LoadRoot(ip, Heap::kTrueValueRootIndex);
1022 __ cmp(r1, ip); 903 __ cmp(r1, ip);
1023 __ b(eq, &fast); 904 __ b(eq, &fast);
1024 __ LoadRoot(ip, Heap::kFalseValueRootIndex); 905 __ LoadRoot(ip, Heap::kFalseValueRootIndex);
1025 __ cmp(r1, ip); 906 __ cmp(r1, ip);
1026 __ b(ne, &miss); 907 __ b(ne, &miss);
1027 __ bind(&fast); 908 __ bind(&fast);
1028 // Check that the maps starting from the prototype haven't changed. 909 // Check that the maps starting from the prototype haven't changed.
1029 GenerateLoadGlobalFunctionPrototype(masm(), 910 GenerateLoadGlobalFunctionPrototype(masm(),
1030 Context::BOOLEAN_FUNCTION_INDEX, 911 Context::BOOLEAN_FUNCTION_INDEX,
1031 r2); 912 r0);
1032 CheckPrototypes(JSObject::cast(object->GetPrototype()), r2, holder, r3, 913 CheckPrototypes(JSObject::cast(object->GetPrototype()), r0, holder, r3,
1033 r1, name, &miss); 914 r1, name, &miss);
1034 } 915 }
1035 break; 916 break;
1036 } 917 }
1037 918
1038 case JSARRAY_HAS_FAST_ELEMENTS_CHECK: 919 case JSARRAY_HAS_FAST_ELEMENTS_CHECK:
1039 CheckPrototypes(JSObject::cast(object), r1, holder, r3, r2, name, &miss); 920 CheckPrototypes(JSObject::cast(object), r1, holder, r3, r0, name, &miss);
1040 // Make sure object->HasFastElements(). 921 // Make sure object->HasFastElements().
1041 // Get the elements array of the object. 922 // Get the elements array of the object.
1042 __ ldr(r3, FieldMemOperand(r1, JSObject::kElementsOffset)); 923 __ ldr(r3, FieldMemOperand(r1, JSObject::kElementsOffset));
1043 // Check that the object is in fast mode (not dictionary). 924 // Check that the object is in fast mode (not dictionary).
1044 __ ldr(r2, FieldMemOperand(r3, HeapObject::kMapOffset)); 925 __ ldr(r0, FieldMemOperand(r3, HeapObject::kMapOffset));
1045 __ LoadRoot(ip, Heap::kFixedArrayMapRootIndex); 926 __ LoadRoot(ip, Heap::kFixedArrayMapRootIndex);
1046 __ cmp(r2, ip); 927 __ cmp(r0, ip);
1047 __ b(ne, &miss); 928 __ b(ne, &miss);
1048 break; 929 break;
1049 930
1050 default: 931 default:
1051 UNREACHABLE(); 932 UNREACHABLE();
1052 } 933 }
1053 934
1054 GenerateCallConstFunction(masm(), function, arguments()); 935 __ InvokeFunction(function, arguments(), JUMP_FUNCTION);
1055 936
1056 // Handle call cache miss. 937 // Handle call cache miss.
1057 __ bind(&miss); 938 __ bind(&miss);
1058 Handle<Code> ic = ComputeCallMiss(arguments().immediate()); 939 Handle<Code> ic = ComputeCallMiss(arguments().immediate());
1059 __ Jump(ic, RelocInfo::CODE_TARGET); 940 __ Jump(ic, RelocInfo::CODE_TARGET);
1060 941
1061 // Return the generated code. 942 // Return the generated code.
1062 String* function_name = NULL; 943 String* function_name = NULL;
1063 if (function->shared()->name()->IsString()) { 944 if (function->shared()->name()->IsString()) {
1064 function_name = String::cast(function->shared()->name()); 945 function_name = String::cast(function->shared()->name());
1065 } 946 }
1066 return GetCode(CONSTANT_FUNCTION, function_name); 947 return GetCode(CONSTANT_FUNCTION, function_name);
1067 } 948 }
1068 949
1069 950
1070 Object* CallStubCompiler::CompileCallInterceptor(Object* object, 951 Object* CallStubCompiler::CompileCallInterceptor(JSObject* object,
1071 JSObject* holder, 952 JSObject* holder,
1072 String* name) { 953 String* name) {
1073 // ----------- S t a t e ------------- 954 // ----------- S t a t e -------------
1074 // -- lr: return address 955 // -- r2 : name
956 // -- lr : return address
1075 // ----------------------------------- 957 // -----------------------------------
958 ASSERT(holder->HasNamedInterceptor());
959 ASSERT(!holder->GetNamedInterceptor()->getter()->IsUndefined());
1076 Label miss; 960 Label miss;
1077 961
962 const Register receiver = r0;
963 const Register holder_reg = r1;
964 const Register name_reg = r2;
965 const Register scratch = r3;
966
1078 // Get the number of arguments. 967 // Get the number of arguments.
1079 const int argc = arguments().immediate(); 968 const int argc = arguments().immediate();
1080 969
1081 LookupResult lookup; 970 LookupResult lookup;
1082 LookupPostInterceptor(holder, name, &lookup); 971 LookupPostInterceptor(holder, name, &lookup);
1083 972
1084 // Get the receiver from the stack into r0. 973 // Get the receiver from the stack into r0.
1085 __ ldr(r0, MemOperand(sp, argc * kPointerSize)); 974 __ ldr(r0, MemOperand(sp, argc * kPointerSize));
1086 // Load the name from the stack into r1.
1087 __ ldr(r1, MemOperand(sp, (argc + 1) * kPointerSize));
1088 975
1089 CallInterceptorCompiler compiler(arguments(), r1); 976 // Check that the receiver isn't a smi.
1090 CompileLoadInterceptor(&compiler, 977 __ BranchOnSmi(receiver, &miss);
1091 this,
1092 masm(),
1093 JSObject::cast(object),
1094 holder,
1095 name,
1096 &lookup,
1097 r0,
1098 r2,
1099 r3,
1100 &miss);
1101 978
979 // Check that the maps haven't changed.
980 Register reg = CheckPrototypes(object, receiver, holder, holder_reg,
981 scratch, name, &miss);
982 if (!reg.is(holder_reg)) {
983 __ mov(holder_reg, reg);
984 }
985
986 // If we call a constant function when the interceptor returns
987 // the no-result sentinel, generate code that optimizes this case.
988 if (lookup.IsProperty() &&
989 lookup.IsCacheable() &&
990 lookup.type() == CONSTANT_FUNCTION &&
991 lookup.GetConstantFunction()->is_compiled() &&
992 !holder->IsJSArray()) {
993 // Constant functions cannot sit on global object.
994 ASSERT(!lookup.holder()->IsGlobalObject());
995
996 // Call the interceptor.
997 __ EnterInternalFrame();
998 __ push(holder_reg);
999 __ push(name_reg);
1000 CompileCallLoadPropertyWithInterceptor(masm(),
1001 receiver,
1002 holder_reg,
1003 name_reg,
1004 holder);
1005 __ pop(name_reg);
1006 __ pop(holder_reg);
1007 __ LeaveInternalFrame();
1008 // r0 no longer contains the receiver.
1009
1010 // If interceptor returns no-result sentinal, call the constant function.
1011 __ LoadRoot(scratch, Heap::kNoInterceptorResultSentinelRootIndex);
1012 __ cmp(r0, scratch);
1013 Label invoke;
1014 __ b(ne, &invoke);
1015 // Check the prototypes between the interceptor's holder and the
1016 // constant function's holder.
1017 CheckPrototypes(holder, holder_reg,
1018 lookup.holder(), r0,
1019 scratch,
1020 name,
1021 &miss);
1022
1023 __ InvokeFunction(lookup.GetConstantFunction(),
1024 arguments(),
1025 JUMP_FUNCTION);
1026
1027 __ bind(&invoke);
1028
1029 } else {
1030 // Call a runtime function to load the interceptor property.
1031 __ EnterInternalFrame();
1032 __ push(name_reg);
1033
1034 PushInterceptorArguments(masm(), receiver, holder_reg, name_reg, holder);
1035
1036 __ CallExternalReference(
1037 ExternalReference(IC_Utility(IC::kLoadPropertyWithInterceptorForCall)),
1038 5);
1039
1040 __ pop(name_reg);
1041 __ LeaveInternalFrame();
1042 }
1043
1044 // Move returned value, the function to call, to r1.
1045 __ mov(r1, r0);
1102 // Restore receiver. 1046 // Restore receiver.
1103 __ ldr(r0, MemOperand(sp, argc * kPointerSize)); 1047 __ ldr(receiver, MemOperand(sp, argc * kPointerSize));
1104 1048
1105 GenerateCallFunction(masm(), object, arguments(), &miss); 1049 GenerateCallFunction(masm(), object, arguments(), &miss);
1106 1050
1107 // Handle call cache miss. 1051 // Handle call cache miss.
1108 __ bind(&miss); 1052 __ bind(&miss);
1109 Handle<Code> ic = ComputeCallMiss(arguments().immediate()); 1053 Handle<Code> ic = ComputeCallMiss(arguments().immediate());
1110 __ Jump(ic, RelocInfo::CODE_TARGET); 1054 __ Jump(ic, RelocInfo::CODE_TARGET);
1111 1055
1112 // Return the generated code. 1056 // Return the generated code.
1113 return GetCode(INTERCEPTOR, name); 1057 return GetCode(INTERCEPTOR, name);
1114 } 1058 }
1115 1059
1116 1060
1117 Object* CallStubCompiler::CompileCallGlobal(JSObject* object, 1061 Object* CallStubCompiler::CompileCallGlobal(JSObject* object,
1118 GlobalObject* holder, 1062 GlobalObject* holder,
1119 JSGlobalPropertyCell* cell, 1063 JSGlobalPropertyCell* cell,
1120 JSFunction* function, 1064 JSFunction* function,
1121 String* name) { 1065 String* name) {
1122 // ----------- S t a t e ------------- 1066 // ----------- S t a t e -------------
1123 // -- lr: return address 1067 // -- r2 : name
1068 // -- lr : return address
1124 // ----------------------------------- 1069 // -----------------------------------
1125 Label miss; 1070 Label miss;
1126 1071
1127 // Get the number of arguments. 1072 // Get the number of arguments.
1128 const int argc = arguments().immediate(); 1073 const int argc = arguments().immediate();
1129 1074
1130 // Get the receiver from the stack. 1075 // Get the receiver from the stack.
1131 __ ldr(r0, MemOperand(sp, argc * kPointerSize)); 1076 __ ldr(r0, MemOperand(sp, argc * kPointerSize));
1132 1077
1133 // If the object is the holder then we know that it's a global 1078 // If the object is the holder then we know that it's a global
1134 // object which can only happen for contextual calls. In this case, 1079 // object which can only happen for contextual calls. In this case,
1135 // the receiver cannot be a smi. 1080 // the receiver cannot be a smi.
1136 if (object != holder) { 1081 if (object != holder) {
1137 __ tst(r0, Operand(kSmiTagMask)); 1082 __ tst(r0, Operand(kSmiTagMask));
1138 __ b(eq, &miss); 1083 __ b(eq, &miss);
1139 } 1084 }
1140 1085
1141 // Check that the maps haven't changed. 1086 // Check that the maps haven't changed.
1142 CheckPrototypes(object, r0, holder, r3, r2, name, &miss); 1087 CheckPrototypes(object, r0, holder, r3, r1, name, &miss);
1143 1088
1144 // Get the value from the cell. 1089 // Get the value from the cell.
1145 __ mov(r3, Operand(Handle<JSGlobalPropertyCell>(cell))); 1090 __ mov(r3, Operand(Handle<JSGlobalPropertyCell>(cell)));
1146 __ ldr(r1, FieldMemOperand(r3, JSGlobalPropertyCell::kValueOffset)); 1091 __ ldr(r1, FieldMemOperand(r3, JSGlobalPropertyCell::kValueOffset));
1147 1092
1148 // Check that the cell contains the same function. 1093 // Check that the cell contains the same function.
1149 if (Heap::InNewSpace(function)) { 1094 if (Heap::InNewSpace(function)) {
1150 // We can't embed a pointer to a function in new space so we have 1095 // We can't embed a pointer to a function in new space so we have
1151 // to verify that the shared function info is unchanged. This has 1096 // to verify that the shared function info is unchanged. This has
1152 // the nice side effect that multiple closures based on the same 1097 // the nice side effect that multiple closures based on the same
1153 // function can all use this call IC. Before we load through the 1098 // function can all use this call IC. Before we load through the
1154 // function, we have to verify that it still is a function. 1099 // function, we have to verify that it still is a function.
1155 __ tst(r1, Operand(kSmiTagMask)); 1100 __ tst(r1, Operand(kSmiTagMask));
1156 __ b(eq, &miss); 1101 __ b(eq, &miss);
1157 __ CompareObjectType(r1, r3, r3, JS_FUNCTION_TYPE); 1102 __ CompareObjectType(r1, r3, r3, JS_FUNCTION_TYPE);
1158 __ b(ne, &miss); 1103 __ b(ne, &miss);
1159 1104
1160 // Check the shared function info. Make sure it hasn't changed. 1105 // Check the shared function info. Make sure it hasn't changed.
1161 __ mov(r3, Operand(Handle<SharedFunctionInfo>(function->shared()))); 1106 __ mov(r3, Operand(Handle<SharedFunctionInfo>(function->shared())));
1162 __ ldr(r2, FieldMemOperand(r1, JSFunction::kSharedFunctionInfoOffset)); 1107 __ ldr(r4, FieldMemOperand(r1, JSFunction::kSharedFunctionInfoOffset));
1163 __ cmp(r2, r3); 1108 __ cmp(r4, r3);
1164 __ b(ne, &miss); 1109 __ b(ne, &miss);
1165 } else { 1110 } else {
1166 __ cmp(r1, Operand(Handle<JSFunction>(function))); 1111 __ cmp(r1, Operand(Handle<JSFunction>(function)));
1167 __ b(ne, &miss); 1112 __ b(ne, &miss);
1168 } 1113 }
1169 1114
1170 // Patch the receiver on the stack with the global proxy if 1115 // Patch the receiver on the stack with the global proxy if
1171 // necessary. 1116 // necessary.
1172 if (object->IsGlobalObject()) { 1117 if (object->IsGlobalObject()) {
1173 __ ldr(r3, FieldMemOperand(r0, GlobalObject::kGlobalReceiverOffset)); 1118 __ ldr(r3, FieldMemOperand(r0, GlobalObject::kGlobalReceiverOffset));
1174 __ str(r3, MemOperand(sp, argc * kPointerSize)); 1119 __ str(r3, MemOperand(sp, argc * kPointerSize));
1175 } 1120 }
1176 1121
1177 // Setup the context (function already in r1). 1122 // Setup the context (function already in r1).
1178 __ ldr(cp, FieldMemOperand(r1, JSFunction::kContextOffset)); 1123 __ ldr(cp, FieldMemOperand(r1, JSFunction::kContextOffset));
1179 1124
1180 // Jump to the cached code (tail call). 1125 // Jump to the cached code (tail call).
1181 __ IncrementCounter(&Counters::call_global_inline, 1, r2, r3); 1126 __ IncrementCounter(&Counters::call_global_inline, 1, r1, r3);
1182 ASSERT(function->is_compiled()); 1127 ASSERT(function->is_compiled());
1183 Handle<Code> code(function->code()); 1128 Handle<Code> code(function->code());
1184 ParameterCount expected(function->shared()->formal_parameter_count()); 1129 ParameterCount expected(function->shared()->formal_parameter_count());
1185 __ InvokeCode(code, expected, arguments(), 1130 __ InvokeCode(code, expected, arguments(),
1186 RelocInfo::CODE_TARGET, JUMP_FUNCTION); 1131 RelocInfo::CODE_TARGET, JUMP_FUNCTION);
1187 1132
1188 // Handle call cache miss. 1133 // Handle call cache miss.
1189 __ bind(&miss); 1134 __ bind(&miss);
1190 __ IncrementCounter(&Counters::call_global_inline_miss, 1, r1, r3); 1135 __ IncrementCounter(&Counters::call_global_inline_miss, 1, r1, r3);
1191 Handle<Code> ic = ComputeCallMiss(arguments().immediate()); 1136 Handle<Code> ic = ComputeCallMiss(arguments().immediate());
1192 __ Jump(ic, RelocInfo::CODE_TARGET); 1137 __ Jump(ic, RelocInfo::CODE_TARGET);
1193 1138
1194 // Return the generated code. 1139 // Return the generated code.
1195 return GetCode(NORMAL, name); 1140 return GetCode(NORMAL, name);
1196 } 1141 }
1197 1142
1198 1143
1199 Object* StoreStubCompiler::CompileStoreField(JSObject* object, 1144 Object* StoreStubCompiler::CompileStoreField(JSObject* object,
1200 int index, 1145 int index,
1201 Map* transition, 1146 Map* transition,
1202 String* name) { 1147 String* name) {
1203 // ----------- S t a t e ------------- 1148 // ----------- S t a t e -------------
1204 // -- r0 : value 1149 // -- r0 : value
1150 // -- r1 : receiver
1205 // -- r2 : name 1151 // -- r2 : name
1206 // -- lr : return address 1152 // -- lr : return address
1207 // -- [sp] : receiver
1208 // ----------------------------------- 1153 // -----------------------------------
1209 Label miss; 1154 Label miss;
1210 1155
1211 // Get the receiver from the stack.
1212 __ ldr(r3, MemOperand(sp, 0 * kPointerSize));
1213
1214 // name register might be clobbered.
1215 GenerateStoreField(masm(), 1156 GenerateStoreField(masm(),
1216 Builtins::StoreIC_ExtendStorage,
1217 object, 1157 object,
1218 index, 1158 index,
1219 transition, 1159 transition,
1220 r3, r2, r1, 1160 r1, r2, r3,
1221 &miss); 1161 &miss);
1222 __ bind(&miss); 1162 __ bind(&miss);
1223 __ mov(r2, Operand(Handle<String>(name))); // restore name
1224 Handle<Code> ic(Builtins::builtin(Builtins::StoreIC_Miss)); 1163 Handle<Code> ic(Builtins::builtin(Builtins::StoreIC_Miss));
1225 __ Jump(ic, RelocInfo::CODE_TARGET); 1164 __ Jump(ic, RelocInfo::CODE_TARGET);
1226 1165
1227 // Return the generated code. 1166 // Return the generated code.
1228 return GetCode(transition == NULL ? FIELD : MAP_TRANSITION, name); 1167 return GetCode(transition == NULL ? FIELD : MAP_TRANSITION, name);
1229 } 1168 }
1230 1169
1231 1170
1232 Object* StoreStubCompiler::CompileStoreCallback(JSObject* object, 1171 Object* StoreStubCompiler::CompileStoreCallback(JSObject* object,
1233 AccessorInfo* callback, 1172 AccessorInfo* callback,
1234 String* name) { 1173 String* name) {
1235 // ----------- S t a t e ------------- 1174 // ----------- S t a t e -------------
1236 // -- r0 : value 1175 // -- r0 : value
1176 // -- r1 : receiver
1237 // -- r2 : name 1177 // -- r2 : name
1238 // -- lr : return address 1178 // -- lr : return address
1239 // -- [sp] : receiver
1240 // ----------------------------------- 1179 // -----------------------------------
1241 Label miss; 1180 Label miss;
1242 1181
1243 // Get the object from the stack.
1244 __ ldr(r3, MemOperand(sp, 0 * kPointerSize));
1245
1246 // Check that the object isn't a smi. 1182 // Check that the object isn't a smi.
1247 __ tst(r3, Operand(kSmiTagMask)); 1183 __ tst(r1, Operand(kSmiTagMask));
1248 __ b(eq, &miss); 1184 __ b(eq, &miss);
1249 1185
1250 // Check that the map of the object hasn't changed. 1186 // Check that the map of the object hasn't changed.
1251 __ ldr(r1, FieldMemOperand(r3, HeapObject::kMapOffset)); 1187 __ ldr(r3, FieldMemOperand(r1, HeapObject::kMapOffset));
1252 __ cmp(r1, Operand(Handle<Map>(object->map()))); 1188 __ cmp(r3, Operand(Handle<Map>(object->map())));
1253 __ b(ne, &miss); 1189 __ b(ne, &miss);
1254 1190
1255 // Perform global security token check if needed. 1191 // Perform global security token check if needed.
1256 if (object->IsJSGlobalProxy()) { 1192 if (object->IsJSGlobalProxy()) {
1257 __ CheckAccessGlobalProxy(r3, r1, &miss); 1193 __ CheckAccessGlobalProxy(r1, r3, &miss);
1258 } 1194 }
1259 1195
1260 // Stub never generated for non-global objects that require access 1196 // Stub never generated for non-global objects that require access
1261 // checks. 1197 // checks.
1262 ASSERT(object->IsJSGlobalProxy() || !object->IsAccessCheckNeeded()); 1198 ASSERT(object->IsJSGlobalProxy() || !object->IsAccessCheckNeeded());
1263 1199
1264 __ ldr(ip, MemOperand(sp)); // receiver 1200 __ push(r1); // receiver
1265 __ push(ip);
1266 __ mov(ip, Operand(Handle<AccessorInfo>(callback))); // callback info 1201 __ mov(ip, Operand(Handle<AccessorInfo>(callback))); // callback info
1267 __ push(ip); 1202 __ stm(db_w, sp, ip.bit() | r2.bit() | r0.bit());
1268 __ push(r2); // name
1269 __ push(r0); // value
1270 1203
1271 // Do tail-call to the runtime system. 1204 // Do tail-call to the runtime system.
1272 ExternalReference store_callback_property = 1205 ExternalReference store_callback_property =
1273 ExternalReference(IC_Utility(IC::kStoreCallbackProperty)); 1206 ExternalReference(IC_Utility(IC::kStoreCallbackProperty));
1274 __ TailCallRuntime(store_callback_property, 4, 1); 1207 __ TailCallRuntime(store_callback_property, 4, 1);
1275 1208
1276 // Handle store cache miss. 1209 // Handle store cache miss.
1277 __ bind(&miss); 1210 __ bind(&miss);
1278 Handle<Code> ic(Builtins::builtin(Builtins::StoreIC_Miss)); 1211 Handle<Code> ic(Builtins::builtin(Builtins::StoreIC_Miss));
1279 __ Jump(ic, RelocInfo::CODE_TARGET); 1212 __ Jump(ic, RelocInfo::CODE_TARGET);
1280 1213
1281 // Return the generated code. 1214 // Return the generated code.
1282 return GetCode(CALLBACKS, name); 1215 return GetCode(CALLBACKS, name);
1283 } 1216 }
1284 1217
1285 1218
1286 Object* StoreStubCompiler::CompileStoreInterceptor(JSObject* receiver, 1219 Object* StoreStubCompiler::CompileStoreInterceptor(JSObject* receiver,
1287 String* name) { 1220 String* name) {
1288 // ----------- S t a t e ------------- 1221 // ----------- S t a t e -------------
1289 // -- r0 : value 1222 // -- r0 : value
1223 // -- r1 : receiver
1290 // -- r2 : name 1224 // -- r2 : name
1291 // -- lr : return address 1225 // -- lr : return address
1292 // -- [sp] : receiver
1293 // ----------------------------------- 1226 // -----------------------------------
1294 Label miss; 1227 Label miss;
1295 1228
1296 // Get the object from the stack.
1297 __ ldr(r3, MemOperand(sp, 0 * kPointerSize));
1298
1299 // Check that the object isn't a smi. 1229 // Check that the object isn't a smi.
1300 __ tst(r3, Operand(kSmiTagMask)); 1230 __ tst(r1, Operand(kSmiTagMask));
1301 __ b(eq, &miss); 1231 __ b(eq, &miss);
1302 1232
1303 // Check that the map of the object hasn't changed. 1233 // Check that the map of the object hasn't changed.
1304 __ ldr(r1, FieldMemOperand(r3, HeapObject::kMapOffset)); 1234 __ ldr(r3, FieldMemOperand(r1, HeapObject::kMapOffset));
1305 __ cmp(r1, Operand(Handle<Map>(receiver->map()))); 1235 __ cmp(r3, Operand(Handle<Map>(receiver->map())));
1306 __ b(ne, &miss); 1236 __ b(ne, &miss);
1307 1237
1308 // Perform global security token check if needed. 1238 // Perform global security token check if needed.
1309 if (receiver->IsJSGlobalProxy()) { 1239 if (receiver->IsJSGlobalProxy()) {
1310 __ CheckAccessGlobalProxy(r3, r1, &miss); 1240 __ CheckAccessGlobalProxy(r1, r3, &miss);
1311 } 1241 }
1312 1242
1313 // Stub never generated for non-global objects that require access 1243 // Stub is never generated for non-global objects that require access
1314 // checks. 1244 // checks.
1315 ASSERT(receiver->IsJSGlobalProxy() || !receiver->IsAccessCheckNeeded()); 1245 ASSERT(receiver->IsJSGlobalProxy() || !receiver->IsAccessCheckNeeded());
1316 1246
1317 __ ldr(ip, MemOperand(sp)); // receiver 1247 __ push(r1); // receiver.
1318 __ push(ip); 1248 __ push(r2); // name.
1319 __ push(r2); // name 1249 __ push(r0); // value.
1320 __ push(r0); // value
1321 1250
1322 // Do tail-call to the runtime system. 1251 // Do tail-call to the runtime system.
1323 ExternalReference store_ic_property = 1252 ExternalReference store_ic_property =
1324 ExternalReference(IC_Utility(IC::kStoreInterceptorProperty)); 1253 ExternalReference(IC_Utility(IC::kStoreInterceptorProperty));
1325 __ TailCallRuntime(store_ic_property, 3, 1); 1254 __ TailCallRuntime(store_ic_property, 3, 1);
1326 1255
1327 // Handle store cache miss. 1256 // Handle store cache miss.
1328 __ bind(&miss); 1257 __ bind(&miss);
1329 Handle<Code> ic(Builtins::builtin(Builtins::StoreIC_Miss)); 1258 Handle<Code> ic(Builtins::builtin(Builtins::StoreIC_Miss));
1330 __ Jump(ic, RelocInfo::CODE_TARGET); 1259 __ Jump(ic, RelocInfo::CODE_TARGET);
1331 1260
1332 // Return the generated code. 1261 // Return the generated code.
1333 return GetCode(INTERCEPTOR, name); 1262 return GetCode(INTERCEPTOR, name);
1334 } 1263 }
1335 1264
1336 1265
1337 Object* StoreStubCompiler::CompileStoreGlobal(GlobalObject* object, 1266 Object* StoreStubCompiler::CompileStoreGlobal(GlobalObject* object,
1338 JSGlobalPropertyCell* cell, 1267 JSGlobalPropertyCell* cell,
1339 String* name) { 1268 String* name) {
1340 // ----------- S t a t e ------------- 1269 // ----------- S t a t e -------------
1341 // -- r0 : value 1270 // -- r0 : value
1271 // -- r1 : receiver
1342 // -- r2 : name 1272 // -- r2 : name
1343 // -- lr : return address 1273 // -- lr : return address
1344 // -- [sp] : receiver
1345 // ----------------------------------- 1274 // -----------------------------------
1346 Label miss; 1275 Label miss;
1347 1276
1348 // Check that the map of the global has not changed. 1277 // Check that the map of the global has not changed.
1349 __ ldr(r1, MemOperand(sp, 0 * kPointerSize));
1350 __ ldr(r3, FieldMemOperand(r1, HeapObject::kMapOffset)); 1278 __ ldr(r3, FieldMemOperand(r1, HeapObject::kMapOffset));
1351 __ cmp(r3, Operand(Handle<Map>(object->map()))); 1279 __ cmp(r3, Operand(Handle<Map>(object->map())));
1352 __ b(ne, &miss); 1280 __ b(ne, &miss);
1353 1281
1354 // Store the value in the cell. 1282 // Store the value in the cell.
1355 __ mov(r2, Operand(Handle<JSGlobalPropertyCell>(cell))); 1283 __ mov(r2, Operand(Handle<JSGlobalPropertyCell>(cell)));
1356 __ str(r0, FieldMemOperand(r2, JSGlobalPropertyCell::kValueOffset)); 1284 __ str(r0, FieldMemOperand(r2, JSGlobalPropertyCell::kValueOffset));
1357 1285
1358 __ IncrementCounter(&Counters::named_store_global_inline, 1, r1, r3); 1286 __ IncrementCounter(&Counters::named_store_global_inline, 1, r4, r3);
1359 __ Ret(); 1287 __ Ret();
1360 1288
1361 // Handle store cache miss. 1289 // Handle store cache miss.
1362 __ bind(&miss); 1290 __ bind(&miss);
1363 __ IncrementCounter(&Counters::named_store_global_inline_miss, 1, r1, r3); 1291 __ IncrementCounter(&Counters::named_store_global_inline_miss, 1, r4, r3);
1364 Handle<Code> ic(Builtins::builtin(Builtins::StoreIC_Miss)); 1292 Handle<Code> ic(Builtins::builtin(Builtins::StoreIC_Miss));
1365 __ Jump(ic, RelocInfo::CODE_TARGET); 1293 __ Jump(ic, RelocInfo::CODE_TARGET);
1366 1294
1367 // Return the generated code. 1295 // Return the generated code.
1368 return GetCode(NORMAL, name); 1296 return GetCode(NORMAL, name);
1369 } 1297 }
1370 1298
1371 1299
1372 Object* LoadStubCompiler::CompileLoadField(JSObject* object, 1300 Object* LoadStubCompiler::CompileLoadField(JSObject* object,
1373 JSObject* holder, 1301 JSObject* holder,
(...skipping 291 matching lines...) Expand 10 before | Expand all | Expand 10 after
1665 // ----------------------------------- 1593 // -----------------------------------
1666 Label miss; 1594 Label miss;
1667 __ IncrementCounter(&Counters::keyed_load_string_length, 1, r1, r3); 1595 __ IncrementCounter(&Counters::keyed_load_string_length, 1, r1, r3);
1668 1596
1669 __ ldr(r2, MemOperand(sp)); 1597 __ ldr(r2, MemOperand(sp));
1670 __ ldr(r0, MemOperand(sp, kPointerSize)); // receiver 1598 __ ldr(r0, MemOperand(sp, kPointerSize)); // receiver
1671 1599
1672 __ cmp(r2, Operand(Handle<String>(name))); 1600 __ cmp(r2, Operand(Handle<String>(name)));
1673 __ b(ne, &miss); 1601 __ b(ne, &miss);
1674 1602
1675 GenerateLoadStringLength2(masm(), r0, r1, r3, &miss); 1603 GenerateLoadStringLength(masm(), r0, r1, r3, &miss);
1676 __ bind(&miss); 1604 __ bind(&miss);
1677 __ DecrementCounter(&Counters::keyed_load_string_length, 1, r1, r3); 1605 __ DecrementCounter(&Counters::keyed_load_string_length, 1, r1, r3);
1678 1606
1679 GenerateLoadMiss(masm(), Code::KEYED_LOAD_IC); 1607 GenerateLoadMiss(masm(), Code::KEYED_LOAD_IC);
1680 1608
1681 return GetCode(CALLBACKS, name); 1609 return GetCode(CALLBACKS, name);
1682 } 1610 }
1683 1611
1684 1612
1685 // TODO(1224671): implement the fast case. 1613 // TODO(1224671): implement the fast case.
(...skipping 24 matching lines...) Expand all
1710 __ IncrementCounter(&Counters::keyed_store_field, 1, r1, r3); 1638 __ IncrementCounter(&Counters::keyed_store_field, 1, r1, r3);
1711 1639
1712 // Check that the name has not changed. 1640 // Check that the name has not changed.
1713 __ cmp(r2, Operand(Handle<String>(name))); 1641 __ cmp(r2, Operand(Handle<String>(name)));
1714 __ b(ne, &miss); 1642 __ b(ne, &miss);
1715 1643
1716 // Load receiver from the stack. 1644 // Load receiver from the stack.
1717 __ ldr(r3, MemOperand(sp)); 1645 __ ldr(r3, MemOperand(sp));
1718 // r1 is used as scratch register, r3 and r2 might be clobbered. 1646 // r1 is used as scratch register, r3 and r2 might be clobbered.
1719 GenerateStoreField(masm(), 1647 GenerateStoreField(masm(),
1720 Builtins::StoreIC_ExtendStorage,
1721 object, 1648 object,
1722 index, 1649 index,
1723 transition, 1650 transition,
1724 r3, r2, r1, 1651 r3, r2, r1,
1725 &miss); 1652 &miss);
1726 __ bind(&miss); 1653 __ bind(&miss);
1727 1654
1728 __ DecrementCounter(&Counters::keyed_store_field, 1, r1, r3); 1655 __ DecrementCounter(&Counters::keyed_store_field, 1, r1, r3);
1729 __ mov(r2, Operand(Handle<String>(name))); // restore name register. 1656 __ mov(r2, Operand(Handle<String>(name))); // restore name register.
1730 Handle<Code> ic(Builtins::builtin(Builtins::KeyedStoreIC_Miss)); 1657 Handle<Code> ic(Builtins::builtin(Builtins::KeyedStoreIC_Miss));
(...skipping 143 matching lines...) Expand 10 before | Expand all | Expand 10 after
1874 __ Jump(generic_construct_stub, RelocInfo::CODE_TARGET); 1801 __ Jump(generic_construct_stub, RelocInfo::CODE_TARGET);
1875 1802
1876 // Return the generated code. 1803 // Return the generated code.
1877 return GetCode(); 1804 return GetCode();
1878 } 1805 }
1879 1806
1880 1807
1881 #undef __ 1808 #undef __
1882 1809
1883 } } // namespace v8::internal 1810 } } // namespace v8::internal
OLDNEW
« no previous file with comments | « src/arm/macro-assembler-arm.cc ('k') | src/arm/virtual-frame-arm.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698