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

Side by Side Diff: src/arm/full-codegen-arm.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 | « no previous file | src/full-codegen.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 2009 the V8 project authors. All rights reserved. 1 // Copyright 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 475 matching lines...) Expand 10 before | Expand all | Expand 10 after
486 486
487 MemOperand FullCodeGenerator::EmitSlotSearch(Slot* slot, Register scratch) { 487 MemOperand FullCodeGenerator::EmitSlotSearch(Slot* slot, Register scratch) {
488 switch (slot->type()) { 488 switch (slot->type()) {
489 case Slot::PARAMETER: 489 case Slot::PARAMETER:
490 case Slot::LOCAL: 490 case Slot::LOCAL:
491 return MemOperand(fp, SlotOffset(slot)); 491 return MemOperand(fp, SlotOffset(slot));
492 case Slot::CONTEXT: { 492 case Slot::CONTEXT: {
493 int context_chain_length = 493 int context_chain_length =
494 scope()->ContextChainLength(slot->var()->scope()); 494 scope()->ContextChainLength(slot->var()->scope());
495 __ LoadContext(scratch, context_chain_length); 495 __ LoadContext(scratch, context_chain_length);
496 return CodeGenerator::ContextOperand(scratch, slot->index()); 496 return ContextOperand(scratch, slot->index());
497 } 497 }
498 case Slot::LOOKUP: 498 case Slot::LOOKUP:
499 UNREACHABLE(); 499 UNREACHABLE();
500 } 500 }
501 UNREACHABLE(); 501 UNREACHABLE();
502 return MemOperand(r0, 0); 502 return MemOperand(r0, 0);
503 } 503 }
504 504
505 505
506 void FullCodeGenerator::Move(Register destination, Slot* source) { 506 void FullCodeGenerator::Move(Register destination, Slot* source) {
(...skipping 43 matching lines...) Expand 10 before | Expand all | Expand 10 after
550 break; 550 break;
551 551
552 case Slot::CONTEXT: 552 case Slot::CONTEXT:
553 // We bypass the general EmitSlotSearch because we know more about 553 // We bypass the general EmitSlotSearch because we know more about
554 // this specific context. 554 // this specific context.
555 555
556 // The variable in the decl always resides in the current context. 556 // The variable in the decl always resides in the current context.
557 ASSERT_EQ(0, scope()->ContextChainLength(variable->scope())); 557 ASSERT_EQ(0, scope()->ContextChainLength(variable->scope()));
558 if (FLAG_debug_code) { 558 if (FLAG_debug_code) {
559 // Check if we have the correct context pointer. 559 // Check if we have the correct context pointer.
560 __ ldr(r1, 560 __ ldr(r1, ContextOperand(cp, Context::FCONTEXT_INDEX));
561 CodeGenerator::ContextOperand(cp, Context::FCONTEXT_INDEX));
562 __ cmp(r1, cp); 561 __ cmp(r1, cp);
563 __ Check(eq, "Unexpected declaration in current context."); 562 __ Check(eq, "Unexpected declaration in current context.");
564 } 563 }
565 if (mode == Variable::CONST) { 564 if (mode == Variable::CONST) {
566 __ LoadRoot(ip, Heap::kTheHoleValueRootIndex); 565 __ LoadRoot(ip, Heap::kTheHoleValueRootIndex);
567 __ str(ip, CodeGenerator::ContextOperand(cp, slot->index())); 566 __ str(ip, ContextOperand(cp, slot->index()));
568 // No write barrier since the_hole_value is in old space. 567 // No write barrier since the_hole_value is in old space.
569 } else if (function != NULL) { 568 } else if (function != NULL) {
570 VisitForValue(function, kAccumulator); 569 VisitForValue(function, kAccumulator);
571 __ str(result_register(), 570 __ str(result_register(), ContextOperand(cp, slot->index()));
572 CodeGenerator::ContextOperand(cp, slot->index()));
573 int offset = Context::SlotOffset(slot->index()); 571 int offset = Context::SlotOffset(slot->index());
574 // We know that we have written a function, which is not a smi. 572 // We know that we have written a function, which is not a smi.
575 __ mov(r1, Operand(cp)); 573 __ mov(r1, Operand(cp));
576 __ RecordWrite(r1, Operand(offset), r2, result_register()); 574 __ RecordWrite(r1, Operand(offset), r2, result_register());
577 } 575 }
578 break; 576 break;
579 577
580 case Slot::LOOKUP: { 578 case Slot::LOOKUP: {
581 __ mov(r2, Operand(variable->name())); 579 __ mov(r2, Operand(variable->name()));
582 // Declaration nodes are always introduced in one of two modes. 580 // Declaration nodes are always introduced in one of two modes.
(...skipping 291 matching lines...) Expand 10 before | Expand all | Expand 10 after
874 Apply(context_, r0); 872 Apply(context_, r0);
875 } 873 }
876 874
877 875
878 void FullCodeGenerator::VisitVariableProxy(VariableProxy* expr) { 876 void FullCodeGenerator::VisitVariableProxy(VariableProxy* expr) {
879 Comment cmnt(masm_, "[ VariableProxy"); 877 Comment cmnt(masm_, "[ VariableProxy");
880 EmitVariableLoad(expr->var(), context_); 878 EmitVariableLoad(expr->var(), context_);
881 } 879 }
882 880
883 881
882 void FullCodeGenerator::EmitLoadGlobalSlotCheckExtensions(
883 Slot* slot,
884 TypeofState typeof_state,
885 Label* slow) {
886 Register current = cp;
887 Register next = r1;
888 Register temp = r2;
889
890 Scope* s = scope();
891 while (s != NULL) {
892 if (s->num_heap_slots() > 0) {
893 if (s->calls_eval()) {
894 // Check that extension is NULL.
895 __ ldr(temp, ContextOperand(current, Context::EXTENSION_INDEX));
896 __ tst(temp, temp);
897 __ b(ne, slow);
898 }
899 // Load next context in chain.
900 __ ldr(next, ContextOperand(current, Context::CLOSURE_INDEX));
901 __ ldr(next, FieldMemOperand(next, JSFunction::kContextOffset));
902 // Walk the rest of the chain using a single register without
903 // clobbering cp.
904 current = next;
905 }
906 // If no outer scope calls eval, we do not need to check more
907 // context extensions.
908 if (!s->outer_scope_calls_eval() || s->is_eval_scope()) break;
909 s = s->outer_scope();
910 }
911
912 if (s->is_eval_scope()) {
913 Label loop, fast;
914 if (!current.is(next)) {
915 __ Move(next, current);
916 }
917 __ bind(&loop);
918 // Terminate at global context.
919 __ ldr(temp, FieldMemOperand(next, HeapObject::kMapOffset));
920 __ LoadRoot(ip, Heap::kGlobalContextMapRootIndex);
921 __ cmp(temp, ip);
922 __ b(eq, &fast);
923 // Check that extension is NULL.
924 __ ldr(temp, ContextOperand(next, Context::EXTENSION_INDEX));
925 __ tst(temp, temp);
926 __ b(ne, slow);
927 // Load next context in chain.
928 __ ldr(next, ContextOperand(next, Context::CLOSURE_INDEX));
929 __ ldr(next, FieldMemOperand(next, JSFunction::kContextOffset));
930 __ b(&loop);
931 __ bind(&fast);
932 }
933
934 __ ldr(r0, CodeGenerator::GlobalObject());
935 __ mov(r2, Operand(slot->var()->name()));
936 RelocInfo::Mode mode = (typeof_state == INSIDE_TYPEOF)
937 ? RelocInfo::CODE_TARGET
938 : RelocInfo::CODE_TARGET_CONTEXT;
939 Handle<Code> ic(Builtins::builtin(Builtins::LoadIC_Initialize));
940 __ Call(ic, mode);
941 }
942
943
884 void FullCodeGenerator::EmitVariableLoad(Variable* var, 944 void FullCodeGenerator::EmitVariableLoad(Variable* var,
885 Expression::Context context) { 945 Expression::Context context) {
886 // Four cases: non-this global variables, lookup slots, all other 946 // Four cases: non-this global variables, lookup slots, all other
887 // types of slots, and parameters that rewrite to explicit property 947 // types of slots, and parameters that rewrite to explicit property
888 // accesses on the arguments object. 948 // accesses on the arguments object.
889 Slot* slot = var->slot(); 949 Slot* slot = var->slot();
890 Property* property = var->AsProperty(); 950 Property* property = var->AsProperty();
891 951
892 if (var->is_global() && !var->is_this()) { 952 if (var->is_global() && !var->is_this()) {
893 Comment cmnt(masm_, "Global variable"); 953 Comment cmnt(masm_, "Global variable");
894 // Use inline caching. Variable name is passed in r2 and the global 954 // Use inline caching. Variable name is passed in r2 and the global
895 // object (receiver) in r0. 955 // object (receiver) in r0.
896 __ ldr(r0, CodeGenerator::GlobalObject()); 956 __ ldr(r0, CodeGenerator::GlobalObject());
897 __ mov(r2, Operand(var->name())); 957 __ mov(r2, Operand(var->name()));
898 Handle<Code> ic(Builtins::builtin(Builtins::LoadIC_Initialize)); 958 Handle<Code> ic(Builtins::builtin(Builtins::LoadIC_Initialize));
899 __ Call(ic, RelocInfo::CODE_TARGET_CONTEXT); 959 __ Call(ic, RelocInfo::CODE_TARGET_CONTEXT);
900 Apply(context, r0); 960 Apply(context, r0);
901 961
902 } else if (slot != NULL && slot->type() == Slot::LOOKUP) { 962 } else if (slot != NULL && slot->type() == Slot::LOOKUP) {
963 Label done, slow;
964
965 // Generate fast-case code for variables that might be shadowed by
966 // eval-introduced variables. Eval is used a lot without
967 // introducing variables. In those cases, we do not want to
968 // perform a runtime call for all variables in the scope
969 // containing the eval.
970 if (slot->var()->mode() == Variable::DYNAMIC_GLOBAL) {
971 EmitLoadGlobalSlotCheckExtensions(slot, NOT_INSIDE_TYPEOF, &slow);
972 Apply(context, r0);
973 __ jmp(&done);
974 }
975
976 __ bind(&slow);
903 Comment cmnt(masm_, "Lookup slot"); 977 Comment cmnt(masm_, "Lookup slot");
904 __ mov(r1, Operand(var->name())); 978 __ mov(r1, Operand(var->name()));
905 __ Push(cp, r1); // Context and name. 979 __ Push(cp, r1); // Context and name.
906 __ CallRuntime(Runtime::kLoadContextSlot, 2); 980 __ CallRuntime(Runtime::kLoadContextSlot, 2);
907 Apply(context, r0); 981 Apply(context, r0);
982 __ bind(&done);
908 983
909 } else if (slot != NULL) { 984 } else if (slot != NULL) {
910 Comment cmnt(masm_, (slot->type() == Slot::CONTEXT) 985 Comment cmnt(masm_, (slot->type() == Slot::CONTEXT)
911 ? "Context slot" 986 ? "Context slot"
912 : "Stack slot"); 987 : "Stack slot");
913 if (var->mode() == Variable::CONST) { 988 if (var->mode() == Variable::CONST) {
914 // Constants may be the hole value if they have not been initialized. 989 // Constants may be the hole value if they have not been initialized.
915 // Unhole them. 990 // Unhole them.
916 Label done; 991 Label done;
917 MemOperand slot_operand = EmitSlotSearch(slot, r0); 992 MemOperand slot_operand = EmitSlotSearch(slot, r0);
(...skipping 1539 matching lines...) Expand 10 before | Expand all | Expand 10 after
2457 __ Abort("Attempt to use undefined cache."); 2532 __ Abort("Attempt to use undefined cache.");
2458 __ LoadRoot(r0, Heap::kUndefinedValueRootIndex); 2533 __ LoadRoot(r0, Heap::kUndefinedValueRootIndex);
2459 Apply(context_, r0); 2534 Apply(context_, r0);
2460 return; 2535 return;
2461 } 2536 }
2462 2537
2463 VisitForValue(args->at(1), kAccumulator); 2538 VisitForValue(args->at(1), kAccumulator);
2464 2539
2465 Register key = r0; 2540 Register key = r0;
2466 Register cache = r1; 2541 Register cache = r1;
2467 __ ldr(cache, CodeGenerator::ContextOperand(cp, Context::GLOBAL_INDEX)); 2542 __ ldr(cache, ContextOperand(cp, Context::GLOBAL_INDEX));
2468 __ ldr(cache, FieldMemOperand(cache, GlobalObject::kGlobalContextOffset)); 2543 __ ldr(cache, FieldMemOperand(cache, GlobalObject::kGlobalContextOffset));
2469 __ ldr(cache, 2544 __ ldr(cache, ContextOperand(cache, Context::JSFUNCTION_RESULT_CACHES_INDEX));
2470 CodeGenerator::ContextOperand(
2471 cache, Context::JSFUNCTION_RESULT_CACHES_INDEX));
2472 __ ldr(cache, 2545 __ ldr(cache,
2473 FieldMemOperand(cache, FixedArray::OffsetOfElementAt(cache_id))); 2546 FieldMemOperand(cache, FixedArray::OffsetOfElementAt(cache_id)));
2474 2547
2475 2548
2476 Label done, not_found; 2549 Label done, not_found;
2477 // tmp now holds finger offset as a smi. 2550 // tmp now holds finger offset as a smi.
2478 ASSERT(kSmiTag == 0 && kSmiTagSize == 1); 2551 ASSERT(kSmiTag == 0 && kSmiTagSize == 1);
2479 __ ldr(r2, FieldMemOperand(cache, JSFunctionResultCache::kFingerOffset)); 2552 __ ldr(r2, FieldMemOperand(cache, JSFunctionResultCache::kFingerOffset));
2480 // r2 now holds finger offset as a smi. 2553 // r2 now holds finger offset as a smi.
2481 __ add(r3, cache, Operand(FixedArray::kHeaderSize - kHeapObjectTag)); 2554 __ add(r3, cache, Operand(FixedArray::kHeaderSize - kHeapObjectTag));
(...skipping 698 matching lines...) Expand 10 before | Expand all | Expand 10 after
3180 Register FullCodeGenerator::context_register() { return cp; } 3253 Register FullCodeGenerator::context_register() { return cp; }
3181 3254
3182 3255
3183 void FullCodeGenerator::StoreToFrameField(int frame_offset, Register value) { 3256 void FullCodeGenerator::StoreToFrameField(int frame_offset, Register value) {
3184 ASSERT_EQ(POINTER_SIZE_ALIGN(frame_offset), frame_offset); 3257 ASSERT_EQ(POINTER_SIZE_ALIGN(frame_offset), frame_offset);
3185 __ str(value, MemOperand(fp, frame_offset)); 3258 __ str(value, MemOperand(fp, frame_offset));
3186 } 3259 }
3187 3260
3188 3261
3189 void FullCodeGenerator::LoadContextField(Register dst, int context_index) { 3262 void FullCodeGenerator::LoadContextField(Register dst, int context_index) {
3190 __ ldr(dst, CodeGenerator::ContextOperand(cp, context_index)); 3263 __ ldr(dst, ContextOperand(cp, context_index));
3191 } 3264 }
3192 3265
3193 3266
3194 // ---------------------------------------------------------------------------- 3267 // ----------------------------------------------------------------------------
3195 // Non-local control flow support. 3268 // Non-local control flow support.
3196 3269
3197 void FullCodeGenerator::EnterFinallyBlock() { 3270 void FullCodeGenerator::EnterFinallyBlock() {
3198 ASSERT(!result_register().is(r1)); 3271 ASSERT(!result_register().is(r1));
3199 // Store result register while executing finally block. 3272 // Store result register while executing finally block.
3200 __ push(result_register()); 3273 __ push(result_register());
(...skipping 16 matching lines...) Expand all
3217 __ mov(r1, Operand(r1, ASR, 1)); // Un-smi-tag value. 3290 __ mov(r1, Operand(r1, ASR, 1)); // Un-smi-tag value.
3218 __ add(pc, r1, Operand(masm_->CodeObject())); 3291 __ add(pc, r1, Operand(masm_->CodeObject()));
3219 } 3292 }
3220 3293
3221 3294
3222 #undef __ 3295 #undef __
3223 3296
3224 } } // namespace v8::internal 3297 } } // namespace v8::internal
3225 3298
3226 #endif // V8_TARGET_ARCH_ARM 3299 #endif // V8_TARGET_ARCH_ARM
OLDNEW
« no previous file with comments | « no previous file | src/full-codegen.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698