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

Side by Side Diff: src/ia32/full-codegen-ia32.cc

Issue 3295022: Handle global variables potentially shadowed by eval-introduced... (Closed) Base URL: http://v8.googlecode.com/svn/branches/bleeding_edge/
Patch Set: '' Created 10 years, 3 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/full-codegen.cc ('k') | src/x64/full-codegen-x64.cc » ('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 2010 the V8 project authors. All rights reserved. 1 // Copyright 2010 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 496 matching lines...) Expand 10 before | Expand all | Expand 10 after
507 507
508 MemOperand FullCodeGenerator::EmitSlotSearch(Slot* slot, Register scratch) { 508 MemOperand FullCodeGenerator::EmitSlotSearch(Slot* slot, Register scratch) {
509 switch (slot->type()) { 509 switch (slot->type()) {
510 case Slot::PARAMETER: 510 case Slot::PARAMETER:
511 case Slot::LOCAL: 511 case Slot::LOCAL:
512 return Operand(ebp, SlotOffset(slot)); 512 return Operand(ebp, SlotOffset(slot));
513 case Slot::CONTEXT: { 513 case Slot::CONTEXT: {
514 int context_chain_length = 514 int context_chain_length =
515 scope()->ContextChainLength(slot->var()->scope()); 515 scope()->ContextChainLength(slot->var()->scope());
516 __ LoadContext(scratch, context_chain_length); 516 __ LoadContext(scratch, context_chain_length);
517 return CodeGenerator::ContextOperand(scratch, slot->index()); 517 return ContextOperand(scratch, slot->index());
518 } 518 }
519 case Slot::LOOKUP: 519 case Slot::LOOKUP:
520 UNREACHABLE(); 520 UNREACHABLE();
521 } 521 }
522 UNREACHABLE(); 522 UNREACHABLE();
523 return Operand(eax, 0); 523 return Operand(eax, 0);
524 } 524 }
525 525
526 526
527 void FullCodeGenerator::Move(Register destination, Slot* source) { 527 void FullCodeGenerator::Move(Register destination, Slot* source) {
(...skipping 39 matching lines...) Expand 10 before | Expand all | Expand 10 after
567 break; 567 break;
568 568
569 case Slot::CONTEXT: 569 case Slot::CONTEXT:
570 // We bypass the general EmitSlotSearch because we know more about 570 // We bypass the general EmitSlotSearch because we know more about
571 // this specific context. 571 // this specific context.
572 572
573 // The variable in the decl always resides in the current context. 573 // The variable in the decl always resides in the current context.
574 ASSERT_EQ(0, scope()->ContextChainLength(variable->scope())); 574 ASSERT_EQ(0, scope()->ContextChainLength(variable->scope()));
575 if (FLAG_debug_code) { 575 if (FLAG_debug_code) {
576 // Check if we have the correct context pointer. 576 // Check if we have the correct context pointer.
577 __ mov(ebx, 577 __ mov(ebx, ContextOperand(esi, Context::FCONTEXT_INDEX));
578 CodeGenerator::ContextOperand(esi, Context::FCONTEXT_INDEX));
579 __ cmp(ebx, Operand(esi)); 578 __ cmp(ebx, Operand(esi));
580 __ Check(equal, "Unexpected declaration in current context."); 579 __ Check(equal, "Unexpected declaration in current context.");
581 } 580 }
582 if (mode == Variable::CONST) { 581 if (mode == Variable::CONST) {
583 __ mov(CodeGenerator::ContextOperand(esi, slot->index()), 582 __ mov(ContextOperand(esi, slot->index()),
584 Immediate(Factory::the_hole_value())); 583 Immediate(Factory::the_hole_value()));
585 // No write barrier since the hole value is in old space. 584 // No write barrier since the hole value is in old space.
586 } else if (function != NULL) { 585 } else if (function != NULL) {
587 VisitForValue(function, kAccumulator); 586 VisitForValue(function, kAccumulator);
588 __ mov(CodeGenerator::ContextOperand(esi, slot->index()), 587 __ mov(ContextOperand(esi, slot->index()), result_register());
589 result_register());
590 int offset = Context::SlotOffset(slot->index()); 588 int offset = Context::SlotOffset(slot->index());
591 __ mov(ebx, esi); 589 __ mov(ebx, esi);
592 __ RecordWrite(ebx, offset, result_register(), ecx); 590 __ RecordWrite(ebx, offset, result_register(), ecx);
593 } 591 }
594 break; 592 break;
595 593
596 case Slot::LOOKUP: { 594 case Slot::LOOKUP: {
597 __ push(esi); 595 __ push(esi);
598 __ push(Immediate(variable->name())); 596 __ push(Immediate(variable->name()));
599 // Declaration nodes are always introduced in one of two modes. 597 // Declaration nodes are always introduced in one of two modes.
(...skipping 278 matching lines...) Expand 10 before | Expand all | Expand 10 after
878 Apply(context_, eax); 876 Apply(context_, eax);
879 } 877 }
880 878
881 879
882 void FullCodeGenerator::VisitVariableProxy(VariableProxy* expr) { 880 void FullCodeGenerator::VisitVariableProxy(VariableProxy* expr) {
883 Comment cmnt(masm_, "[ VariableProxy"); 881 Comment cmnt(masm_, "[ VariableProxy");
884 EmitVariableLoad(expr->var(), context_); 882 EmitVariableLoad(expr->var(), context_);
885 } 883 }
886 884
887 885
886 void FullCodeGenerator::EmitLoadGlobalSlotCheckExtensions(
887 Slot* slot,
888 TypeofState typeof_state,
889 Label* slow) {
890 Register context = esi;
891 Register temp = edx;
892
893 Scope* s = scope();
894 while (s != NULL) {
895 if (s->num_heap_slots() > 0) {
896 if (s->calls_eval()) {
897 // Check that extension is NULL.
898 __ cmp(ContextOperand(context, Context::EXTENSION_INDEX),
899 Immediate(0));
900 __ j(not_equal, slow);
901 }
902 // Load next context in chain.
903 __ mov(temp, ContextOperand(context, Context::CLOSURE_INDEX));
904 __ mov(temp, FieldOperand(temp, JSFunction::kContextOffset));
905 // Walk the rest of the chain using a single register without
906 // clobbering esi.
907 context = temp;
908 }
909 // If no outer scope calls eval, we do not need to check more
910 // context extensions. If we have reached an eval scope, we check
911 // all extensions from this point.
912 if (!s->outer_scope_calls_eval() || s->is_eval_scope()) break;
913 s = s->outer_scope();
914 }
915
916 if (s != NULL && s->is_eval_scope()) {
917 // Loop up the context chain. There is no frame effect so it is
918 // safe to use raw labels here.
919 Label next, fast;
920 if (!context.is(temp)) {
921 __ mov(temp, context);
922 }
923 __ bind(&next);
924 // Terminate at global context.
925 __ cmp(FieldOperand(temp, HeapObject::kMapOffset),
926 Immediate(Factory::global_context_map()));
927 __ j(equal, &fast);
928 // Check that extension is NULL.
929 __ cmp(ContextOperand(temp, Context::EXTENSION_INDEX), Immediate(0));
930 __ j(not_equal, slow);
931 // Load next context in chain.
932 __ mov(temp, ContextOperand(temp, Context::CLOSURE_INDEX));
933 __ mov(temp, FieldOperand(temp, JSFunction::kContextOffset));
934 __ jmp(&next);
935 __ bind(&fast);
936 }
937
938 // All extension objects were empty and it is safe to use a global
939 // load IC call.
940 __ mov(eax, CodeGenerator::GlobalObject());
941 __ mov(ecx, slot->var()->name());
942 Handle<Code> ic(Builtins::builtin(Builtins::LoadIC_Initialize));
943 RelocInfo::Mode mode = (typeof_state == INSIDE_TYPEOF)
944 ? RelocInfo::CODE_TARGET
945 : RelocInfo::CODE_TARGET_CONTEXT;
946 __ call(ic, mode);
947 }
948
949
888 void FullCodeGenerator::EmitVariableLoad(Variable* var, 950 void FullCodeGenerator::EmitVariableLoad(Variable* var,
889 Expression::Context context) { 951 Expression::Context context) {
890 // Four cases: non-this global variables, lookup slots, all other 952 // Four cases: non-this global variables, lookup slots, all other
891 // types of slots, and parameters that rewrite to explicit property 953 // types of slots, and parameters that rewrite to explicit property
892 // accesses on the arguments object. 954 // accesses on the arguments object.
893 Slot* slot = var->slot(); 955 Slot* slot = var->slot();
894 Property* property = var->AsProperty(); 956 Property* property = var->AsProperty();
895 957
896 if (var->is_global() && !var->is_this()) { 958 if (var->is_global() && !var->is_this()) {
897 Comment cmnt(masm_, "Global variable"); 959 Comment cmnt(masm_, "Global variable");
898 // Use inline caching. Variable name is passed in ecx and the global 960 // Use inline caching. Variable name is passed in ecx and the global
899 // object on the stack. 961 // object on the stack.
900 __ mov(eax, CodeGenerator::GlobalObject()); 962 __ mov(eax, CodeGenerator::GlobalObject());
901 __ mov(ecx, var->name()); 963 __ mov(ecx, var->name());
902 Handle<Code> ic(Builtins::builtin(Builtins::LoadIC_Initialize)); 964 Handle<Code> ic(Builtins::builtin(Builtins::LoadIC_Initialize));
903 __ call(ic, RelocInfo::CODE_TARGET_CONTEXT); 965 __ call(ic, RelocInfo::CODE_TARGET_CONTEXT);
904 // By emitting a nop we make sure that we do not have a test eax 966 // By emitting a nop we make sure that we do not have a test eax
905 // instruction after the call it is treated specially by the LoadIC code 967 // instruction after the call it is treated specially by the LoadIC code
906 // Remember that the assembler may choose to do peephole optimization 968 // Remember that the assembler may choose to do peephole optimization
907 // (eg, push/pop elimination). 969 // (eg, push/pop elimination).
908 __ nop(); 970 __ nop();
909 Apply(context, eax); 971 Apply(context, eax);
910 972
911 } else if (slot != NULL && slot->type() == Slot::LOOKUP) { 973 } else if (slot != NULL && slot->type() == Slot::LOOKUP) {
974 Label done, slow;
975
976 // Generate fast-case code for variables that might be shadowed by
977 // eval-introduced variables. Eval is used a lot without
978 // introducing variables. In those cases, we do not want to
979 // perform a runtime call for all variables in the scope
980 // containing the eval.
981 if (slot->var()->mode() == Variable::DYNAMIC_GLOBAL) {
982 EmitLoadGlobalSlotCheckExtensions(slot, NOT_INSIDE_TYPEOF, &slow);
983 Apply(context, eax);
984 __ jmp(&done);
985 }
986
987 __ bind(&slow);
912 Comment cmnt(masm_, "Lookup slot"); 988 Comment cmnt(masm_, "Lookup slot");
913 __ push(esi); // Context. 989 __ push(esi); // Context.
914 __ push(Immediate(var->name())); 990 __ push(Immediate(var->name()));
915 __ CallRuntime(Runtime::kLoadContextSlot, 2); 991 __ CallRuntime(Runtime::kLoadContextSlot, 2);
916 Apply(context, eax); 992 Apply(context, eax);
993 __ bind(&done);
917 994
918 } else if (slot != NULL) { 995 } else if (slot != NULL) {
919 Comment cmnt(masm_, (slot->type() == Slot::CONTEXT) 996 Comment cmnt(masm_, (slot->type() == Slot::CONTEXT)
920 ? "Context slot" 997 ? "Context slot"
921 : "Stack slot"); 998 : "Stack slot");
922 if (var->mode() == Variable::CONST) { 999 if (var->mode() == Variable::CONST) {
923 // Constants may be the hole value if they have not been initialized. 1000 // Constants may be the hole value if they have not been initialized.
924 // Unhole them. 1001 // Unhole them.
925 Label done; 1002 Label done;
926 MemOperand slot_operand = EmitSlotSearch(slot, eax); 1003 MemOperand slot_operand = EmitSlotSearch(slot, eax);
(...skipping 1847 matching lines...) Expand 10 before | Expand all | Expand 10 after
2774 __ mov(eax, Factory::undefined_value()); 2851 __ mov(eax, Factory::undefined_value());
2775 Apply(context_, eax); 2852 Apply(context_, eax);
2776 return; 2853 return;
2777 } 2854 }
2778 2855
2779 VisitForValue(args->at(1), kAccumulator); 2856 VisitForValue(args->at(1), kAccumulator);
2780 2857
2781 Register key = eax; 2858 Register key = eax;
2782 Register cache = ebx; 2859 Register cache = ebx;
2783 Register tmp = ecx; 2860 Register tmp = ecx;
2784 __ mov(cache, CodeGenerator::ContextOperand(esi, Context::GLOBAL_INDEX)); 2861 __ mov(cache, ContextOperand(esi, Context::GLOBAL_INDEX));
2785 __ mov(cache, 2862 __ mov(cache,
2786 FieldOperand(cache, GlobalObject::kGlobalContextOffset)); 2863 FieldOperand(cache, GlobalObject::kGlobalContextOffset));
2787 __ mov(cache, 2864 __ mov(cache, ContextOperand(cache, Context::JSFUNCTION_RESULT_CACHES_INDEX));
2788 CodeGenerator::ContextOperand(
2789 cache, Context::JSFUNCTION_RESULT_CACHES_INDEX));
2790 __ mov(cache, 2865 __ mov(cache,
2791 FieldOperand(cache, FixedArray::OffsetOfElementAt(cache_id))); 2866 FieldOperand(cache, FixedArray::OffsetOfElementAt(cache_id)));
2792 2867
2793 Label done, not_found; 2868 Label done, not_found;
2794 // tmp now holds finger offset as a smi. 2869 // tmp now holds finger offset as a smi.
2795 ASSERT(kSmiTag == 0 && kSmiTagSize == 1); 2870 ASSERT(kSmiTag == 0 && kSmiTagSize == 1);
2796 __ mov(tmp, FieldOperand(cache, JSFunctionResultCache::kFingerOffset)); 2871 __ mov(tmp, FieldOperand(cache, JSFunctionResultCache::kFingerOffset));
2797 __ cmp(key, CodeGenerator::FixedArrayElementOperand(cache, tmp)); 2872 __ cmp(key, CodeGenerator::FixedArrayElementOperand(cache, tmp));
2798 __ j(not_equal, &not_found); 2873 __ j(not_equal, &not_found);
2799 2874
(...skipping 705 matching lines...) Expand 10 before | Expand all | Expand 10 after
3505 Register FullCodeGenerator::context_register() { return esi; } 3580 Register FullCodeGenerator::context_register() { return esi; }
3506 3581
3507 3582
3508 void FullCodeGenerator::StoreToFrameField(int frame_offset, Register value) { 3583 void FullCodeGenerator::StoreToFrameField(int frame_offset, Register value) {
3509 ASSERT_EQ(POINTER_SIZE_ALIGN(frame_offset), frame_offset); 3584 ASSERT_EQ(POINTER_SIZE_ALIGN(frame_offset), frame_offset);
3510 __ mov(Operand(ebp, frame_offset), value); 3585 __ mov(Operand(ebp, frame_offset), value);
3511 } 3586 }
3512 3587
3513 3588
3514 void FullCodeGenerator::LoadContextField(Register dst, int context_index) { 3589 void FullCodeGenerator::LoadContextField(Register dst, int context_index) {
3515 __ mov(dst, CodeGenerator::ContextOperand(esi, context_index)); 3590 __ mov(dst, ContextOperand(esi, context_index));
3516 } 3591 }
3517 3592
3518 3593
3519 // ---------------------------------------------------------------------------- 3594 // ----------------------------------------------------------------------------
3520 // Non-local control flow support. 3595 // Non-local control flow support.
3521 3596
3522 void FullCodeGenerator::EnterFinallyBlock() { 3597 void FullCodeGenerator::EnterFinallyBlock() {
3523 // Cook return address on top of stack (smi encoded Code* delta) 3598 // Cook return address on top of stack (smi encoded Code* delta)
3524 ASSERT(!result_register().is(edx)); 3599 ASSERT(!result_register().is(edx));
3525 __ mov(edx, Operand(esp, 0)); 3600 __ mov(edx, Operand(esp, 0));
(...skipping 19 matching lines...) Expand all
3545 // And return. 3620 // And return.
3546 __ ret(0); 3621 __ ret(0);
3547 } 3622 }
3548 3623
3549 3624
3550 #undef __ 3625 #undef __
3551 3626
3552 } } // namespace v8::internal 3627 } } // namespace v8::internal
3553 3628
3554 #endif // V8_TARGET_ARCH_IA32 3629 #endif // V8_TARGET_ARCH_IA32
OLDNEW
« no previous file with comments | « src/full-codegen.cc ('k') | src/x64/full-codegen-x64.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698