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

Side by Side Diff: src/codegen-arm.cc

Issue 20453: ARM side of load optimization in the presence of eval. (Closed) Base URL: http://v8.googlecode.com/svn/branches/bleeding_edge/
Patch Set: Created 11 years, 10 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/codegen-arm.h ('k') | src/codegen-ia32.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 2006-2008 the V8 project authors. All rights reserved. 1 // Copyright 2006-2008 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 351 matching lines...) Expand 10 before | Expand all | Expand 10 after
362 return frame_->Parameter(index); 362 return frame_->Parameter(index);
363 363
364 case Slot::LOCAL: 364 case Slot::LOCAL:
365 return frame_->Local(index); 365 return frame_->Local(index);
366 366
367 case Slot::CONTEXT: { 367 case Slot::CONTEXT: {
368 // Follow the context chain if necessary. 368 // Follow the context chain if necessary.
369 ASSERT(!tmp.is(cp)); // do not overwrite context register 369 ASSERT(!tmp.is(cp)); // do not overwrite context register
370 Register context = cp; 370 Register context = cp;
371 int chain_length = scope()->ContextChainLength(slot->var()->scope()); 371 int chain_length = scope()->ContextChainLength(slot->var()->scope());
372 for (int i = chain_length; i-- > 0;) { 372 for (int i = 0; i < chain_length; i++) {
373 // Load the closure. 373 // Load the closure.
374 // (All contexts, even 'with' contexts, have a closure, 374 // (All contexts, even 'with' contexts, have a closure,
375 // and it is the same for all contexts inside a function. 375 // and it is the same for all contexts inside a function.
376 // There is no need to go to the function context first.) 376 // There is no need to go to the function context first.)
377 __ ldr(tmp, ContextOperand(context, Context::CLOSURE_INDEX)); 377 __ ldr(tmp, ContextOperand(context, Context::CLOSURE_INDEX));
378 // Load the function context (which is the incoming, outer context). 378 // Load the function context (which is the incoming, outer context).
379 __ ldr(tmp, FieldMemOperand(tmp, JSFunction::kContextOffset)); 379 __ ldr(tmp, FieldMemOperand(tmp, JSFunction::kContextOffset));
380 context = tmp; 380 context = tmp;
381 } 381 }
382 // We may have a 'with' context now. Get the function context. 382 // We may have a 'with' context now. Get the function context.
383 // (In fact this mov may never be the needed, since the scope analysis 383 // (In fact this mov may never be the needed, since the scope analysis
384 // may not permit a direct context access in this case and thus we are 384 // may not permit a direct context access in this case and thus we are
385 // always at a function context. However it is safe to dereference be- 385 // always at a function context. However it is safe to dereference be-
386 // cause the function context of a function context is itself. Before 386 // cause the function context of a function context is itself. Before
387 // deleting this mov we should try to create a counter-example first, 387 // deleting this mov we should try to create a counter-example first,
388 // though...) 388 // though...)
389 __ ldr(tmp, ContextOperand(context, Context::FCONTEXT_INDEX)); 389 __ ldr(tmp, ContextOperand(context, Context::FCONTEXT_INDEX));
390 return ContextOperand(tmp, index); 390 return ContextOperand(tmp, index);
391 } 391 }
392 392
393 default: 393 default:
394 UNREACHABLE(); 394 UNREACHABLE();
395 return MemOperand(r0, 0); 395 return MemOperand(r0, 0);
396 } 396 }
397 } 397 }
398 398
399 399
400 MemOperand CodeGenerator::ContextSlotOperandCheckExtensions(Slot* slot,
401 Register tmp,
402 Register tmp2,
403 Label* slow) {
404 ASSERT(slot->type() == Slot::CONTEXT);
405 int index = slot->index();
406 Register context = cp;
407 for (Scope* s = scope(); s != slot->var()->scope(); s = s->outer_scope()) {
408 if (s->num_heap_slots() > 0) {
409 if (s->calls_eval()) {
410 // Check that extension is NULL.
411 __ ldr(tmp2, ContextOperand(context, Context::EXTENSION_INDEX));
412 __ tst(tmp2, tmp2);
413 __ b(ne, slow);
414 }
415 __ ldr(tmp, ContextOperand(context, Context::CLOSURE_INDEX));
416 __ ldr(tmp, FieldMemOperand(tmp, JSFunction::kContextOffset));
417 context = tmp;
418 }
419 }
420 // Check that last extension is NULL.
421 __ ldr(tmp2, ContextOperand(tmp, Context::EXTENSION_INDEX));
422 __ tst(tmp2, tmp2);
423 __ b(ne, slow);
424 __ ldr(tmp, ContextOperand(tmp, Context::FCONTEXT_INDEX));
425 return ContextOperand(tmp, index);
426 }
427
428
400 // Loads a value on TOS. If it is a boolean value, the result may have been 429 // Loads a value on TOS. If it is a boolean value, the result may have been
401 // (partially) translated into branches, or it may have set the condition 430 // (partially) translated into branches, or it may have set the condition
402 // code register. If force_cc is set, the value is forced to set the 431 // code register. If force_cc is set, the value is forced to set the
403 // condition code register and no value is pushed. If the condition code 432 // condition code register and no value is pushed. If the condition code
404 // register was set, has_cc() is true and cc_reg_ contains the condition to 433 // register was set, has_cc() is true and cc_reg_ contains the condition to
405 // test for 'true'. 434 // test for 'true'.
406 void CodeGenerator::LoadCondition(Expression* x, 435 void CodeGenerator::LoadCondition(Expression* x,
407 TypeofState typeof_state, 436 TypeofState typeof_state,
408 Label* true_target, 437 Label* true_target,
409 Label* false_target, 438 Label* false_target,
(...skipping 1568 matching lines...) Expand 10 before | Expand all | Expand 10 after
1978 __ bind(&else_); 2007 __ bind(&else_);
1979 Load(node->else_expression(), typeof_state()); 2008 Load(node->else_expression(), typeof_state());
1980 __ bind(&exit); 2009 __ bind(&exit);
1981 } 2010 }
1982 2011
1983 2012
1984 void CodeGenerator::LoadFromSlot(Slot* slot, TypeofState typeof_state) { 2013 void CodeGenerator::LoadFromSlot(Slot* slot, TypeofState typeof_state) {
1985 if (slot->type() == Slot::LOOKUP) { 2014 if (slot->type() == Slot::LOOKUP) {
1986 ASSERT(slot->var()->is_dynamic()); 2015 ASSERT(slot->var()->is_dynamic());
1987 2016
1988 // For now, just do a runtime call. 2017 Label slow, done;
2018
2019 // Generate fast-case code for variables that might be shadowed by
2020 // eval-introduced variables. Eval is used a lot without
2021 // introducing variables. In those cases, we do not want to
2022 // perform a runtime call for all variables in the scope
2023 // containing the eval.
2024 if (slot->var()->mode() == Variable::DYNAMIC_GLOBAL) {
2025 LoadFromGlobalSlotCheckExtensions(slot, typeof_state, r1, r2, &slow);
2026 __ b(&done);
2027
2028 } else if (slot->var()->mode() == Variable::DYNAMIC_LOCAL) {
2029 Slot* potential_slot = slot->var()->local_if_not_shadowed()->slot();
2030 __ ldr(r0,
2031 ContextSlotOperandCheckExtensions(potential_slot,
2032 r1,
2033 r2,
2034 &slow));
2035 __ b(&done);
2036 }
2037
2038 __ bind(&slow);
1989 frame_->Push(cp); 2039 frame_->Push(cp);
1990 __ mov(r0, Operand(slot->var()->name())); 2040 __ mov(r0, Operand(slot->var()->name()));
1991 frame_->Push(r0); 2041 frame_->Push(r0);
1992 2042
1993 if (typeof_state == INSIDE_TYPEOF) { 2043 if (typeof_state == INSIDE_TYPEOF) {
1994 __ CallRuntime(Runtime::kLoadContextSlotNoReferenceError, 2); 2044 __ CallRuntime(Runtime::kLoadContextSlotNoReferenceError, 2);
1995 } else { 2045 } else {
1996 __ CallRuntime(Runtime::kLoadContextSlot, 2); 2046 __ CallRuntime(Runtime::kLoadContextSlot, 2);
1997 } 2047 }
2048
2049 __ bind(&done);
1998 frame_->Push(r0); 2050 frame_->Push(r0);
1999 2051
2000 } else { 2052 } else {
2001 // Note: We would like to keep the assert below, but it fires because of 2053 // Note: We would like to keep the assert below, but it fires because of
2002 // some nasty code in LoadTypeofExpression() which should be removed... 2054 // some nasty code in LoadTypeofExpression() which should be removed...
2003 // ASSERT(!slot->var()->is_dynamic()); 2055 // ASSERT(!slot->var()->is_dynamic());
2004 2056
2005 // Special handling for locals allocated in registers. 2057 // Special handling for locals allocated in registers.
2006 __ ldr(r0, SlotOperand(slot, r2)); 2058 __ ldr(r0, SlotOperand(slot, r2));
2007 frame_->Push(r0); 2059 frame_->Push(r0);
2008 if (slot->var()->mode() == Variable::CONST) { 2060 if (slot->var()->mode() == Variable::CONST) {
2009 // Const slots may contain 'the hole' value (the constant hasn't been 2061 // Const slots may contain 'the hole' value (the constant hasn't been
2010 // initialized yet) which needs to be converted into the 'undefined' 2062 // initialized yet) which needs to be converted into the 'undefined'
2011 // value. 2063 // value.
2012 Comment cmnt(masm_, "[ Unhole const"); 2064 Comment cmnt(masm_, "[ Unhole const");
2013 frame_->Pop(r0); 2065 frame_->Pop(r0);
2014 __ cmp(r0, Operand(Factory::the_hole_value())); 2066 __ cmp(r0, Operand(Factory::the_hole_value()));
2015 __ mov(r0, Operand(Factory::undefined_value()), LeaveCC, eq); 2067 __ mov(r0, Operand(Factory::undefined_value()), LeaveCC, eq);
2016 frame_->Push(r0); 2068 frame_->Push(r0);
2017 } 2069 }
2018 } 2070 }
2019 } 2071 }
2020 2072
2021 2073
2074 void CodeGenerator::LoadFromGlobalSlotCheckExtensions(Slot* slot,
2075 TypeofState typeof_state,
2076 Register tmp,
2077 Register tmp2,
2078 Label* slow) {
2079 // Check that no extension objects have been created by calls to
2080 // eval from the current scope to the global scope.
2081 Register context = cp;
2082 for (Scope* s = scope(); s != NULL; s = s->outer_scope()) {
2083 if (s->num_heap_slots() > 0) {
2084 if (s->calls_eval()) {
2085 // Check that extension is NULL.
2086 __ ldr(tmp2, ContextOperand(context, Context::EXTENSION_INDEX));
2087 __ tst(tmp2, tmp2);
2088 __ b(ne, slow);
2089 }
2090 // Load next context in chain.
2091 __ ldr(tmp, ContextOperand(context, Context::CLOSURE_INDEX));
2092 __ ldr(tmp, FieldMemOperand(tmp, JSFunction::kContextOffset));
2093 context = tmp;
2094 }
2095 // If no outer scope calls eval, we do not need to check more
2096 // context extensions.
2097 if (!s->outer_scope_calls_eval()) break;
2098 }
2099
2100 // All extension objects were empty and it is safe to use a global
2101 // load IC call.
2102 Handle<Code> ic(Builtins::builtin(Builtins::LoadIC_Initialize));
2103 // Load the global object.
2104 LoadGlobal();
2105 // Setup the name register.
2106 __ mov(r2, Operand(slot->var()->name()));
2107 // Call IC stub.
2108 if (typeof_state == INSIDE_TYPEOF) {
2109 __ Call(ic, RelocInfo::CODE_TARGET);
2110 } else {
2111 __ Call(ic, RelocInfo::CODE_TARGET_CONTEXT);
2112 }
2113
2114 // Pop the global object. The result is in r0.
2115 frame_->Pop();
2116 }
2117
2118
2022 void CodeGenerator::VisitSlot(Slot* node) { 2119 void CodeGenerator::VisitSlot(Slot* node) {
2023 Comment cmnt(masm_, "[ Slot"); 2120 Comment cmnt(masm_, "[ Slot");
2024 LoadFromSlot(node, typeof_state()); 2121 LoadFromSlot(node, typeof_state());
2025 } 2122 }
2026 2123
2027 2124
2028 void CodeGenerator::VisitVariableProxy(VariableProxy* node) { 2125 void CodeGenerator::VisitVariableProxy(VariableProxy* node) {
2029 Comment cmnt(masm_, "[ VariableProxy"); 2126 Comment cmnt(masm_, "[ VariableProxy");
2030 2127
2031 Variable* var = node->var(); 2128 Variable* var = node->var();
(...skipping 2329 matching lines...) Expand 10 before | Expand all | Expand 10 after
4361 __ mov(r2, Operand(0)); 4458 __ mov(r2, Operand(0));
4362 __ GetBuiltinEntry(r3, Builtins::CALL_NON_FUNCTION); 4459 __ GetBuiltinEntry(r3, Builtins::CALL_NON_FUNCTION);
4363 __ Jump(Handle<Code>(Builtins::builtin(Builtins::ArgumentsAdaptorTrampoline)), 4460 __ Jump(Handle<Code>(Builtins::builtin(Builtins::ArgumentsAdaptorTrampoline)),
4364 RelocInfo::CODE_TARGET); 4461 RelocInfo::CODE_TARGET);
4365 } 4462 }
4366 4463
4367 4464
4368 #undef __ 4465 #undef __
4369 4466
4370 } } // namespace v8::internal 4467 } } // namespace v8::internal
OLDNEW
« no previous file with comments | « src/codegen-arm.h ('k') | src/codegen-ia32.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698