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

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

Issue 155344: Re-enable ICs for loads and calls that skips a global object during... (Closed) Base URL: http://v8.googlecode.com/svn/branches/bleeding_edge/
Patch Set: Created 11 years, 5 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
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 255 matching lines...) Expand 10 before | Expand all | Expand 10 after
266 __ mov(dst, FieldOperand(src, offset)); 266 __ mov(dst, FieldOperand(src, offset));
267 } else { 267 } else {
268 // Calculate the offset into the properties array. 268 // Calculate the offset into the properties array.
269 int offset = index * kPointerSize + Array::kHeaderSize; 269 int offset = index * kPointerSize + Array::kHeaderSize;
270 __ mov(dst, FieldOperand(src, JSObject::kPropertiesOffset)); 270 __ mov(dst, FieldOperand(src, JSObject::kPropertiesOffset));
271 __ mov(dst, FieldOperand(dst, offset)); 271 __ mov(dst, FieldOperand(dst, offset));
272 } 272 }
273 } 273 }
274 274
275 275
276 void StubCompiler::GenerateLoadField(MacroAssembler* masm,
277 JSObject* object,
278 JSObject* holder,
279 Register receiver,
280 Register scratch1,
281 Register scratch2,
282 int index,
283 Label* miss_label) {
284 // Check that the receiver isn't a smi.
285 __ test(receiver, Immediate(kSmiTagMask));
286 __ j(zero, miss_label, not_taken);
287
288 // Check that the maps haven't changed.
289 Register reg =
290 masm->CheckMaps(object, receiver, holder, scratch1, scratch2, miss_label);
291
292 // Get the value from the properties.
293 GenerateFastPropertyLoad(masm, eax, reg, holder, index);
294 __ ret(0);
295 }
296
297
298 void StubCompiler::GenerateLoadCallback(MacroAssembler* masm,
299 JSObject* object,
300 JSObject* holder,
301 Register receiver,
302 Register name,
303 Register scratch1,
304 Register scratch2,
305 AccessorInfo* callback,
306 Label* miss_label) {
307 // Check that the receiver isn't a smi.
308 __ test(receiver, Immediate(kSmiTagMask));
309 __ j(zero, miss_label, not_taken);
310
311 // Check that the maps haven't changed.
312 Register reg =
313 masm->CheckMaps(object, receiver, holder, scratch1, scratch2, miss_label);
314
315 // Push the arguments on the JS stack of the caller.
316 __ pop(scratch2); // remove return address
317 __ push(receiver); // receiver
318 __ push(Immediate(Handle<AccessorInfo>(callback))); // callback data
319 __ push(name); // name
320 __ push(reg); // holder
321 __ push(scratch2); // restore return address
322
323 // Do tail-call to the runtime system.
324 ExternalReference load_callback_property =
325 ExternalReference(IC_Utility(IC::kLoadCallbackProperty));
326 __ TailCallRuntime(load_callback_property, 4);
327 }
328
329
330 void StubCompiler::GenerateLoadConstant(MacroAssembler* masm,
331 JSObject* object,
332 JSObject* holder,
333 Register receiver,
334 Register scratch1,
335 Register scratch2,
336 Object* value,
337 Label* miss_label) {
338 // Check that the receiver isn't a smi.
339 __ test(receiver, Immediate(kSmiTagMask));
340 __ j(zero, miss_label, not_taken);
341
342 // Check that the maps haven't changed.
343 Register reg =
344 masm->CheckMaps(object, receiver, holder, scratch1, scratch2, miss_label);
345
346 // Return the constant value.
347 __ mov(eax, Handle<Object>(value));
348 __ ret(0);
349 }
350
351
352 void StubCompiler::GenerateLoadInterceptor(MacroAssembler* masm,
353 JSObject* object,
354 JSObject* holder,
355 Smi* lookup_hint,
356 Register receiver,
357 Register name,
358 Register scratch1,
359 Register scratch2,
360 Label* miss_label) {
361 // Check that the receiver isn't a smi.
362 __ test(receiver, Immediate(kSmiTagMask));
363 __ j(zero, miss_label, not_taken);
364
365 // Check that the maps haven't changed.
366 Register reg =
367 masm->CheckMaps(object, receiver, holder, scratch1, scratch2, miss_label);
368
369 // Push the arguments on the JS stack of the caller.
370 __ pop(scratch2); // remove return address
371 __ push(receiver); // receiver
372 __ push(reg); // holder
373 __ push(name); // name
374 // TODO(367): Maybe don't push lookup_hint for LOOKUP_IN_HOLDER and/or
375 // LOOKUP_IN_PROTOTYPE, but use a special version of lookup method?
376 __ push(Immediate(lookup_hint));
377 __ push(scratch2); // restore return address
378
379 // Do tail-call to the runtime system.
380 ExternalReference load_ic_property =
381 ExternalReference(IC_Utility(IC::kLoadInterceptorProperty));
382 __ TailCallRuntime(load_ic_property, 4);
383 }
384 276
385 277
386 void StubCompiler::GenerateLoadMiss(MacroAssembler* masm, Code::Kind kind) { 278 void StubCompiler::GenerateLoadMiss(MacroAssembler* masm, Code::Kind kind) {
387 ASSERT(kind == Code::LOAD_IC || kind == Code::KEYED_LOAD_IC); 279 ASSERT(kind == Code::LOAD_IC || kind == Code::KEYED_LOAD_IC);
388 Code* code = NULL; 280 Code* code = NULL;
389 if (kind == Code::LOAD_IC) { 281 if (kind == Code::LOAD_IC) {
390 code = Builtins::builtin(Builtins::LoadIC_Miss); 282 code = Builtins::builtin(Builtins::LoadIC_Miss);
391 } else { 283 } else {
392 code = Builtins::builtin(Builtins::KeyedLoadIC_Miss); 284 code = Builtins::builtin(Builtins::KeyedLoadIC_Miss);
393 } 285 }
(...skipping 73 matching lines...) Expand 10 before | Expand all | Expand 10 after
467 __ mov(name_reg, Operand(eax)); 359 __ mov(name_reg, Operand(eax));
468 __ RecordWrite(scratch, offset, name_reg, receiver_reg); 360 __ RecordWrite(scratch, offset, name_reg, receiver_reg);
469 } 361 }
470 362
471 // Return the value (register eax). 363 // Return the value (register eax).
472 __ ret(0); 364 __ ret(0);
473 } 365 }
474 366
475 367
476 #undef __ 368 #undef __
369 #define __ ACCESS_MASM(masm())
477 370
478 #define __ ACCESS_MASM(masm()) 371
372 Register StubCompiler::CheckPrototypes(JSObject* object,
373 Register object_reg,
374 JSObject* holder,
375 Register holder_reg,
376 Register scratch,
377 String* name,
378 Label* miss) {
379 // Check that the maps haven't changed.
380 Register result =
381 masm()->CheckMaps(object, object_reg, holder, holder_reg, scratch, miss);
382
383 // If we've skipped any global objects, it's not enough to verify
384 // that their maps haven't changed.
385 while (object != holder) {
386 if (object->IsGlobalObject()) {
387 GlobalObject* global = GlobalObject::cast(object);
388 Object* probe = global->EnsurePropertyCell(name);
389 if (probe->IsFailure()) {
390 set_failure(Failure::cast(probe));
391 return result;
392 }
393 JSGlobalPropertyCell* cell = JSGlobalPropertyCell::cast(probe);
394 ASSERT(cell->value()->IsTheHole());
395 __ mov(scratch, Immediate(Handle<Object>(cell)));
396 __ cmp(FieldOperand(scratch, JSGlobalPropertyCell::kValueOffset),
397 Immediate(Factory::the_hole_value()));
398 __ j(not_equal, miss, not_taken);
399 }
400 object = JSObject::cast(object->GetPrototype());
401 }
402
403 // Return the register containin the holder.
404 return result;
405 }
406
407
408 void StubCompiler::GenerateLoadField(JSObject* object,
409 JSObject* holder,
410 Register receiver,
411 Register scratch1,
412 Register scratch2,
413 int index,
414 String* name,
415 Label* miss) {
416 // Check that the receiver isn't a smi.
417 __ test(receiver, Immediate(kSmiTagMask));
418 __ j(zero, miss, not_taken);
419
420 // Check the prototype chain.
421 Register reg =
422 CheckPrototypes(object, receiver, holder,
423 scratch1, scratch2, name, miss);
424
425 // Get the value from the properties.
426 GenerateFastPropertyLoad(masm(), eax, reg, holder, index);
427 __ ret(0);
428 }
429
430
431 void StubCompiler::GenerateLoadCallback(JSObject* object,
432 JSObject* holder,
433 Register receiver,
434 Register name_reg,
435 Register scratch1,
436 Register scratch2,
437 AccessorInfo* callback,
438 String* name,
439 Label* miss) {
440 // Check that the receiver isn't a smi.
441 __ test(receiver, Immediate(kSmiTagMask));
442 __ j(zero, miss, not_taken);
443
444 // Check that the maps haven't changed.
445 Register reg =
446 CheckPrototypes(object, receiver, holder,
447 scratch1, scratch2, name, miss);
448
449 // Push the arguments on the JS stack of the caller.
450 __ pop(scratch2); // remove return address
451 __ push(receiver); // receiver
452 __ push(Immediate(Handle<AccessorInfo>(callback))); // callback data
453 __ push(name_reg); // name
454 __ push(reg); // holder
455 __ push(scratch2); // restore return address
456
457 // Do tail-call to the runtime system.
458 ExternalReference load_callback_property =
459 ExternalReference(IC_Utility(IC::kLoadCallbackProperty));
460 __ TailCallRuntime(load_callback_property, 4);
461 }
462
463
464 void StubCompiler::GenerateLoadConstant(JSObject* object,
465 JSObject* holder,
466 Register receiver,
467 Register scratch1,
468 Register scratch2,
469 Object* value,
470 String* name,
471 Label* miss) {
472 // Check that the receiver isn't a smi.
473 __ test(receiver, Immediate(kSmiTagMask));
474 __ j(zero, miss, not_taken);
475
476 // Check that the maps haven't changed.
477 Register reg =
478 CheckPrototypes(object, receiver, holder,
479 scratch1, scratch2, name, miss);
480
481 // Return the constant value.
482 __ mov(eax, Handle<Object>(value));
483 __ ret(0);
484 }
485
486
487 void StubCompiler::GenerateLoadInterceptor(JSObject* object,
488 JSObject* holder,
489 Smi* lookup_hint,
490 Register receiver,
491 Register name_reg,
492 Register scratch1,
493 Register scratch2,
494 String* name,
495 Label* miss) {
496 // Check that the receiver isn't a smi.
497 __ test(receiver, Immediate(kSmiTagMask));
498 __ j(zero, miss, not_taken);
499
500 // Check that the maps haven't changed.
501 Register reg =
502 CheckPrototypes(object, receiver, holder,
503 scratch1, scratch2, name, miss);
504
505 // Push the arguments on the JS stack of the caller.
506 __ pop(scratch2); // remove return address
507 __ push(receiver); // receiver
508 __ push(reg); // holder
509 __ push(name_reg); // name
510 // TODO(367): Maybe don't push lookup_hint for LOOKUP_IN_HOLDER and/or
511 // LOOKUP_IN_PROTOTYPE, but use a special version of lookup method?
512 __ push(Immediate(lookup_hint));
513 __ push(scratch2); // restore return address
514
515 // Do tail-call to the runtime system.
516 ExternalReference load_ic_property =
517 ExternalReference(IC_Utility(IC::kLoadInterceptorProperty));
518 __ TailCallRuntime(load_ic_property, 4);
519 }
479 520
480 521
481 // TODO(1241006): Avoid having lazy compile stubs specialized by the 522 // TODO(1241006): Avoid having lazy compile stubs specialized by the
482 // number of arguments. It is not needed anymore. 523 // number of arguments. It is not needed anymore.
483 Object* StubCompiler::CompileLazyCompile(Code::Flags flags) { 524 Object* StubCompiler::CompileLazyCompile(Code::Flags flags) {
484 // Enter an internal frame. 525 // Enter an internal frame.
485 __ EnterInternalFrame(); 526 __ EnterInternalFrame();
486 527
487 // Push a copy of the function onto the stack. 528 // Push a copy of the function onto the stack.
488 __ push(edi); 529 __ push(edi);
(...skipping 24 matching lines...) Expand all
513 // Get the receiver from the stack. 554 // Get the receiver from the stack.
514 const int argc = arguments().immediate(); 555 const int argc = arguments().immediate();
515 __ mov(edx, Operand(esp, (argc + 1) * kPointerSize)); 556 __ mov(edx, Operand(esp, (argc + 1) * kPointerSize));
516 557
517 // Check that the receiver isn't a smi. 558 // Check that the receiver isn't a smi.
518 __ test(edx, Immediate(kSmiTagMask)); 559 __ test(edx, Immediate(kSmiTagMask));
519 __ j(zero, &miss, not_taken); 560 __ j(zero, &miss, not_taken);
520 561
521 // Do the right check and compute the holder register. 562 // Do the right check and compute the holder register.
522 Register reg = 563 Register reg =
523 masm()->CheckMaps(JSObject::cast(object), edx, holder, ebx, ecx, &miss); 564 CheckPrototypes(JSObject::cast(object), edx, holder,
565 ebx, ecx, name, &miss);
524 566
525 GenerateFastPropertyLoad(masm(), edi, reg, holder, index); 567 GenerateFastPropertyLoad(masm(), edi, reg, holder, index);
526 568
527 // Check that the function really is a function. 569 // Check that the function really is a function.
528 __ test(edi, Immediate(kSmiTagMask)); 570 __ test(edi, Immediate(kSmiTagMask));
529 __ j(zero, &miss, not_taken); 571 __ j(zero, &miss, not_taken);
530 __ CmpObjectType(edi, JS_FUNCTION_TYPE, ebx); 572 __ CmpObjectType(edi, JS_FUNCTION_TYPE, ebx);
531 __ j(not_equal, &miss, not_taken); 573 __ j(not_equal, &miss, not_taken);
532 574
533 // Patch the receiver on the stack with the global proxy if 575 // Patch the receiver on the stack with the global proxy if
(...skipping 12 matching lines...) Expand all
546 __ jmp(ic, RelocInfo::CODE_TARGET); 588 __ jmp(ic, RelocInfo::CODE_TARGET);
547 589
548 // Return the generated code. 590 // Return the generated code.
549 return GetCode(FIELD, name); 591 return GetCode(FIELD, name);
550 } 592 }
551 593
552 594
553 Object* CallStubCompiler::CompileCallConstant(Object* object, 595 Object* CallStubCompiler::CompileCallConstant(Object* object,
554 JSObject* holder, 596 JSObject* holder,
555 JSFunction* function, 597 JSFunction* function,
598 String* name,
556 CheckType check) { 599 CheckType check) {
557 // ----------- S t a t e ------------- 600 // ----------- S t a t e -------------
558 // ----------------------------------- 601 // -----------------------------------
559 Label miss; 602 Label miss;
560 603
561 // Get the receiver from the stack. 604 // Get the receiver from the stack.
562 const int argc = arguments().immediate(); 605 const int argc = arguments().immediate();
563 __ mov(edx, Operand(esp, (argc + 1) * kPointerSize)); 606 __ mov(edx, Operand(esp, (argc + 1) * kPointerSize));
564 607
565 // Check that the receiver isn't a smi. 608 // Check that the receiver isn't a smi.
566 if (check != NUMBER_CHECK) { 609 if (check != NUMBER_CHECK) {
567 __ test(edx, Immediate(kSmiTagMask)); 610 __ test(edx, Immediate(kSmiTagMask));
568 __ j(zero, &miss, not_taken); 611 __ j(zero, &miss, not_taken);
569 } 612 }
570 613
571 // Make sure that it's okay not to patch the on stack receiver 614 // Make sure that it's okay not to patch the on stack receiver
572 // unless we're doing a receiver map check. 615 // unless we're doing a receiver map check.
573 ASSERT(!object->IsGlobalObject() || check == RECEIVER_MAP_CHECK); 616 ASSERT(!object->IsGlobalObject() || check == RECEIVER_MAP_CHECK);
574 617
575 switch (check) { 618 switch (check) {
576 case RECEIVER_MAP_CHECK: 619 case RECEIVER_MAP_CHECK:
577 // Check that the maps haven't changed. 620 // Check that the maps haven't changed.
578 __ CheckMaps(JSObject::cast(object), edx, holder, ebx, ecx, &miss); 621 CheckPrototypes(JSObject::cast(object), edx, holder,
622 ebx, ecx, name, &miss);
579 623
580 // Patch the receiver on the stack with the global proxy if 624 // Patch the receiver on the stack with the global proxy if
581 // necessary. 625 // necessary.
582 if (object->IsGlobalObject()) { 626 if (object->IsGlobalObject()) {
583 __ mov(edx, FieldOperand(edx, GlobalObject::kGlobalReceiverOffset)); 627 __ mov(edx, FieldOperand(edx, GlobalObject::kGlobalReceiverOffset));
584 __ mov(Operand(esp, (argc + 1) * kPointerSize), edx); 628 __ mov(Operand(esp, (argc + 1) * kPointerSize), edx);
585 } 629 }
586 break; 630 break;
587 631
588 case STRING_CHECK: 632 case STRING_CHECK:
589 // Check that the object is a two-byte string or a symbol. 633 // Check that the object is a two-byte string or a symbol.
590 __ mov(ecx, FieldOperand(edx, HeapObject::kMapOffset)); 634 __ mov(ecx, FieldOperand(edx, HeapObject::kMapOffset));
591 __ movzx_b(ecx, FieldOperand(ecx, Map::kInstanceTypeOffset)); 635 __ movzx_b(ecx, FieldOperand(ecx, Map::kInstanceTypeOffset));
592 __ cmp(ecx, FIRST_NONSTRING_TYPE); 636 __ cmp(ecx, FIRST_NONSTRING_TYPE);
593 __ j(above_equal, &miss, not_taken); 637 __ j(above_equal, &miss, not_taken);
594 // Check that the maps starting from the prototype haven't changed. 638 // Check that the maps starting from the prototype haven't changed.
595 GenerateLoadGlobalFunctionPrototype(masm(), 639 GenerateLoadGlobalFunctionPrototype(masm(),
596 Context::STRING_FUNCTION_INDEX, 640 Context::STRING_FUNCTION_INDEX,
597 ecx); 641 ecx);
598 __ CheckMaps(JSObject::cast(object->GetPrototype()), 642 CheckPrototypes(JSObject::cast(object->GetPrototype()), ecx, holder,
599 ecx, holder, ebx, edx, &miss); 643 ebx, edx, name, &miss);
600 break; 644 break;
601 645
602 case NUMBER_CHECK: { 646 case NUMBER_CHECK: {
603 Label fast; 647 Label fast;
604 // Check that the object is a smi or a heap number. 648 // Check that the object is a smi or a heap number.
605 __ test(edx, Immediate(kSmiTagMask)); 649 __ test(edx, Immediate(kSmiTagMask));
606 __ j(zero, &fast, taken); 650 __ j(zero, &fast, taken);
607 __ CmpObjectType(edx, HEAP_NUMBER_TYPE, ecx); 651 __ CmpObjectType(edx, HEAP_NUMBER_TYPE, ecx);
608 __ j(not_equal, &miss, not_taken); 652 __ j(not_equal, &miss, not_taken);
609 __ bind(&fast); 653 __ bind(&fast);
610 // Check that the maps starting from the prototype haven't changed. 654 // Check that the maps starting from the prototype haven't changed.
611 GenerateLoadGlobalFunctionPrototype(masm(), 655 GenerateLoadGlobalFunctionPrototype(masm(),
612 Context::NUMBER_FUNCTION_INDEX, 656 Context::NUMBER_FUNCTION_INDEX,
613 ecx); 657 ecx);
614 __ CheckMaps(JSObject::cast(object->GetPrototype()), 658 CheckPrototypes(JSObject::cast(object->GetPrototype()), ecx, holder,
615 ecx, holder, ebx, edx, &miss); 659 ebx, edx, name, &miss);
616 break; 660 break;
617 } 661 }
618 662
619 case BOOLEAN_CHECK: { 663 case BOOLEAN_CHECK: {
620 Label fast; 664 Label fast;
621 // Check that the object is a boolean. 665 // Check that the object is a boolean.
622 __ cmp(edx, Factory::true_value()); 666 __ cmp(edx, Factory::true_value());
623 __ j(equal, &fast, taken); 667 __ j(equal, &fast, taken);
624 __ cmp(edx, Factory::false_value()); 668 __ cmp(edx, Factory::false_value());
625 __ j(not_equal, &miss, not_taken); 669 __ j(not_equal, &miss, not_taken);
626 __ bind(&fast); 670 __ bind(&fast);
627 // Check that the maps starting from the prototype haven't changed. 671 // Check that the maps starting from the prototype haven't changed.
628 GenerateLoadGlobalFunctionPrototype(masm(), 672 GenerateLoadGlobalFunctionPrototype(masm(),
629 Context::BOOLEAN_FUNCTION_INDEX, 673 Context::BOOLEAN_FUNCTION_INDEX,
630 ecx); 674 ecx);
631 __ CheckMaps(JSObject::cast(object->GetPrototype()), 675 CheckPrototypes(JSObject::cast(object->GetPrototype()), ecx, holder,
632 ecx, holder, ebx, edx, &miss); 676 ebx, edx, name, &miss);
633 break; 677 break;
634 } 678 }
635 679
636 case JSARRAY_HAS_FAST_ELEMENTS_CHECK: 680 case JSARRAY_HAS_FAST_ELEMENTS_CHECK:
637 __ CheckMaps(JSObject::cast(object), edx, holder, ebx, ecx, &miss); 681 CheckPrototypes(JSObject::cast(object), edx, holder,
682 ebx, ecx, name, &miss);
638 // Make sure object->elements()->map() != Heap::dictionary_array_map() 683 // Make sure object->elements()->map() != Heap::dictionary_array_map()
639 // Get the elements array of the object. 684 // Get the elements array of the object.
640 __ mov(ebx, FieldOperand(edx, JSObject::kElementsOffset)); 685 __ mov(ebx, FieldOperand(edx, JSObject::kElementsOffset));
641 // Check that the object is in fast mode (not dictionary). 686 // Check that the object is in fast mode (not dictionary).
642 __ cmp(FieldOperand(ebx, HeapObject::kMapOffset), 687 __ cmp(FieldOperand(ebx, HeapObject::kMapOffset),
643 Immediate(Factory::hash_table_map())); 688 Immediate(Factory::hash_table_map()));
644 __ j(equal, &miss, not_taken); 689 __ j(equal, &miss, not_taken);
645 break; 690 break;
646 691
647 default: 692 default:
(...skipping 37 matching lines...) Expand 10 before | Expand all | Expand 10 after
685 730
686 // Get the receiver from the stack. 731 // Get the receiver from the stack.
687 __ mov(edx, Operand(esp, (argc + 1) * kPointerSize)); 732 __ mov(edx, Operand(esp, (argc + 1) * kPointerSize));
688 733
689 // Check that the receiver isn't a smi. 734 // Check that the receiver isn't a smi.
690 __ test(edx, Immediate(kSmiTagMask)); 735 __ test(edx, Immediate(kSmiTagMask));
691 __ j(zero, &miss, not_taken); 736 __ j(zero, &miss, not_taken);
692 737
693 // Check that maps have not changed and compute the holder register. 738 // Check that maps have not changed and compute the holder register.
694 Register reg = 739 Register reg =
695 masm()->CheckMaps(JSObject::cast(object), edx, holder, ebx, ecx, &miss); 740 CheckPrototypes(JSObject::cast(object), edx, holder,
741 ebx, ecx, name, &miss);
696 742
697 // Enter an internal frame. 743 // Enter an internal frame.
698 __ EnterInternalFrame(); 744 __ EnterInternalFrame();
699 745
700 // Push arguments on the expression stack. 746 // Push arguments on the expression stack.
701 __ push(edx); // receiver 747 __ push(edx); // receiver
702 __ push(reg); // holder 748 __ push(reg); // holder
703 __ push(Operand(ebp, (argc + 3) * kPointerSize)); // name 749 __ push(Operand(ebp, (argc + 3) * kPointerSize)); // name
704 __ push(Immediate(holder->InterceptorPropertyLookupHint(name))); 750 __ push(Immediate(holder->InterceptorPropertyLookupHint(name)));
705 751
(...skipping 58 matching lines...) Expand 10 before | Expand all | Expand 10 after
764 810
765 // If the object is the holder then we know that it's a global 811 // If the object is the holder then we know that it's a global
766 // object which can only happen for contextual calls. In this case, 812 // object which can only happen for contextual calls. In this case,
767 // the receiver cannot be a smi. 813 // the receiver cannot be a smi.
768 if (object != holder) { 814 if (object != holder) {
769 __ test(edx, Immediate(kSmiTagMask)); 815 __ test(edx, Immediate(kSmiTagMask));
770 __ j(zero, &miss, not_taken); 816 __ j(zero, &miss, not_taken);
771 } 817 }
772 818
773 // Check that the maps haven't changed. 819 // Check that the maps haven't changed.
774 masm()->CheckMaps(object, edx, holder, ebx, ecx, &miss); 820 CheckPrototypes(object, edx, holder, ebx, ecx, name, &miss);
775 821
776 // Get the value from the cell. 822 // Get the value from the cell.
777 __ mov(edi, Immediate(Handle<JSGlobalPropertyCell>(cell))); 823 __ mov(edi, Immediate(Handle<JSGlobalPropertyCell>(cell)));
778 __ mov(edi, FieldOperand(edi, JSGlobalPropertyCell::kValueOffset)); 824 __ mov(edi, FieldOperand(edi, JSGlobalPropertyCell::kValueOffset));
779 825
780 // Check that the cell contains the same function. 826 // Check that the cell contains the same function.
781 __ cmp(Operand(edi), Immediate(Handle<JSFunction>(function))); 827 __ cmp(Operand(edi), Immediate(Handle<JSFunction>(function)));
782 __ j(not_equal, &miss, not_taken); 828 __ j(not_equal, &miss, not_taken);
783 829
784 // Patch the receiver on the stack with the global proxy. 830 // Patch the receiver on the stack with the global proxy.
(...skipping 241 matching lines...) Expand 10 before | Expand all | Expand 10 after
1026 __ bind(&miss); 1072 __ bind(&miss);
1027 __ DecrementCounter(&Counters::keyed_store_field, 1); 1073 __ DecrementCounter(&Counters::keyed_store_field, 1);
1028 Handle<Code> ic(Builtins::builtin(Builtins::KeyedStoreIC_Miss)); 1074 Handle<Code> ic(Builtins::builtin(Builtins::KeyedStoreIC_Miss));
1029 __ jmp(ic, RelocInfo::CODE_TARGET); 1075 __ jmp(ic, RelocInfo::CODE_TARGET);
1030 1076
1031 // Return the generated code. 1077 // Return the generated code.
1032 return GetCode(transition == NULL ? FIELD : MAP_TRANSITION, name); 1078 return GetCode(transition == NULL ? FIELD : MAP_TRANSITION, name);
1033 } 1079 }
1034 1080
1035 1081
1082
1036 Object* LoadStubCompiler::CompileLoadField(JSObject* object, 1083 Object* LoadStubCompiler::CompileLoadField(JSObject* object,
1037 JSObject* holder, 1084 JSObject* holder,
1038 int index, 1085 int index,
1039 String* name) { 1086 String* name) {
1040 // ----------- S t a t e ------------- 1087 // ----------- S t a t e -------------
1041 // -- ecx : name 1088 // -- ecx : name
1042 // -- esp[0] : return address 1089 // -- esp[0] : return address
1043 // -- esp[4] : receiver 1090 // -- esp[4] : receiver
1044 // ----------------------------------- 1091 // -----------------------------------
1045 Label miss; 1092 Label miss;
1046 1093
1047 __ mov(eax, (Operand(esp, kPointerSize))); 1094 __ mov(eax, (Operand(esp, kPointerSize)));
1048 GenerateLoadField(masm(), object, holder, eax, ebx, edx, index, &miss); 1095 GenerateLoadField(object, holder, eax, ebx, edx, index, name, &miss);
1049 __ bind(&miss); 1096 __ bind(&miss);
1050 GenerateLoadMiss(masm(), Code::LOAD_IC); 1097 GenerateLoadMiss(masm(), Code::LOAD_IC);
1051 1098
1052 // Return the generated code. 1099 // Return the generated code.
1053 return GetCode(FIELD, name); 1100 return GetCode(FIELD, name);
1054 } 1101 }
1055 1102
1056 1103
1057 Object* LoadStubCompiler::CompileLoadCallback(JSObject* object, 1104 Object* LoadStubCompiler::CompileLoadCallback(JSObject* object,
1058 JSObject* holder, 1105 JSObject* holder,
1059 AccessorInfo* callback, 1106 AccessorInfo* callback,
1060 String* name) { 1107 String* name) {
1061 // ----------- S t a t e ------------- 1108 // ----------- S t a t e -------------
1062 // -- ecx : name 1109 // -- ecx : name
1063 // -- esp[0] : return address 1110 // -- esp[0] : return address
1064 // -- esp[4] : receiver 1111 // -- esp[4] : receiver
1065 // ----------------------------------- 1112 // -----------------------------------
1066 Label miss; 1113 Label miss;
1067 1114
1068 __ mov(eax, (Operand(esp, kPointerSize))); 1115 __ mov(eax, (Operand(esp, kPointerSize)));
1069 GenerateLoadCallback(masm(), object, holder, eax, ecx, ebx, 1116 GenerateLoadCallback(object, holder, eax, ecx, ebx, edx,
1070 edx, callback, &miss); 1117 callback, name, &miss);
1071 __ bind(&miss); 1118 __ bind(&miss);
1072 GenerateLoadMiss(masm(), Code::LOAD_IC); 1119 GenerateLoadMiss(masm(), Code::LOAD_IC);
1073 1120
1074 // Return the generated code. 1121 // Return the generated code.
1075 return GetCode(CALLBACKS, name); 1122 return GetCode(CALLBACKS, name);
1076 } 1123 }
1077 1124
1078 1125
1079 Object* LoadStubCompiler::CompileLoadConstant(JSObject* object, 1126 Object* LoadStubCompiler::CompileLoadConstant(JSObject* object,
1080 JSObject* holder, 1127 JSObject* holder,
1081 Object* value, 1128 Object* value,
1082 String* name) { 1129 String* name) {
1083 // ----------- S t a t e ------------- 1130 // ----------- S t a t e -------------
1084 // -- ecx : name 1131 // -- ecx : name
1085 // -- esp[0] : return address 1132 // -- esp[0] : return address
1086 // -- esp[4] : receiver 1133 // -- esp[4] : receiver
1087 // ----------------------------------- 1134 // -----------------------------------
1088 Label miss; 1135 Label miss;
1089 1136
1090 __ mov(eax, (Operand(esp, kPointerSize))); 1137 __ mov(eax, (Operand(esp, kPointerSize)));
1091 GenerateLoadConstant(masm(), object, holder, eax, ebx, edx, value, &miss); 1138 GenerateLoadConstant(object, holder, eax, ebx, edx, value, name, &miss);
1092 __ bind(&miss); 1139 __ bind(&miss);
1093 GenerateLoadMiss(masm(), Code::LOAD_IC); 1140 GenerateLoadMiss(masm(), Code::LOAD_IC);
1094 1141
1095 // Return the generated code. 1142 // Return the generated code.
1096 return GetCode(CONSTANT_FUNCTION, name); 1143 return GetCode(CONSTANT_FUNCTION, name);
1097 } 1144 }
1098 1145
1099 1146
1100 Object* LoadStubCompiler::CompileLoadInterceptor(JSObject* receiver, 1147 Object* LoadStubCompiler::CompileLoadInterceptor(JSObject* receiver,
1101 JSObject* holder, 1148 JSObject* holder,
1102 String* name) { 1149 String* name) {
1103 // ----------- S t a t e ------------- 1150 // ----------- S t a t e -------------
1104 // -- ecx : name 1151 // -- ecx : name
1105 // -- esp[0] : return address 1152 // -- esp[0] : return address
1106 // -- esp[4] : receiver 1153 // -- esp[4] : receiver
1107 // ----------------------------------- 1154 // -----------------------------------
1108 Label miss; 1155 Label miss;
1109 1156
1110 __ mov(eax, (Operand(esp, kPointerSize))); 1157 __ mov(eax, (Operand(esp, kPointerSize)));
1111 // TODO(368): Compile in the whole chain: all the interceptors in 1158 // TODO(368): Compile in the whole chain: all the interceptors in
1112 // prototypes and ultimate answer. 1159 // prototypes and ultimate answer.
1113 GenerateLoadInterceptor(masm(), 1160 GenerateLoadInterceptor(receiver,
1114 receiver,
1115 holder, 1161 holder,
1116 holder->InterceptorPropertyLookupHint(name), 1162 holder->InterceptorPropertyLookupHint(name),
1117 eax, 1163 eax,
1118 ecx, 1164 ecx,
1119 edx, 1165 edx,
1120 ebx, 1166 ebx,
1167 name,
1121 &miss); 1168 &miss);
1122 1169
1123 __ bind(&miss); 1170 __ bind(&miss);
1124 GenerateLoadMiss(masm(), Code::LOAD_IC); 1171 GenerateLoadMiss(masm(), Code::LOAD_IC);
1125 1172
1126 // Return the generated code. 1173 // Return the generated code.
1127 return GetCode(INTERCEPTOR, name); 1174 return GetCode(INTERCEPTOR, name);
1128 } 1175 }
1129 1176
1130 1177
(...skipping 16 matching lines...) Expand all
1147 1194
1148 // If the object is the holder then we know that it's a global 1195 // If the object is the holder then we know that it's a global
1149 // object which can only happen for contextual loads. In this case, 1196 // object which can only happen for contextual loads. In this case,
1150 // the receiver cannot be a smi. 1197 // the receiver cannot be a smi.
1151 if (object != holder) { 1198 if (object != holder) {
1152 __ test(eax, Immediate(kSmiTagMask)); 1199 __ test(eax, Immediate(kSmiTagMask));
1153 __ j(zero, &miss, not_taken); 1200 __ j(zero, &miss, not_taken);
1154 } 1201 }
1155 1202
1156 // Check that the maps haven't changed. 1203 // Check that the maps haven't changed.
1157 masm()->CheckMaps(object, eax, holder, ebx, edx, &miss); 1204 CheckPrototypes(object, eax, holder, ebx, edx, name, &miss);
1158 1205
1159 // Get the value from the cell. 1206 // Get the value from the cell.
1160 __ mov(eax, Immediate(Handle<JSGlobalPropertyCell>(cell))); 1207 __ mov(eax, Immediate(Handle<JSGlobalPropertyCell>(cell)));
1161 __ mov(eax, FieldOperand(eax, JSGlobalPropertyCell::kValueOffset)); 1208 __ mov(eax, FieldOperand(eax, JSGlobalPropertyCell::kValueOffset));
1162 1209
1163 // Check for deleted property if property can actually be deleted. 1210 // Check for deleted property if property can actually be deleted.
1164 if (!is_dont_delete) { 1211 if (!is_dont_delete) {
1165 __ cmp(eax, Factory::the_hole_value()); 1212 __ cmp(eax, Factory::the_hole_value());
1166 __ j(equal, &miss, not_taken); 1213 __ j(equal, &miss, not_taken);
1167 } else if (FLAG_debug_code) { 1214 } else if (FLAG_debug_code) {
(...skipping 25 matching lines...) Expand all
1193 Label miss; 1240 Label miss;
1194 1241
1195 __ mov(eax, (Operand(esp, kPointerSize))); 1242 __ mov(eax, (Operand(esp, kPointerSize)));
1196 __ mov(ecx, (Operand(esp, 2 * kPointerSize))); 1243 __ mov(ecx, (Operand(esp, 2 * kPointerSize)));
1197 __ IncrementCounter(&Counters::keyed_load_field, 1); 1244 __ IncrementCounter(&Counters::keyed_load_field, 1);
1198 1245
1199 // Check that the name has not changed. 1246 // Check that the name has not changed.
1200 __ cmp(Operand(eax), Immediate(Handle<String>(name))); 1247 __ cmp(Operand(eax), Immediate(Handle<String>(name)));
1201 __ j(not_equal, &miss, not_taken); 1248 __ j(not_equal, &miss, not_taken);
1202 1249
1203 GenerateLoadField(masm(), receiver, holder, ecx, ebx, edx, index, &miss); 1250 GenerateLoadField(receiver, holder, ecx, ebx, edx, index, name, &miss);
1251
1204 __ bind(&miss); 1252 __ bind(&miss);
1205 __ DecrementCounter(&Counters::keyed_load_field, 1); 1253 __ DecrementCounter(&Counters::keyed_load_field, 1);
1206 GenerateLoadMiss(masm(), Code::KEYED_LOAD_IC); 1254 GenerateLoadMiss(masm(), Code::KEYED_LOAD_IC);
1207 1255
1208 // Return the generated code. 1256 // Return the generated code.
1209 return GetCode(FIELD, name); 1257 return GetCode(FIELD, name);
1210 } 1258 }
1211 1259
1212 1260
1213 Object* KeyedLoadStubCompiler::CompileLoadCallback(String* name, 1261 Object* KeyedLoadStubCompiler::CompileLoadCallback(String* name,
1214 JSObject* receiver, 1262 JSObject* receiver,
1215 JSObject* holder, 1263 JSObject* holder,
1216 AccessorInfo* callback) { 1264 AccessorInfo* callback) {
1217 // ----------- S t a t e ------------- 1265 // ----------- S t a t e -------------
1218 // -- esp[0] : return address 1266 // -- esp[0] : return address
1219 // -- esp[4] : name 1267 // -- esp[4] : name
1220 // -- esp[8] : receiver 1268 // -- esp[8] : receiver
1221 // ----------------------------------- 1269 // -----------------------------------
1222 Label miss; 1270 Label miss;
1223 1271
1224 __ mov(eax, (Operand(esp, kPointerSize))); 1272 __ mov(eax, (Operand(esp, kPointerSize)));
1225 __ mov(ecx, (Operand(esp, 2 * kPointerSize))); 1273 __ mov(ecx, (Operand(esp, 2 * kPointerSize)));
1226 __ IncrementCounter(&Counters::keyed_load_callback, 1); 1274 __ IncrementCounter(&Counters::keyed_load_callback, 1);
1227 1275
1228 // Check that the name has not changed. 1276 // Check that the name has not changed.
1229 __ cmp(Operand(eax), Immediate(Handle<String>(name))); 1277 __ cmp(Operand(eax), Immediate(Handle<String>(name)));
1230 __ j(not_equal, &miss, not_taken); 1278 __ j(not_equal, &miss, not_taken);
1231 1279
1232 GenerateLoadCallback(masm(), receiver, holder, ecx, eax, ebx, edx, 1280 GenerateLoadCallback(receiver, holder, ecx, eax, ebx, edx,
1233 callback, &miss); 1281 callback, name, &miss);
1234 __ bind(&miss); 1282 __ bind(&miss);
1235 __ DecrementCounter(&Counters::keyed_load_callback, 1); 1283 __ DecrementCounter(&Counters::keyed_load_callback, 1);
1236 GenerateLoadMiss(masm(), Code::KEYED_LOAD_IC); 1284 GenerateLoadMiss(masm(), Code::KEYED_LOAD_IC);
1237 1285
1238 // Return the generated code. 1286 // Return the generated code.
1239 return GetCode(CALLBACKS, name); 1287 return GetCode(CALLBACKS, name);
1240 } 1288 }
1241 1289
1242 1290
1243 Object* KeyedLoadStubCompiler::CompileLoadConstant(String* name, 1291 Object* KeyedLoadStubCompiler::CompileLoadConstant(String* name,
1244 JSObject* receiver, 1292 JSObject* receiver,
1245 JSObject* holder, 1293 JSObject* holder,
1246 Object* value) { 1294 Object* value) {
1247 // ----------- S t a t e ------------- 1295 // ----------- S t a t e -------------
1248 // -- esp[0] : return address 1296 // -- esp[0] : return address
1249 // -- esp[4] : name 1297 // -- esp[4] : name
1250 // -- esp[8] : receiver 1298 // -- esp[8] : receiver
1251 // ----------------------------------- 1299 // -----------------------------------
1252 Label miss; 1300 Label miss;
1253 1301
1254 __ mov(eax, (Operand(esp, kPointerSize))); 1302 __ mov(eax, (Operand(esp, kPointerSize)));
1255 __ mov(ecx, (Operand(esp, 2 * kPointerSize))); 1303 __ mov(ecx, (Operand(esp, 2 * kPointerSize)));
1256 __ IncrementCounter(&Counters::keyed_load_constant_function, 1); 1304 __ IncrementCounter(&Counters::keyed_load_constant_function, 1);
1257 1305
1258 // Check that the name has not changed. 1306 // Check that the name has not changed.
1259 __ cmp(Operand(eax), Immediate(Handle<String>(name))); 1307 __ cmp(Operand(eax), Immediate(Handle<String>(name)));
1260 __ j(not_equal, &miss, not_taken); 1308 __ j(not_equal, &miss, not_taken);
1261 1309
1262 GenerateLoadConstant(masm(), receiver, holder, ecx, ebx, edx, value, &miss); 1310 GenerateLoadConstant(receiver, holder, ecx, ebx, edx,
1311 value, name, &miss);
1263 __ bind(&miss); 1312 __ bind(&miss);
1264 __ DecrementCounter(&Counters::keyed_load_constant_function, 1); 1313 __ DecrementCounter(&Counters::keyed_load_constant_function, 1);
1265 GenerateLoadMiss(masm(), Code::KEYED_LOAD_IC); 1314 GenerateLoadMiss(masm(), Code::KEYED_LOAD_IC);
1266 1315
1267 // Return the generated code. 1316 // Return the generated code.
1268 return GetCode(CONSTANT_FUNCTION, name); 1317 return GetCode(CONSTANT_FUNCTION, name);
1269 } 1318 }
1270 1319
1271 1320
1272 Object* KeyedLoadStubCompiler::CompileLoadInterceptor(JSObject* receiver, 1321 Object* KeyedLoadStubCompiler::CompileLoadInterceptor(JSObject* receiver,
1273 JSObject* holder, 1322 JSObject* holder,
1274 String* name) { 1323 String* name) {
1275 // ----------- S t a t e ------------- 1324 // ----------- S t a t e -------------
1276 // -- esp[0] : return address 1325 // -- esp[0] : return address
1277 // -- esp[4] : name 1326 // -- esp[4] : name
1278 // -- esp[8] : receiver 1327 // -- esp[8] : receiver
1279 // ----------------------------------- 1328 // -----------------------------------
1280 Label miss; 1329 Label miss;
1281 1330
1282 __ mov(eax, (Operand(esp, kPointerSize))); 1331 __ mov(eax, (Operand(esp, kPointerSize)));
1283 __ mov(ecx, (Operand(esp, 2 * kPointerSize))); 1332 __ mov(ecx, (Operand(esp, 2 * kPointerSize)));
1284 __ IncrementCounter(&Counters::keyed_load_interceptor, 1); 1333 __ IncrementCounter(&Counters::keyed_load_interceptor, 1);
1285 1334
1286 // Check that the name has not changed. 1335 // Check that the name has not changed.
1287 __ cmp(Operand(eax), Immediate(Handle<String>(name))); 1336 __ cmp(Operand(eax), Immediate(Handle<String>(name)));
1288 __ j(not_equal, &miss, not_taken); 1337 __ j(not_equal, &miss, not_taken);
1289 1338
1290 GenerateLoadInterceptor(masm(), 1339 GenerateLoadInterceptor(receiver,
1291 receiver,
1292 holder, 1340 holder,
1293 Smi::FromInt(JSObject::kLookupInHolder), 1341 Smi::FromInt(JSObject::kLookupInHolder),
1294 ecx, 1342 ecx,
1295 eax, 1343 eax,
1296 edx, 1344 edx,
1297 ebx, 1345 ebx,
1346 name,
1298 &miss); 1347 &miss);
1299 __ bind(&miss); 1348 __ bind(&miss);
1300 __ DecrementCounter(&Counters::keyed_load_interceptor, 1); 1349 __ DecrementCounter(&Counters::keyed_load_interceptor, 1);
1301 GenerateLoadMiss(masm(), Code::KEYED_LOAD_IC); 1350 GenerateLoadMiss(masm(), Code::KEYED_LOAD_IC);
1302 1351
1303 // Return the generated code. 1352 // Return the generated code.
1304 return GetCode(INTERCEPTOR, name); 1353 return GetCode(INTERCEPTOR, name);
1305 } 1354 }
1306 1355
1307 1356
(...skipping 73 matching lines...) Expand 10 before | Expand all | Expand 10 after
1381 GenerateLoadMiss(masm(), Code::KEYED_LOAD_IC); 1430 GenerateLoadMiss(masm(), Code::KEYED_LOAD_IC);
1382 1431
1383 // Return the generated code. 1432 // Return the generated code.
1384 return GetCode(CALLBACKS, name); 1433 return GetCode(CALLBACKS, name);
1385 } 1434 }
1386 1435
1387 1436
1388 #undef __ 1437 #undef __
1389 1438
1390 } } // namespace v8::internal 1439 } } // namespace v8::internal
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698