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

Side by Side Diff: src/x64/full-codegen-x64.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/ia32/full-codegen-ia32.cc ('k') | no next file » | 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 489 matching lines...) Expand 10 before | Expand all | Expand 10 after
500 500
501 MemOperand FullCodeGenerator::EmitSlotSearch(Slot* slot, Register scratch) { 501 MemOperand FullCodeGenerator::EmitSlotSearch(Slot* slot, Register scratch) {
502 switch (slot->type()) { 502 switch (slot->type()) {
503 case Slot::PARAMETER: 503 case Slot::PARAMETER:
504 case Slot::LOCAL: 504 case Slot::LOCAL:
505 return Operand(rbp, SlotOffset(slot)); 505 return Operand(rbp, SlotOffset(slot));
506 case Slot::CONTEXT: { 506 case Slot::CONTEXT: {
507 int context_chain_length = 507 int context_chain_length =
508 scope()->ContextChainLength(slot->var()->scope()); 508 scope()->ContextChainLength(slot->var()->scope());
509 __ LoadContext(scratch, context_chain_length); 509 __ LoadContext(scratch, context_chain_length);
510 return CodeGenerator::ContextOperand(scratch, slot->index()); 510 return ContextOperand(scratch, slot->index());
511 } 511 }
512 case Slot::LOOKUP: 512 case Slot::LOOKUP:
513 UNREACHABLE(); 513 UNREACHABLE();
514 } 514 }
515 UNREACHABLE(); 515 UNREACHABLE();
516 return Operand(rax, 0); 516 return Operand(rax, 0);
517 } 517 }
518 518
519 519
520 void FullCodeGenerator::Move(Register destination, Slot* source) { 520 void FullCodeGenerator::Move(Register destination, Slot* source) {
(...skipping 40 matching lines...) Expand 10 before | Expand all | Expand 10 after
561 break; 561 break;
562 562
563 case Slot::CONTEXT: 563 case Slot::CONTEXT:
564 // We bypass the general EmitSlotSearch because we know more about 564 // We bypass the general EmitSlotSearch because we know more about
565 // this specific context. 565 // this specific context.
566 566
567 // The variable in the decl always resides in the current context. 567 // The variable in the decl always resides in the current context.
568 ASSERT_EQ(0, scope()->ContextChainLength(variable->scope())); 568 ASSERT_EQ(0, scope()->ContextChainLength(variable->scope()));
569 if (FLAG_debug_code) { 569 if (FLAG_debug_code) {
570 // Check if we have the correct context pointer. 570 // Check if we have the correct context pointer.
571 __ movq(rbx, 571 __ movq(rbx, ContextOperand(rsi, Context::FCONTEXT_INDEX));
572 CodeGenerator::ContextOperand(rsi, Context::FCONTEXT_INDEX));
573 __ cmpq(rbx, rsi); 572 __ cmpq(rbx, rsi);
574 __ Check(equal, "Unexpected declaration in current context."); 573 __ Check(equal, "Unexpected declaration in current context.");
575 } 574 }
576 if (mode == Variable::CONST) { 575 if (mode == Variable::CONST) {
577 __ LoadRoot(kScratchRegister, Heap::kTheHoleValueRootIndex); 576 __ LoadRoot(kScratchRegister, Heap::kTheHoleValueRootIndex);
578 __ movq(CodeGenerator::ContextOperand(rsi, slot->index()), 577 __ movq(ContextOperand(rsi, slot->index()), kScratchRegister);
579 kScratchRegister);
580 // No write barrier since the hole value is in old space. 578 // No write barrier since the hole value is in old space.
581 } else if (function != NULL) { 579 } else if (function != NULL) {
582 VisitForValue(function, kAccumulator); 580 VisitForValue(function, kAccumulator);
583 __ movq(CodeGenerator::ContextOperand(rsi, slot->index()), 581 __ movq(ContextOperand(rsi, slot->index()), result_register());
584 result_register());
585 int offset = Context::SlotOffset(slot->index()); 582 int offset = Context::SlotOffset(slot->index());
586 __ movq(rbx, rsi); 583 __ movq(rbx, rsi);
587 __ RecordWrite(rbx, offset, result_register(), rcx); 584 __ RecordWrite(rbx, offset, result_register(), rcx);
588 } 585 }
589 break; 586 break;
590 587
591 case Slot::LOOKUP: { 588 case Slot::LOOKUP: {
592 __ push(rsi); 589 __ push(rsi);
593 __ Push(variable->name()); 590 __ Push(variable->name());
594 // Declaration nodes are always introduced in one of two modes. 591 // Declaration nodes are always introduced in one of two modes.
(...skipping 279 matching lines...) Expand 10 before | Expand all | Expand 10 after
874 Apply(context_, rax); 871 Apply(context_, rax);
875 } 872 }
876 873
877 874
878 void FullCodeGenerator::VisitVariableProxy(VariableProxy* expr) { 875 void FullCodeGenerator::VisitVariableProxy(VariableProxy* expr) {
879 Comment cmnt(masm_, "[ VariableProxy"); 876 Comment cmnt(masm_, "[ VariableProxy");
880 EmitVariableLoad(expr->var(), context_); 877 EmitVariableLoad(expr->var(), context_);
881 } 878 }
882 879
883 880
881 void FullCodeGenerator::EmitLoadGlobalSlotCheckExtensions(
882 Slot* slot,
883 TypeofState typeof_state,
884 Label* slow) {
885 Register context = rsi;
886 Register temp = rdx;
887
888 Scope* s = scope();
889 while (s != NULL) {
890 if (s->num_heap_slots() > 0) {
891 if (s->calls_eval()) {
892 // Check that extension is NULL.
893 __ cmpq(ContextOperand(context, Context::EXTENSION_INDEX),
894 Immediate(0));
895 __ j(not_equal, slow);
896 }
897 // Load next context in chain.
898 __ movq(temp, ContextOperand(context, Context::CLOSURE_INDEX));
899 __ movq(temp, FieldOperand(temp, JSFunction::kContextOffset));
900 // Walk the rest of the chain using a single register without
901 // clobbering rsi.
902 context = temp;
903 }
904 // If no outer scope calls eval, we do not need to check more
905 // context extensions. If we have reached an eval scope, we check
906 // all extensions from this point.
907 if (!s->outer_scope_calls_eval() || s->is_eval_scope()) break;
908 s = s->outer_scope();
909 }
910
911 if (s != NULL && s->is_eval_scope()) {
912 // Loop up the context chain. There is no frame effect so it is
913 // safe to use raw labels here.
914 Label next, fast;
915 if (!context.is(temp)) {
916 __ movq(temp, context);
917 }
918 // Load map for comparison into register, outside loop.
919 __ LoadRoot(kScratchRegister, Heap::kGlobalContextMapRootIndex);
920 __ bind(&next);
921 // Terminate at global context.
922 __ cmpq(kScratchRegister, FieldOperand(temp, HeapObject::kMapOffset));
923 __ j(equal, &fast);
924 // Check that extension is NULL.
925 __ cmpq(ContextOperand(temp, Context::EXTENSION_INDEX), Immediate(0));
926 __ j(not_equal, slow);
927 // Load next context in chain.
928 __ movq(temp, ContextOperand(temp, Context::CLOSURE_INDEX));
929 __ movq(temp, FieldOperand(temp, JSFunction::kContextOffset));
930 __ jmp(&next);
931 __ bind(&fast);
932 }
933
934 // All extension objects were empty and it is safe to use a global
935 // load IC call.
936 __ movq(rax, CodeGenerator::GlobalObject());
937 __ Move(rcx, slot->var()->name());
938 Handle<Code> ic(Builtins::builtin(Builtins::LoadIC_Initialize));
939 RelocInfo::Mode mode = (typeof_state == INSIDE_TYPEOF)
940 ? RelocInfo::CODE_TARGET
941 : RelocInfo::CODE_TARGET_CONTEXT;
942 __ call(ic, mode);
943 }
944
945
884 void FullCodeGenerator::EmitVariableLoad(Variable* var, 946 void FullCodeGenerator::EmitVariableLoad(Variable* var,
885 Expression::Context context) { 947 Expression::Context context) {
886 // Four cases: non-this global variables, lookup slots, all other 948 // Four cases: non-this global variables, lookup slots, all other
887 // types of slots, and parameters that rewrite to explicit property 949 // types of slots, and parameters that rewrite to explicit property
888 // accesses on the arguments object. 950 // accesses on the arguments object.
889 Slot* slot = var->slot(); 951 Slot* slot = var->slot();
890 Property* property = var->AsProperty(); 952 Property* property = var->AsProperty();
891 953
892 if (var->is_global() && !var->is_this()) { 954 if (var->is_global() && !var->is_this()) {
893 Comment cmnt(masm_, "Global variable"); 955 Comment cmnt(masm_, "Global variable");
894 // Use inline caching. Variable name is passed in rcx and the global 956 // Use inline caching. Variable name is passed in rcx and the global
895 // object on the stack. 957 // object on the stack.
896 __ Move(rcx, var->name()); 958 __ Move(rcx, var->name());
897 __ movq(rax, CodeGenerator::GlobalObject()); 959 __ movq(rax, CodeGenerator::GlobalObject());
898 Handle<Code> ic(Builtins::builtin(Builtins::LoadIC_Initialize)); 960 Handle<Code> ic(Builtins::builtin(Builtins::LoadIC_Initialize));
899 __ Call(ic, RelocInfo::CODE_TARGET_CONTEXT); 961 __ Call(ic, RelocInfo::CODE_TARGET_CONTEXT);
900 // A test rax instruction following the call is used by the IC to 962 // A test rax instruction following the call is used by the IC to
901 // indicate that the inobject property case was inlined. Ensure there 963 // indicate that the inobject property case was inlined. Ensure there
902 // is no test rax instruction here. 964 // is no test rax instruction here.
903 __ nop(); 965 __ nop();
904 Apply(context, rax); 966 Apply(context, rax);
905 967
906 } else if (slot != NULL && slot->type() == Slot::LOOKUP) { 968 } else if (slot != NULL && slot->type() == Slot::LOOKUP) {
969 Label done, slow;
970
971 // Generate fast-case code for variables that might be shadowed by
972 // eval-introduced variables. Eval is used a lot without
973 // introducing variables. In those cases, we do not want to
974 // perform a runtime call for all variables in the scope
975 // containing the eval.
976 if (slot->var()->mode() == Variable::DYNAMIC_GLOBAL) {
977 EmitLoadGlobalSlotCheckExtensions(slot, NOT_INSIDE_TYPEOF, &slow);
978 Apply(context, rax);
979 __ jmp(&done);
980 }
981
982 __ bind(&slow);
907 Comment cmnt(masm_, "Lookup slot"); 983 Comment cmnt(masm_, "Lookup slot");
908 __ push(rsi); // Context. 984 __ push(rsi); // Context.
909 __ Push(var->name()); 985 __ Push(var->name());
910 __ CallRuntime(Runtime::kLoadContextSlot, 2); 986 __ CallRuntime(Runtime::kLoadContextSlot, 2);
911 Apply(context, rax); 987 Apply(context, rax);
988 __ bind(&done);
912 989
913 } else if (slot != NULL) { 990 } else if (slot != NULL) {
914 Comment cmnt(masm_, (slot->type() == Slot::CONTEXT) 991 Comment cmnt(masm_, (slot->type() == Slot::CONTEXT)
915 ? "Context slot" 992 ? "Context slot"
916 : "Stack slot"); 993 : "Stack slot");
917 if (var->mode() == Variable::CONST) { 994 if (var->mode() == Variable::CONST) {
918 // Constants may be the hole value if they have not been initialized. 995 // Constants may be the hole value if they have not been initialized.
919 // Unhole them. 996 // Unhole them.
920 Label done; 997 Label done;
921 MemOperand slot_operand = EmitSlotSearch(slot, rax); 998 MemOperand slot_operand = EmitSlotSearch(slot, rax);
(...skipping 1593 matching lines...) Expand 10 before | Expand all | Expand 10 after
2515 __ LoadRoot(rax, Heap::kUndefinedValueRootIndex); 2592 __ LoadRoot(rax, Heap::kUndefinedValueRootIndex);
2516 Apply(context_, rax); 2593 Apply(context_, rax);
2517 return; 2594 return;
2518 } 2595 }
2519 2596
2520 VisitForValue(args->at(1), kAccumulator); 2597 VisitForValue(args->at(1), kAccumulator);
2521 2598
2522 Register key = rax; 2599 Register key = rax;
2523 Register cache = rbx; 2600 Register cache = rbx;
2524 Register tmp = rcx; 2601 Register tmp = rcx;
2525 __ movq(cache, CodeGenerator::ContextOperand(rsi, Context::GLOBAL_INDEX)); 2602 __ movq(cache, ContextOperand(rsi, Context::GLOBAL_INDEX));
2526 __ movq(cache, 2603 __ movq(cache,
2527 FieldOperand(cache, GlobalObject::kGlobalContextOffset)); 2604 FieldOperand(cache, GlobalObject::kGlobalContextOffset));
2528 __ movq(cache, 2605 __ movq(cache,
2529 CodeGenerator::ContextOperand( 2606 ContextOperand(cache, Context::JSFUNCTION_RESULT_CACHES_INDEX));
2530 cache, Context::JSFUNCTION_RESULT_CACHES_INDEX));
2531 __ movq(cache, 2607 __ movq(cache,
2532 FieldOperand(cache, FixedArray::OffsetOfElementAt(cache_id))); 2608 FieldOperand(cache, FixedArray::OffsetOfElementAt(cache_id)));
2533 2609
2534 Label done, not_found; 2610 Label done, not_found;
2535 // tmp now holds finger offset as a smi. 2611 // tmp now holds finger offset as a smi.
2536 ASSERT(kSmiTag == 0 && kSmiTagSize == 1); 2612 ASSERT(kSmiTag == 0 && kSmiTagSize == 1);
2537 __ movq(tmp, FieldOperand(cache, JSFunctionResultCache::kFingerOffset)); 2613 __ movq(tmp, FieldOperand(cache, JSFunctionResultCache::kFingerOffset));
2538 SmiIndex index = 2614 SmiIndex index =
2539 __ SmiToIndex(kScratchRegister, tmp, kPointerSizeLog2); 2615 __ SmiToIndex(kScratchRegister, tmp, kPointerSizeLog2);
2540 __ cmpq(key, FieldOperand(cache, 2616 __ cmpq(key, FieldOperand(cache,
(...skipping 695 matching lines...) Expand 10 before | Expand all | Expand 10 after
3236 Register FullCodeGenerator::context_register() { return rsi; } 3312 Register FullCodeGenerator::context_register() { return rsi; }
3237 3313
3238 3314
3239 void FullCodeGenerator::StoreToFrameField(int frame_offset, Register value) { 3315 void FullCodeGenerator::StoreToFrameField(int frame_offset, Register value) {
3240 ASSERT(IsAligned(frame_offset, kPointerSize)); 3316 ASSERT(IsAligned(frame_offset, kPointerSize));
3241 __ movq(Operand(rbp, frame_offset), value); 3317 __ movq(Operand(rbp, frame_offset), value);
3242 } 3318 }
3243 3319
3244 3320
3245 void FullCodeGenerator::LoadContextField(Register dst, int context_index) { 3321 void FullCodeGenerator::LoadContextField(Register dst, int context_index) {
3246 __ movq(dst, CodeGenerator::ContextOperand(rsi, context_index)); 3322 __ movq(dst, ContextOperand(rsi, context_index));
3247 } 3323 }
3248 3324
3249 3325
3250 // ---------------------------------------------------------------------------- 3326 // ----------------------------------------------------------------------------
3251 // Non-local control flow support. 3327 // Non-local control flow support.
3252 3328
3253 3329
3254 void FullCodeGenerator::EnterFinallyBlock() { 3330 void FullCodeGenerator::EnterFinallyBlock() {
3255 ASSERT(!result_register().is(rdx)); 3331 ASSERT(!result_register().is(rdx));
3256 ASSERT(!result_register().is(rcx)); 3332 ASSERT(!result_register().is(rcx));
(...skipping 23 matching lines...) Expand all
3280 __ ret(0); 3356 __ ret(0);
3281 } 3357 }
3282 3358
3283 3359
3284 #undef __ 3360 #undef __
3285 3361
3286 3362
3287 } } // namespace v8::internal 3363 } } // namespace v8::internal
3288 3364
3289 #endif // V8_TARGET_ARCH_X64 3365 #endif // V8_TARGET_ARCH_X64
OLDNEW
« no previous file with comments | « src/ia32/full-codegen-ia32.cc ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698