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

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

Issue 6606006: [Isolates] Merge 6500:6700 from bleeding_edge to isolates. (Closed) Base URL: http://v8.googlecode.com/svn/branches/experimental/isolates/
Patch Set: '' Created 9 years, 9 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/disasm-ia32.cc ('k') | src/ia32/ic-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 2011 the V8 project authors. All rights reserved. 1 // Copyright 2011 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 188 matching lines...) Expand 10 before | Expand all | Expand 10 after
199 // The stub will rewrite receiver and parameter count if the previous 199 // The stub will rewrite receiver and parameter count if the previous
200 // stack frame was an arguments adapter frame. 200 // stack frame was an arguments adapter frame.
201 ArgumentsAccessStub stub(ArgumentsAccessStub::NEW_OBJECT); 201 ArgumentsAccessStub stub(ArgumentsAccessStub::NEW_OBJECT);
202 __ CallStub(&stub); 202 __ CallStub(&stub);
203 __ mov(ecx, eax); // Duplicate result. 203 __ mov(ecx, eax); // Duplicate result.
204 Move(arguments->AsSlot(), eax, ebx, edx); 204 Move(arguments->AsSlot(), eax, ebx, edx);
205 Slot* dot_arguments_slot = scope()->arguments_shadow()->AsSlot(); 205 Slot* dot_arguments_slot = scope()->arguments_shadow()->AsSlot();
206 Move(dot_arguments_slot, ecx, ebx, edx); 206 Move(dot_arguments_slot, ecx, ebx, edx);
207 } 207 }
208 208
209 { Comment cmnt(masm_, "[ Declarations");
210 // For named function expressions, declare the function name as a
211 // constant.
212 if (scope()->is_function_scope() && scope()->function() != NULL) {
213 EmitDeclaration(scope()->function(), Variable::CONST, NULL);
214 }
215 // Visit all the explicit declarations unless there is an illegal
216 // redeclaration.
217 if (scope()->HasIllegalRedeclaration()) {
218 scope()->VisitIllegalRedeclaration(this);
219 } else {
220 VisitDeclarations(scope()->declarations());
221 }
222 }
223
224 if (FLAG_trace) { 209 if (FLAG_trace) {
225 __ CallRuntime(Runtime::kTraceEnter, 0); 210 __ CallRuntime(Runtime::kTraceEnter, 0);
226 } 211 }
227 212
228 { Comment cmnt(masm_, "[ Stack check"); 213 // Visit the declarations and body unless there is an illegal
229 PrepareForBailout(info->function(), NO_REGISTERS); 214 // redeclaration.
230 NearLabel ok; 215 if (scope()->HasIllegalRedeclaration()) {
231 ExternalReference stack_limit = 216 Comment cmnt(masm_, "[ Declarations");
232 ExternalReference::address_of_stack_limit(); 217 scope()->VisitIllegalRedeclaration(this);
233 __ cmp(esp, Operand::StaticVariable(stack_limit)); 218
234 __ j(above_equal, &ok, taken); 219 } else {
235 StackCheckStub stub; 220 { Comment cmnt(masm_, "[ Declarations");
236 __ CallStub(&stub); 221 // For named function expressions, declare the function name as a
237 __ bind(&ok); 222 // constant.
223 if (scope()->is_function_scope() && scope()->function() != NULL) {
224 EmitDeclaration(scope()->function(), Variable::CONST, NULL);
225 }
226 VisitDeclarations(scope()->declarations());
227 }
228
229 { Comment cmnt(masm_, "[ Stack check");
230 PrepareForBailout(info->function(), NO_REGISTERS);
231 NearLabel ok;
232 ExternalReference stack_limit =
233 ExternalReference::address_of_stack_limit();
234 __ cmp(esp, Operand::StaticVariable(stack_limit));
235 __ j(above_equal, &ok, taken);
236 StackCheckStub stub;
237 __ CallStub(&stub);
238 __ bind(&ok);
239 }
240
241 { Comment cmnt(masm_, "[ Body");
242 ASSERT(loop_depth() == 0);
243 VisitStatements(function()->body());
244 ASSERT(loop_depth() == 0);
245 }
238 } 246 }
239 247
240 { Comment cmnt(masm_, "[ Body"); 248 // Always emit a 'return undefined' in case control fell off the end of
241 ASSERT(loop_depth() == 0); 249 // the body.
242 VisitStatements(function()->body());
243 ASSERT(loop_depth() == 0);
244 }
245
246 { Comment cmnt(masm_, "[ return <undefined>;"); 250 { Comment cmnt(masm_, "[ return <undefined>;");
247 // Emit a 'return undefined' in case control fell off the end of the body.
248 __ mov(eax, isolate()->factory()->undefined_value()); 251 __ mov(eax, isolate()->factory()->undefined_value());
249 EmitReturnSequence(); 252 EmitReturnSequence();
250 } 253 }
251 } 254 }
252 255
253 256
254 void FullCodeGenerator::ClearAccumulator() { 257 void FullCodeGenerator::ClearAccumulator() {
255 __ Set(eax, Immediate(Smi::FromInt(0))); 258 __ Set(eax, Immediate(Smi::FromInt(0)));
256 } 259 }
257 260
(...skipping 42 matching lines...) Expand 10 before | Expand all | Expand 10 after
300 // Add a label for checking the size of the code used for returning. 303 // Add a label for checking the size of the code used for returning.
301 Label check_exit_codesize; 304 Label check_exit_codesize;
302 masm_->bind(&check_exit_codesize); 305 masm_->bind(&check_exit_codesize);
303 #endif 306 #endif
304 SetSourcePosition(function()->end_position() - 1); 307 SetSourcePosition(function()->end_position() - 1);
305 __ RecordJSReturn(); 308 __ RecordJSReturn();
306 // Do not use the leave instruction here because it is too short to 309 // Do not use the leave instruction here because it is too short to
307 // patch with the code required by the debugger. 310 // patch with the code required by the debugger.
308 __ mov(esp, ebp); 311 __ mov(esp, ebp);
309 __ pop(ebp); 312 __ pop(ebp);
310 __ ret((scope()->num_parameters() + 1) * kPointerSize); 313
314 int arguments_bytes = (scope()->num_parameters() + 1) * kPointerSize;
315 __ Ret(arguments_bytes, ecx);
311 #ifdef ENABLE_DEBUGGER_SUPPORT 316 #ifdef ENABLE_DEBUGGER_SUPPORT
312 // Check that the size of the code used for returning matches what is 317 // Check that the size of the code used for returning is large enough
313 // expected by the debugger. 318 // for the debugger's requirements.
314 ASSERT_EQ(Assembler::kJSReturnSequenceLength, 319 ASSERT(Assembler::kJSReturnSequenceLength <=
315 masm_->SizeOfCodeGeneratedSince(&check_exit_codesize)); 320 masm_->SizeOfCodeGeneratedSince(&check_exit_codesize));
316 #endif 321 #endif
317 } 322 }
318 } 323 }
319 324
320 325
321 FullCodeGenerator::ConstantOperand FullCodeGenerator::GetConstantOperand( 326 FullCodeGenerator::ConstantOperand FullCodeGenerator::GetConstantOperand(
322 Token::Value op, Expression* left, Expression* right) { 327 Token::Value op, Expression* left, Expression* right) {
323 ASSERT(ShouldInlineSmiCase(op)); 328 ASSERT(ShouldInlineSmiCase(op));
324 if (op == Token::DIV || op == Token::MOD || op == Token::MUL) { 329 if (op == Token::DIV || op == Token::MOD || op == Token::MUL) {
325 // We never generate inlined constant smi operations for these. 330 // We never generate inlined constant smi operations for these.
(...skipping 279 matching lines...) Expand 10 before | Expand all | Expand 10 after
605 void FullCodeGenerator::Move(Slot* dst, 610 void FullCodeGenerator::Move(Slot* dst,
606 Register src, 611 Register src,
607 Register scratch1, 612 Register scratch1,
608 Register scratch2) { 613 Register scratch2) {
609 ASSERT(dst->type() != Slot::LOOKUP); // Not yet implemented. 614 ASSERT(dst->type() != Slot::LOOKUP); // Not yet implemented.
610 ASSERT(!scratch1.is(src) && !scratch2.is(src)); 615 ASSERT(!scratch1.is(src) && !scratch2.is(src));
611 MemOperand location = EmitSlotSearch(dst, scratch1); 616 MemOperand location = EmitSlotSearch(dst, scratch1);
612 __ mov(location, src); 617 __ mov(location, src);
613 // Emit the write barrier code if the location is in the heap. 618 // Emit the write barrier code if the location is in the heap.
614 if (dst->type() == Slot::CONTEXT) { 619 if (dst->type() == Slot::CONTEXT) {
615 int offset = FixedArray::kHeaderSize + dst->index() * kPointerSize; 620 int offset = Context::SlotOffset(dst->index());
616 __ RecordWrite(scratch1, offset, src, scratch2); 621 __ RecordWrite(scratch1, offset, src, scratch2);
617 } 622 }
618 } 623 }
619 624
620 625
621 void FullCodeGenerator::PrepareForBailoutBeforeSplit(State state, 626 void FullCodeGenerator::PrepareForBailoutBeforeSplit(State state,
622 bool should_normalize, 627 bool should_normalize,
623 Label* if_true, 628 Label* if_true,
624 Label* if_false) { 629 Label* if_false) {
625 // Only prepare for bailouts before splits if we're in a test 630 // Only prepare for bailouts before splits if we're in a test
(...skipping 35 matching lines...) Expand 10 before | Expand all | Expand 10 after
661 } else if (function != NULL) { 666 } else if (function != NULL) {
662 VisitForAccumulatorValue(function); 667 VisitForAccumulatorValue(function);
663 __ mov(Operand(ebp, SlotOffset(slot)), result_register()); 668 __ mov(Operand(ebp, SlotOffset(slot)), result_register());
664 } 669 }
665 break; 670 break;
666 671
667 case Slot::CONTEXT: 672 case Slot::CONTEXT:
668 // We bypass the general EmitSlotSearch because we know more about 673 // We bypass the general EmitSlotSearch because we know more about
669 // this specific context. 674 // this specific context.
670 675
671 // The variable in the decl always resides in the current context. 676 // The variable in the decl always resides in the current function
677 // context.
672 ASSERT_EQ(0, scope()->ContextChainLength(variable->scope())); 678 ASSERT_EQ(0, scope()->ContextChainLength(variable->scope()));
673 if (FLAG_debug_code) { 679 if (FLAG_debug_code) {
674 // Check if we have the correct context pointer. 680 // Check that we're not inside a 'with'.
675 __ mov(ebx, ContextOperand(esi, Context::FCONTEXT_INDEX)); 681 __ mov(ebx, ContextOperand(esi, Context::FCONTEXT_INDEX));
676 __ cmp(ebx, Operand(esi)); 682 __ cmp(ebx, Operand(esi));
677 __ Check(equal, "Unexpected declaration in current context."); 683 __ Check(equal, "Unexpected declaration in current context.");
678 } 684 }
679 if (mode == Variable::CONST) { 685 if (mode == Variable::CONST) {
680 __ mov(ContextOperand(esi, slot->index()), 686 __ mov(ContextOperand(esi, slot->index()),
681 Immediate(isolate()->factory()->the_hole_value())); 687 Immediate(isolate()->factory()->the_hole_value()));
682 // No write barrier since the hole value is in old space. 688 // No write barrier since the hole value is in old space.
683 } else if (function != NULL) { 689 } else if (function != NULL) {
684 VisitForAccumulatorValue(function); 690 VisitForAccumulatorValue(function);
(...skipping 23 matching lines...) Expand all
708 __ push(Immediate(Smi::FromInt(0))); // No initial value! 714 __ push(Immediate(Smi::FromInt(0))); // No initial value!
709 } 715 }
710 __ CallRuntime(Runtime::kDeclareContextSlot, 4); 716 __ CallRuntime(Runtime::kDeclareContextSlot, 4);
711 break; 717 break;
712 } 718 }
713 } 719 }
714 720
715 } else if (prop != NULL) { 721 } else if (prop != NULL) {
716 if (function != NULL || mode == Variable::CONST) { 722 if (function != NULL || mode == Variable::CONST) {
717 // We are declaring a function or constant that rewrites to a 723 // We are declaring a function or constant that rewrites to a
718 // property. Use (keyed) IC to set the initial value. 724 // property. Use (keyed) IC to set the initial value. We cannot
719 VisitForStackValue(prop->obj()); 725 // visit the rewrite because it's shared and we risk recording
726 // duplicate AST IDs for bailouts from optimized code.
727 ASSERT(prop->obj()->AsVariableProxy() != NULL);
728 { AccumulatorValueContext for_object(this);
729 EmitVariableLoad(prop->obj()->AsVariableProxy()->var());
730 }
731
720 if (function != NULL) { 732 if (function != NULL) {
721 VisitForStackValue(prop->key()); 733 __ push(eax);
722 VisitForAccumulatorValue(function); 734 VisitForAccumulatorValue(function);
723 __ pop(ecx); 735 __ pop(edx);
724 } else { 736 } else {
725 VisitForAccumulatorValue(prop->key()); 737 __ mov(edx, eax);
726 __ mov(ecx, result_register()); 738 __ mov(eax, isolate()->factory()->the_hole_value());
727 __ mov(result_register(), isolate()->factory()->the_hole_value());
728 } 739 }
729 __ pop(edx); 740 ASSERT(prop->key()->AsLiteral() != NULL &&
741 prop->key()->AsLiteral()->handle()->IsSmi());
742 __ Set(ecx, Immediate(prop->key()->AsLiteral()->handle()));
730 743
731 Handle<Code> ic(isolate()->builtins()->builtin( 744 Handle<Code> ic(isolate()->builtins()->builtin(
732 Builtins::KeyedStoreIC_Initialize)); 745 Builtins::KeyedStoreIC_Initialize));
733 EmitCallIC(ic, RelocInfo::CODE_TARGET); 746 EmitCallIC(ic, RelocInfo::CODE_TARGET);
734 } 747 }
735 } 748 }
736 } 749 }
737 750
738 751
739 void FullCodeGenerator::VisitDeclaration(Declaration* decl) { 752 void FullCodeGenerator::VisitDeclaration(Declaration* decl) {
(...skipping 382 matching lines...) Expand 10 before | Expand all | Expand 10 after
1122 } 1135 }
1123 __ mov(temp, ContextOperand(context, Context::CLOSURE_INDEX)); 1136 __ mov(temp, ContextOperand(context, Context::CLOSURE_INDEX));
1124 __ mov(temp, FieldOperand(temp, JSFunction::kContextOffset)); 1137 __ mov(temp, FieldOperand(temp, JSFunction::kContextOffset));
1125 // Walk the rest of the chain without clobbering esi. 1138 // Walk the rest of the chain without clobbering esi.
1126 context = temp; 1139 context = temp;
1127 } 1140 }
1128 } 1141 }
1129 // Check that last extension is NULL. 1142 // Check that last extension is NULL.
1130 __ cmp(ContextOperand(context, Context::EXTENSION_INDEX), Immediate(0)); 1143 __ cmp(ContextOperand(context, Context::EXTENSION_INDEX), Immediate(0));
1131 __ j(not_equal, slow); 1144 __ j(not_equal, slow);
1132 __ mov(temp, ContextOperand(context, Context::FCONTEXT_INDEX)); 1145
1133 return ContextOperand(temp, slot->index()); 1146 // This function is used only for loads, not stores, so it's safe to
1147 // return an esi-based operand (the write barrier cannot be allowed to
1148 // destroy the esi register).
1149 return ContextOperand(context, slot->index());
1134 } 1150 }
1135 1151
1136 1152
1137 void FullCodeGenerator::EmitDynamicLoadFromSlotFastCase( 1153 void FullCodeGenerator::EmitDynamicLoadFromSlotFastCase(
1138 Slot* slot, 1154 Slot* slot,
1139 TypeofState typeof_state, 1155 TypeofState typeof_state,
1140 Label* slow, 1156 Label* slow,
1141 Label* done) { 1157 Label* done) {
1142 // Generate fast-case code for variables that might be shadowed by 1158 // Generate fast-case code for variables that might be shadowed by
1143 // eval-introduced variables. Eval is used a lot without 1159 // eval-introduced variables. Eval is used a lot without
(...skipping 864 matching lines...) Expand 10 before | Expand all | Expand 10 after
2008 ASSERT(!var->is_this()); 2024 ASSERT(!var->is_this());
2009 // Assignment to a global variable. Use inline caching for the 2025 // Assignment to a global variable. Use inline caching for the
2010 // assignment. Right-hand-side value is passed in eax, variable name in 2026 // assignment. Right-hand-side value is passed in eax, variable name in
2011 // ecx, and the global object on the stack. 2027 // ecx, and the global object on the stack.
2012 __ mov(ecx, var->name()); 2028 __ mov(ecx, var->name());
2013 __ mov(edx, GlobalObjectOperand()); 2029 __ mov(edx, GlobalObjectOperand());
2014 Handle<Code> ic(isolate()->builtins()->builtin( 2030 Handle<Code> ic(isolate()->builtins()->builtin(
2015 Builtins::StoreIC_Initialize)); 2031 Builtins::StoreIC_Initialize));
2016 EmitCallIC(ic, RelocInfo::CODE_TARGET); 2032 EmitCallIC(ic, RelocInfo::CODE_TARGET);
2017 2033
2018 } else if (var->mode() != Variable::CONST || op == Token::INIT_CONST) { 2034 } else if (op == Token::INIT_CONST) {
2019 // Perform the assignment for non-const variables and for initialization 2035 // Like var declarations, const declarations are hoisted to function
2020 // of const variables. Const assignments are simply skipped. 2036 // scope. However, unlike var initializers, const initializers are able
2021 Label done; 2037 // to drill a hole to that function context, even from inside a 'with'
2038 // context. We thus bypass the normal static scope lookup.
2039 Slot* slot = var->AsSlot();
2040 Label skip;
2041 switch (slot->type()) {
2042 case Slot::PARAMETER:
2043 // No const parameters.
2044 UNREACHABLE();
2045 break;
2046 case Slot::LOCAL:
2047 __ mov(edx, Operand(ebp, SlotOffset(slot)));
2048 __ cmp(edx, isolate()->factory()->the_hole_value());
2049 __ j(not_equal, &skip);
2050 __ mov(Operand(ebp, SlotOffset(slot)), eax);
2051 break;
2052 case Slot::CONTEXT: {
2053 __ mov(ecx, ContextOperand(esi, Context::FCONTEXT_INDEX));
2054 __ mov(edx, ContextOperand(ecx, slot->index()));
2055 __ cmp(edx, isolate()->factory()->the_hole_value());
2056 __ j(not_equal, &skip);
2057 __ mov(ContextOperand(ecx, slot->index()), eax);
2058 int offset = Context::SlotOffset(slot->index());
2059 __ mov(edx, eax); // Preserve the stored value in eax.
2060 __ RecordWrite(ecx, offset, edx, ebx);
2061 break;
2062 }
2063 case Slot::LOOKUP:
2064 __ push(eax);
2065 __ push(esi);
2066 __ push(Immediate(var->name()));
2067 __ CallRuntime(Runtime::kInitializeConstContextSlot, 3);
2068 break;
2069 }
2070 __ bind(&skip);
2071
2072 } else if (var->mode() != Variable::CONST) {
2073 // Perform the assignment for non-const variables. Const assignments
2074 // are simply skipped.
2022 Slot* slot = var->AsSlot(); 2075 Slot* slot = var->AsSlot();
2023 switch (slot->type()) { 2076 switch (slot->type()) {
2024 case Slot::PARAMETER: 2077 case Slot::PARAMETER:
2025 case Slot::LOCAL: 2078 case Slot::LOCAL:
2026 if (op == Token::INIT_CONST) {
2027 // Detect const reinitialization by checking for the hole value.
2028 __ mov(edx, Operand(ebp, SlotOffset(slot)));
2029 __ cmp(edx, isolate()->factory()->the_hole_value());
2030 __ j(not_equal, &done);
2031 }
2032 // Perform the assignment. 2079 // Perform the assignment.
2033 __ mov(Operand(ebp, SlotOffset(slot)), eax); 2080 __ mov(Operand(ebp, SlotOffset(slot)), eax);
2034 break; 2081 break;
2035 2082
2036 case Slot::CONTEXT: { 2083 case Slot::CONTEXT: {
2037 MemOperand target = EmitSlotSearch(slot, ecx); 2084 MemOperand target = EmitSlotSearch(slot, ecx);
2038 if (op == Token::INIT_CONST) {
2039 // Detect const reinitialization by checking for the hole value.
2040 __ mov(edx, target);
2041 __ cmp(edx, isolate()->factory()->the_hole_value());
2042 __ j(not_equal, &done);
2043 }
2044 // Perform the assignment and issue the write barrier. 2085 // Perform the assignment and issue the write barrier.
2045 __ mov(target, eax); 2086 __ mov(target, eax);
2046 // The value of the assignment is in eax. RecordWrite clobbers its 2087 // The value of the assignment is in eax. RecordWrite clobbers its
2047 // register arguments. 2088 // register arguments.
2048 __ mov(edx, eax); 2089 __ mov(edx, eax);
2049 int offset = FixedArray::kHeaderSize + slot->index() * kPointerSize; 2090 int offset = Context::SlotOffset(slot->index());
2050 __ RecordWrite(ecx, offset, edx, ebx); 2091 __ RecordWrite(ecx, offset, edx, ebx);
2051 break; 2092 break;
2052 } 2093 }
2053 2094
2054 case Slot::LOOKUP: 2095 case Slot::LOOKUP:
2055 // Call the runtime for the assignment. The runtime will ignore 2096 // Call the runtime for the assignment.
2056 // const reinitialization.
2057 __ push(eax); // Value. 2097 __ push(eax); // Value.
2058 __ push(esi); // Context. 2098 __ push(esi); // Context.
2059 __ push(Immediate(var->name())); 2099 __ push(Immediate(var->name()));
2060 if (op == Token::INIT_CONST) { 2100 __ CallRuntime(Runtime::kStoreContextSlot, 3);
2061 // The runtime will ignore const redeclaration.
2062 __ CallRuntime(Runtime::kInitializeConstContextSlot, 3);
2063 } else {
2064 __ CallRuntime(Runtime::kStoreContextSlot, 3);
2065 }
2066 break; 2101 break;
2067 } 2102 }
2068 __ bind(&done);
2069 } 2103 }
2070 } 2104 }
2071 2105
2072 2106
2073 void FullCodeGenerator::EmitNamedPropertyAssignment(Assignment* expr) { 2107 void FullCodeGenerator::EmitNamedPropertyAssignment(Assignment* expr) {
2074 // Assignment to a property, using a named store IC. 2108 // Assignment to a property, using a named store IC.
2075 Property* prop = expr->target()->AsProperty(); 2109 Property* prop = expr->target()->AsProperty();
2076 ASSERT(prop != NULL); 2110 ASSERT(prop != NULL);
2077 ASSERT(prop->key()->AsLiteral() != NULL); 2111 ASSERT(prop->key()->AsLiteral() != NULL);
2078 2112
(...skipping 203 matching lines...) Expand 10 before | Expand all | Expand 10 after
2282 2316
2283 // Push copy of the first argument or undefined if it doesn't exist. 2317 // Push copy of the first argument or undefined if it doesn't exist.
2284 if (arg_count > 0) { 2318 if (arg_count > 0) {
2285 __ push(Operand(esp, arg_count * kPointerSize)); 2319 __ push(Operand(esp, arg_count * kPointerSize));
2286 } else { 2320 } else {
2287 __ push(Immediate(isolate()->factory()->undefined_value())); 2321 __ push(Immediate(isolate()->factory()->undefined_value()));
2288 } 2322 }
2289 2323
2290 // Push the receiver of the enclosing function and do runtime call. 2324 // Push the receiver of the enclosing function and do runtime call.
2291 __ push(Operand(ebp, (2 + scope()->num_parameters()) * kPointerSize)); 2325 __ push(Operand(ebp, (2 + scope()->num_parameters()) * kPointerSize));
2292 __ CallRuntime(Runtime::kResolvePossiblyDirectEval, 3); 2326 // Push the strict mode flag.
2327 __ push(Immediate(Smi::FromInt(strict_mode_flag())));
2328 __ CallRuntime(Runtime::kResolvePossiblyDirectEval, 4);
2293 2329
2294 // The runtime call returns a pair of values in eax (function) and 2330 // The runtime call returns a pair of values in eax (function) and
2295 // edx (receiver). Touch up the stack with the right values. 2331 // edx (receiver). Touch up the stack with the right values.
2296 __ mov(Operand(esp, (arg_count + 0) * kPointerSize), edx); 2332 __ mov(Operand(esp, (arg_count + 0) * kPointerSize), edx);
2297 __ mov(Operand(esp, (arg_count + 1) * kPointerSize), eax); 2333 __ mov(Operand(esp, (arg_count + 1) * kPointerSize), eax);
2298 } 2334 }
2299 // Record source position for debugger. 2335 // Record source position for debugger.
2300 SetSourcePosition(expr->position()); 2336 SetSourcePosition(expr->position());
2301 InLoopFlag in_loop = (loop_depth() > 0) ? IN_LOOP : NOT_IN_LOOP; 2337 InLoopFlag in_loop = (loop_depth() > 0) ? IN_LOOP : NOT_IN_LOOP;
2302 CallFunctionStub stub(arg_count, in_loop, RECEIVER_MIGHT_BE_VALUE); 2338 CallFunctionStub stub(arg_count, in_loop, RECEIVER_MIGHT_BE_VALUE);
(...skipping 1460 matching lines...) Expand 10 before | Expand all | Expand 10 after
3763 context()->Plug(eax); 3799 context()->Plug(eax);
3764 break; 3800 break;
3765 } 3801 }
3766 3802
3767 case Token::ADD: { 3803 case Token::ADD: {
3768 Comment cmt(masm_, "[ UnaryOperation (ADD)"); 3804 Comment cmt(masm_, "[ UnaryOperation (ADD)");
3769 VisitForAccumulatorValue(expr->expression()); 3805 VisitForAccumulatorValue(expr->expression());
3770 Label no_conversion; 3806 Label no_conversion;
3771 __ test(result_register(), Immediate(kSmiTagMask)); 3807 __ test(result_register(), Immediate(kSmiTagMask));
3772 __ j(zero, &no_conversion); 3808 __ j(zero, &no_conversion);
3773 __ push(result_register()); 3809 ToNumberStub convert_stub;
3774 __ InvokeBuiltin(Builtins::TO_NUMBER, CALL_FUNCTION); 3810 __ CallStub(&convert_stub);
3775 __ bind(&no_conversion); 3811 __ bind(&no_conversion);
3776 context()->Plug(result_register()); 3812 context()->Plug(result_register());
3777 break; 3813 break;
3778 } 3814 }
3779 3815
3780 case Token::SUB: { 3816 case Token::SUB: {
3781 Comment cmt(masm_, "[ UnaryOperation (SUB)"); 3817 Comment cmt(masm_, "[ UnaryOperation (SUB)");
3782 bool can_overwrite = expr->expression()->ResultOverwriteAllowed(); 3818 bool can_overwrite = expr->expression()->ResultOverwriteAllowed();
3783 UnaryOverwriteMode overwrite = 3819 UnaryOverwriteMode overwrite =
3784 can_overwrite ? UNARY_OVERWRITE : UNARY_NO_OVERWRITE; 3820 can_overwrite ? UNARY_OVERWRITE : UNARY_NO_OVERWRITE;
(...skipping 99 matching lines...) Expand 10 before | Expand all | Expand 10 after
3884 // We need a second deoptimization point after loading the value 3920 // We need a second deoptimization point after loading the value
3885 // in case evaluating the property load my have a side effect. 3921 // in case evaluating the property load my have a side effect.
3886 PrepareForBailout(expr->increment(), TOS_REG); 3922 PrepareForBailout(expr->increment(), TOS_REG);
3887 3923
3888 // Call ToNumber only if operand is not a smi. 3924 // Call ToNumber only if operand is not a smi.
3889 NearLabel no_conversion; 3925 NearLabel no_conversion;
3890 if (ShouldInlineSmiCase(expr->op())) { 3926 if (ShouldInlineSmiCase(expr->op())) {
3891 __ test(eax, Immediate(kSmiTagMask)); 3927 __ test(eax, Immediate(kSmiTagMask));
3892 __ j(zero, &no_conversion); 3928 __ j(zero, &no_conversion);
3893 } 3929 }
3894 __ push(eax); 3930 ToNumberStub convert_stub;
3895 __ InvokeBuiltin(Builtins::TO_NUMBER, CALL_FUNCTION); 3931 __ CallStub(&convert_stub);
3896 __ bind(&no_conversion); 3932 __ bind(&no_conversion);
3897 3933
3898 // Save result for postfix expressions. 3934 // Save result for postfix expressions.
3899 if (expr->is_postfix()) { 3935 if (expr->is_postfix()) {
3900 if (!context()->IsEffect()) { 3936 if (!context()->IsEffect()) {
3901 // Save the result on the stack. If we have a named or keyed property 3937 // Save the result on the stack. If we have a named or keyed property
3902 // we store the result under the receiver that is currently on top 3938 // we store the result under the receiver that is currently on top
3903 // of the stack. 3939 // of the stack.
3904 switch (assign_type) { 3940 switch (assign_type) {
3905 case VARIABLE: 3941 case VARIABLE:
(...skipping 32 matching lines...) Expand 10 before | Expand all | Expand 10 after
3938 __ add(Operand(eax), Immediate(Smi::FromInt(1))); 3974 __ add(Operand(eax), Immediate(Smi::FromInt(1)));
3939 } 3975 }
3940 } 3976 }
3941 3977
3942 // Record position before stub call. 3978 // Record position before stub call.
3943 SetSourcePosition(expr->position()); 3979 SetSourcePosition(expr->position());
3944 3980
3945 // Call stub for +1/-1. 3981 // Call stub for +1/-1.
3946 __ mov(edx, eax); 3982 __ mov(edx, eax);
3947 __ mov(eax, Immediate(Smi::FromInt(1))); 3983 __ mov(eax, Immediate(Smi::FromInt(1)));
3948 TypeRecordingBinaryOpStub stub(expr->binary_op(), 3984 TypeRecordingBinaryOpStub stub(expr->binary_op(), NO_OVERWRITE);
3949 NO_OVERWRITE);
3950 EmitCallIC(stub.GetCode(), &patch_site); 3985 EmitCallIC(stub.GetCode(), &patch_site);
3951 __ bind(&done); 3986 __ bind(&done);
3952 3987
3953 // Store the value returned in eax. 3988 // Store the value returned in eax.
3954 switch (assign_type) { 3989 switch (assign_type) {
3955 case VARIABLE: 3990 case VARIABLE:
3956 if (expr->is_postfix()) { 3991 if (expr->is_postfix()) {
3957 // Perform the assignment as if via '='. 3992 // Perform the assignment as if via '='.
3958 { EffectContext context(this); 3993 { EffectContext context(this);
3959 EmitVariableAssignment(expr->expression()->AsVariableProxy()->var(), 3994 EmitVariableAssignment(expr->expression()->AsVariableProxy()->var(),
(...skipping 432 matching lines...) Expand 10 before | Expand all | Expand 10 after
4392 // And return. 4427 // And return.
4393 __ ret(0); 4428 __ ret(0);
4394 } 4429 }
4395 4430
4396 4431
4397 #undef __ 4432 #undef __
4398 4433
4399 } } // namespace v8::internal 4434 } } // namespace v8::internal
4400 4435
4401 #endif // V8_TARGET_ARCH_IA32 4436 #endif // V8_TARGET_ARCH_IA32
OLDNEW
« no previous file with comments | « src/ia32/disasm-ia32.cc ('k') | src/ia32/ic-ia32.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698