| OLD | NEW |
| 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 85 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 96 | 96 |
| 97 CodeGenState::~CodeGenState() { | 97 CodeGenState::~CodeGenState() { |
| 98 ASSERT(owner_->state() == this); | 98 ASSERT(owner_->state() == this); |
| 99 owner_->set_state(previous_); | 99 owner_->set_state(previous_); |
| 100 } | 100 } |
| 101 | 101 |
| 102 | 102 |
| 103 // ------------------------------------------------------------------------- | 103 // ------------------------------------------------------------------------- |
| 104 // CodeGenerator implementation | 104 // CodeGenerator implementation |
| 105 | 105 |
| 106 CodeGenerator::CodeGenerator(MacroAssembler* masm, | 106 CodeGenerator::CodeGenerator(MacroAssembler* masm) |
| 107 Handle<Script> script, | 107 : deferred_(8), |
| 108 bool is_eval) | |
| 109 : is_eval_(is_eval), | |
| 110 script_(script), | |
| 111 deferred_(8), | |
| 112 masm_(masm), | 108 masm_(masm), |
| 113 scope_(NULL), | 109 info_(NULL), |
| 114 frame_(NULL), | 110 frame_(NULL), |
| 115 allocator_(NULL), | 111 allocator_(NULL), |
| 116 state_(NULL), | 112 state_(NULL), |
| 117 loop_nesting_(0), | 113 loop_nesting_(0), |
| 118 function_return_is_shadowed_(false), | 114 function_return_is_shadowed_(false), |
| 119 in_spilled_code_(false) { | 115 in_spilled_code_(false) { |
| 120 } | 116 } |
| 121 | 117 |
| 122 | 118 |
| 119 Scope* CodeGenerator::scope() { return info_->function()->scope(); } |
| 120 |
| 121 |
| 123 // Calling conventions: | 122 // Calling conventions: |
| 124 // ebp: caller's frame pointer | 123 // ebp: caller's frame pointer |
| 125 // esp: stack pointer | 124 // esp: stack pointer |
| 126 // edi: called JS function | 125 // edi: called JS function |
| 127 // esi: callee's context | 126 // esi: callee's context |
| 128 | 127 |
| 129 void CodeGenerator::Generate(FunctionLiteral* fun, | 128 void CodeGenerator::Generate(CompilationInfo* info, Mode mode) { |
| 130 Mode mode, | |
| 131 CompilationInfo* info) { | |
| 132 // Record the position for debugging purposes. | 129 // Record the position for debugging purposes. |
| 133 CodeForFunctionPosition(fun); | 130 CodeForFunctionPosition(info->function()); |
| 134 | |
| 135 ZoneList<Statement*>* body = fun->body(); | |
| 136 | 131 |
| 137 // Initialize state. | 132 // Initialize state. |
| 138 ASSERT(scope_ == NULL); | 133 info_ = info; |
| 139 scope_ = fun->scope(); | |
| 140 ASSERT(allocator_ == NULL); | 134 ASSERT(allocator_ == NULL); |
| 141 RegisterAllocator register_allocator(this); | 135 RegisterAllocator register_allocator(this); |
| 142 allocator_ = ®ister_allocator; | 136 allocator_ = ®ister_allocator; |
| 143 ASSERT(frame_ == NULL); | 137 ASSERT(frame_ == NULL); |
| 144 frame_ = new VirtualFrame(); | 138 frame_ = new VirtualFrame(); |
| 145 set_in_spilled_code(false); | 139 set_in_spilled_code(false); |
| 146 | 140 |
| 147 // Adjust for function-level loop nesting. | 141 // Adjust for function-level loop nesting. |
| 148 loop_nesting_ += info->loop_nesting(); | 142 loop_nesting_ += info->loop_nesting(); |
| 149 | 143 |
| 150 JumpTarget::set_compiling_deferred_code(false); | 144 JumpTarget::set_compiling_deferred_code(false); |
| 151 | 145 |
| 152 #ifdef DEBUG | 146 #ifdef DEBUG |
| 153 if (strlen(FLAG_stop_at) > 0 && | 147 if (strlen(FLAG_stop_at) > 0 && |
| 154 fun->name()->IsEqualTo(CStrVector(FLAG_stop_at))) { | 148 info->function()->name()->IsEqualTo(CStrVector(FLAG_stop_at))) { |
| 155 frame_->SpillAll(); | 149 frame_->SpillAll(); |
| 156 __ int3(); | 150 __ int3(); |
| 157 } | 151 } |
| 158 #endif | 152 #endif |
| 159 | 153 |
| 160 // New scope to get automatic timing calculation. | 154 // New scope to get automatic timing calculation. |
| 161 { // NOLINT | 155 { // NOLINT |
| 162 HistogramTimerScope codegen_timer(&Counters::code_generation); | 156 HistogramTimerScope codegen_timer(&Counters::code_generation); |
| 163 CodeGenState state(this); | 157 CodeGenState state(this); |
| 164 | 158 |
| 165 // Entry: | 159 // Entry: |
| 166 // Stack: receiver, arguments, return address. | 160 // Stack: receiver, arguments, return address. |
| 167 // ebp: caller's frame pointer | 161 // ebp: caller's frame pointer |
| 168 // esp: stack pointer | 162 // esp: stack pointer |
| 169 // edi: called JS function | 163 // edi: called JS function |
| 170 // esi: callee's context | 164 // esi: callee's context |
| 171 allocator_->Initialize(); | 165 allocator_->Initialize(); |
| 172 | 166 |
| 173 if (mode == PRIMARY) { | 167 if (mode == PRIMARY) { |
| 174 frame_->Enter(); | 168 frame_->Enter(); |
| 175 | 169 |
| 176 // Allocate space for locals and initialize them. | 170 // Allocate space for locals and initialize them. |
| 177 frame_->AllocateStackSlots(); | 171 frame_->AllocateStackSlots(); |
| 178 | 172 |
| 179 // Allocate the local context if needed. | 173 // Allocate the local context if needed. |
| 180 int heap_slots = scope_->num_heap_slots() - Context::MIN_CONTEXT_SLOTS; | 174 int heap_slots = scope()->num_heap_slots() - Context::MIN_CONTEXT_SLOTS; |
| 181 if (heap_slots > 0) { | 175 if (heap_slots > 0) { |
| 182 Comment cmnt(masm_, "[ allocate local context"); | 176 Comment cmnt(masm_, "[ allocate local context"); |
| 183 // Allocate local context. | 177 // Allocate local context. |
| 184 // Get outer context and create a new context based on it. | 178 // Get outer context and create a new context based on it. |
| 185 frame_->PushFunction(); | 179 frame_->PushFunction(); |
| 186 Result context; | 180 Result context; |
| 187 if (heap_slots <= FastNewContextStub::kMaximumSlots) { | 181 if (heap_slots <= FastNewContextStub::kMaximumSlots) { |
| 188 FastNewContextStub stub(heap_slots); | 182 FastNewContextStub stub(heap_slots); |
| 189 context = frame_->CallStub(&stub, 1); | 183 context = frame_->CallStub(&stub, 1); |
| 190 } else { | 184 } else { |
| 191 context = frame_->CallRuntime(Runtime::kNewContext, 1); | 185 context = frame_->CallRuntime(Runtime::kNewContext, 1); |
| 192 } | 186 } |
| 193 | 187 |
| 194 // Update context local. | 188 // Update context local. |
| 195 frame_->SaveContextRegister(); | 189 frame_->SaveContextRegister(); |
| 196 | 190 |
| 197 // Verify that the runtime call result and esi agree. | 191 // Verify that the runtime call result and esi agree. |
| 198 if (FLAG_debug_code) { | 192 if (FLAG_debug_code) { |
| 199 __ cmp(context.reg(), Operand(esi)); | 193 __ cmp(context.reg(), Operand(esi)); |
| 200 __ Assert(equal, "Runtime::NewContext should end up in esi"); | 194 __ Assert(equal, "Runtime::NewContext should end up in esi"); |
| 201 } | 195 } |
| 202 } | 196 } |
| 203 | 197 |
| 204 // TODO(1241774): Improve this code: | 198 // TODO(1241774): Improve this code: |
| 205 // 1) only needed if we have a context | 199 // 1) only needed if we have a context |
| 206 // 2) no need to recompute context ptr every single time | 200 // 2) no need to recompute context ptr every single time |
| 207 // 3) don't copy parameter operand code from SlotOperand! | 201 // 3) don't copy parameter operand code from SlotOperand! |
| 208 { | 202 { |
| 209 Comment cmnt2(masm_, "[ copy context parameters into .context"); | 203 Comment cmnt2(masm_, "[ copy context parameters into .context"); |
| 210 | |
| 211 // Note that iteration order is relevant here! If we have the same | 204 // Note that iteration order is relevant here! If we have the same |
| 212 // parameter twice (e.g., function (x, y, x)), and that parameter | 205 // parameter twice (e.g., function (x, y, x)), and that parameter |
| 213 // needs to be copied into the context, it must be the last argument | 206 // needs to be copied into the context, it must be the last argument |
| 214 // passed to the parameter that needs to be copied. This is a rare | 207 // passed to the parameter that needs to be copied. This is a rare |
| 215 // case so we don't check for it, instead we rely on the copying | 208 // case so we don't check for it, instead we rely on the copying |
| 216 // order: such a parameter is copied repeatedly into the same | 209 // order: such a parameter is copied repeatedly into the same |
| 217 // context location and thus the last value is what is seen inside | 210 // context location and thus the last value is what is seen inside |
| 218 // the function. | 211 // the function. |
| 219 for (int i = 0; i < scope_->num_parameters(); i++) { | 212 for (int i = 0; i < scope()->num_parameters(); i++) { |
| 220 Variable* par = scope_->parameter(i); | 213 Variable* par = scope()->parameter(i); |
| 221 Slot* slot = par->slot(); | 214 Slot* slot = par->slot(); |
| 222 if (slot != NULL && slot->type() == Slot::CONTEXT) { | 215 if (slot != NULL && slot->type() == Slot::CONTEXT) { |
| 223 // The use of SlotOperand below is safe in unspilled code | 216 // The use of SlotOperand below is safe in unspilled code |
| 224 // because the slot is guaranteed to be a context slot. | 217 // because the slot is guaranteed to be a context slot. |
| 225 // | 218 // |
| 226 // There are no parameters in the global scope. | 219 // There are no parameters in the global scope. |
| 227 ASSERT(!scope_->is_global_scope()); | 220 ASSERT(!scope()->is_global_scope()); |
| 228 frame_->PushParameterAt(i); | 221 frame_->PushParameterAt(i); |
| 229 Result value = frame_->Pop(); | 222 Result value = frame_->Pop(); |
| 230 value.ToRegister(); | 223 value.ToRegister(); |
| 231 | 224 |
| 232 // SlotOperand loads context.reg() with the context object | 225 // SlotOperand loads context.reg() with the context object |
| 233 // stored to, used below in RecordWrite. | 226 // stored to, used below in RecordWrite. |
| 234 Result context = allocator_->Allocate(); | 227 Result context = allocator_->Allocate(); |
| 235 ASSERT(context.is_valid()); | 228 ASSERT(context.is_valid()); |
| 236 __ mov(SlotOperand(slot, context.reg()), value.reg()); | 229 __ mov(SlotOperand(slot, context.reg()), value.reg()); |
| 237 int offset = FixedArray::kHeaderSize + slot->index() * kPointerSize; | 230 int offset = FixedArray::kHeaderSize + slot->index() * kPointerSize; |
| 238 Result scratch = allocator_->Allocate(); | 231 Result scratch = allocator_->Allocate(); |
| 239 ASSERT(scratch.is_valid()); | 232 ASSERT(scratch.is_valid()); |
| 240 frame_->Spill(context.reg()); | 233 frame_->Spill(context.reg()); |
| 241 frame_->Spill(value.reg()); | 234 frame_->Spill(value.reg()); |
| 242 __ RecordWrite(context.reg(), offset, value.reg(), scratch.reg()); | 235 __ RecordWrite(context.reg(), offset, value.reg(), scratch.reg()); |
| 243 } | 236 } |
| 244 } | 237 } |
| 245 } | 238 } |
| 246 | 239 |
| 247 // Store the arguments object. This must happen after context | 240 // Store the arguments object. This must happen after context |
| 248 // initialization because the arguments object may be stored in | 241 // initialization because the arguments object may be stored in |
| 249 // the context. | 242 // the context. |
| 250 if (ArgumentsMode() != NO_ARGUMENTS_ALLOCATION) { | 243 if (ArgumentsMode() != NO_ARGUMENTS_ALLOCATION) { |
| 251 StoreArgumentsObject(true); | 244 StoreArgumentsObject(true); |
| 252 } | 245 } |
| 253 | 246 |
| 254 // Initialize ThisFunction reference if present. | 247 // Initialize ThisFunction reference if present. |
| 255 if (scope_->is_function_scope() && scope_->function() != NULL) { | 248 if (scope()->is_function_scope() && scope()->function() != NULL) { |
| 256 frame_->Push(Factory::the_hole_value()); | 249 frame_->Push(Factory::the_hole_value()); |
| 257 StoreToSlot(scope_->function()->slot(), NOT_CONST_INIT); | 250 StoreToSlot(scope()->function()->slot(), NOT_CONST_INIT); |
| 258 } | 251 } |
| 259 } else { | 252 } else { |
| 260 // When used as the secondary compiler for splitting, ebp, esi, | 253 // When used as the secondary compiler for splitting, ebp, esi, |
| 261 // and edi have been pushed on the stack. Adjust the virtual | 254 // and edi have been pushed on the stack. Adjust the virtual |
| 262 // frame to match this state. | 255 // frame to match this state. |
| 263 frame_->Adjust(3); | 256 frame_->Adjust(3); |
| 264 allocator_->Unuse(edi); | 257 allocator_->Unuse(edi); |
| 265 } | 258 } |
| 266 | 259 |
| 267 // Initialize the function return target after the locals are set | 260 // Initialize the function return target after the locals are set |
| 268 // up, because it needs the expected frame height from the frame. | 261 // up, because it needs the expected frame height from the frame. |
| 269 function_return_.set_direction(JumpTarget::BIDIRECTIONAL); | 262 function_return_.set_direction(JumpTarget::BIDIRECTIONAL); |
| 270 function_return_is_shadowed_ = false; | 263 function_return_is_shadowed_ = false; |
| 271 | 264 |
| 272 // Generate code to 'execute' declarations and initialize functions | 265 // Generate code to 'execute' declarations and initialize functions |
| 273 // (source elements). In case of an illegal redeclaration we need to | 266 // (source elements). In case of an illegal redeclaration we need to |
| 274 // handle that instead of processing the declarations. | 267 // handle that instead of processing the declarations. |
| 275 if (scope_->HasIllegalRedeclaration()) { | 268 if (scope()->HasIllegalRedeclaration()) { |
| 276 Comment cmnt(masm_, "[ illegal redeclarations"); | 269 Comment cmnt(masm_, "[ illegal redeclarations"); |
| 277 scope_->VisitIllegalRedeclaration(this); | 270 scope()->VisitIllegalRedeclaration(this); |
| 278 } else { | 271 } else { |
| 279 Comment cmnt(masm_, "[ declarations"); | 272 Comment cmnt(masm_, "[ declarations"); |
| 280 ProcessDeclarations(scope_->declarations()); | 273 ProcessDeclarations(scope()->declarations()); |
| 281 // Bail out if a stack-overflow exception occurred when processing | 274 // Bail out if a stack-overflow exception occurred when processing |
| 282 // declarations. | 275 // declarations. |
| 283 if (HasStackOverflow()) return; | 276 if (HasStackOverflow()) return; |
| 284 } | 277 } |
| 285 | 278 |
| 286 if (FLAG_trace) { | 279 if (FLAG_trace) { |
| 287 frame_->CallRuntime(Runtime::kTraceEnter, 0); | 280 frame_->CallRuntime(Runtime::kTraceEnter, 0); |
| 288 // Ignore the return value. | 281 // Ignore the return value. |
| 289 } | 282 } |
| 290 CheckStack(); | 283 CheckStack(); |
| 291 | 284 |
| 292 // Compile the body of the function in a vanilla state. Don't | 285 // Compile the body of the function in a vanilla state. Don't |
| 293 // bother compiling all the code if the scope has an illegal | 286 // bother compiling all the code if the scope has an illegal |
| 294 // redeclaration. | 287 // redeclaration. |
| 295 if (!scope_->HasIllegalRedeclaration()) { | 288 if (!scope()->HasIllegalRedeclaration()) { |
| 296 Comment cmnt(masm_, "[ function body"); | 289 Comment cmnt(masm_, "[ function body"); |
| 297 #ifdef DEBUG | 290 #ifdef DEBUG |
| 298 bool is_builtin = Bootstrapper::IsActive(); | 291 bool is_builtin = Bootstrapper::IsActive(); |
| 299 bool should_trace = | 292 bool should_trace = |
| 300 is_builtin ? FLAG_trace_builtin_calls : FLAG_trace_calls; | 293 is_builtin ? FLAG_trace_builtin_calls : FLAG_trace_calls; |
| 301 if (should_trace) { | 294 if (should_trace) { |
| 302 frame_->CallRuntime(Runtime::kDebugTrace, 0); | 295 frame_->CallRuntime(Runtime::kDebugTrace, 0); |
| 303 // Ignore the return value. | 296 // Ignore the return value. |
| 304 } | 297 } |
| 305 #endif | 298 #endif |
| 306 VisitStatements(body); | 299 VisitStatements(info->function()->body()); |
| 307 | 300 |
| 308 // Handle the return from the function. | 301 // Handle the return from the function. |
| 309 if (has_valid_frame()) { | 302 if (has_valid_frame()) { |
| 310 // If there is a valid frame, control flow can fall off the end of | 303 // If there is a valid frame, control flow can fall off the end of |
| 311 // the body. In that case there is an implicit return statement. | 304 // the body. In that case there is an implicit return statement. |
| 312 ASSERT(!function_return_is_shadowed_); | 305 ASSERT(!function_return_is_shadowed_); |
| 313 CodeForReturnPosition(fun); | 306 CodeForReturnPosition(info->function()); |
| 314 frame_->PrepareForReturn(); | 307 frame_->PrepareForReturn(); |
| 315 Result undefined(Factory::undefined_value()); | 308 Result undefined(Factory::undefined_value()); |
| 316 if (function_return_.is_bound()) { | 309 if (function_return_.is_bound()) { |
| 317 function_return_.Jump(&undefined); | 310 function_return_.Jump(&undefined); |
| 318 } else { | 311 } else { |
| 319 function_return_.Bind(&undefined); | 312 function_return_.Bind(&undefined); |
| 320 GenerateReturnSequence(&undefined); | 313 GenerateReturnSequence(&undefined); |
| 321 } | 314 } |
| 322 } else if (function_return_.is_linked()) { | 315 } else if (function_return_.is_linked()) { |
| 323 // If the return target has dangling jumps to it, then we have not | 316 // If the return target has dangling jumps to it, then we have not |
| (...skipping 22 matching lines...) Expand all Loading... |
| 346 if (!HasStackOverflow()) { | 339 if (!HasStackOverflow()) { |
| 347 HistogramTimerScope deferred_timer(&Counters::deferred_code_generation); | 340 HistogramTimerScope deferred_timer(&Counters::deferred_code_generation); |
| 348 JumpTarget::set_compiling_deferred_code(true); | 341 JumpTarget::set_compiling_deferred_code(true); |
| 349 ProcessDeferred(); | 342 ProcessDeferred(); |
| 350 JumpTarget::set_compiling_deferred_code(false); | 343 JumpTarget::set_compiling_deferred_code(false); |
| 351 } | 344 } |
| 352 | 345 |
| 353 // There is no need to delete the register allocator, it is a | 346 // There is no need to delete the register allocator, it is a |
| 354 // stack-allocated local. | 347 // stack-allocated local. |
| 355 allocator_ = NULL; | 348 allocator_ = NULL; |
| 356 scope_ = NULL; | |
| 357 } | 349 } |
| 358 | 350 |
| 359 | 351 |
| 360 Operand CodeGenerator::SlotOperand(Slot* slot, Register tmp) { | 352 Operand CodeGenerator::SlotOperand(Slot* slot, Register tmp) { |
| 361 // Currently, this assertion will fail if we try to assign to | 353 // Currently, this assertion will fail if we try to assign to |
| 362 // a constant variable that is constant because it is read-only | 354 // a constant variable that is constant because it is read-only |
| 363 // (such as the variable referring to a named function expression). | 355 // (such as the variable referring to a named function expression). |
| 364 // We need to implement assignments to read-only variables. | 356 // We need to implement assignments to read-only variables. |
| 365 // Ideally, we should do this during AST generation (by converting | 357 // Ideally, we should do this during AST generation (by converting |
| 366 // such assignments into expression statements); however, in general | 358 // such assignments into expression statements); however, in general |
| (...skipping 216 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 583 // For a variable that rewrites to a slot, we signal it is the immediate | 575 // For a variable that rewrites to a slot, we signal it is the immediate |
| 584 // subexpression of a typeof. | 576 // subexpression of a typeof. |
| 585 LoadFromSlotCheckForArguments(variable->slot(), INSIDE_TYPEOF); | 577 LoadFromSlotCheckForArguments(variable->slot(), INSIDE_TYPEOF); |
| 586 } else { | 578 } else { |
| 587 // Anything else can be handled normally. | 579 // Anything else can be handled normally. |
| 588 Load(expr); | 580 Load(expr); |
| 589 } | 581 } |
| 590 } | 582 } |
| 591 | 583 |
| 592 | 584 |
| 593 ArgumentsAllocationMode CodeGenerator::ArgumentsMode() const { | 585 ArgumentsAllocationMode CodeGenerator::ArgumentsMode() { |
| 594 if (scope_->arguments() == NULL) return NO_ARGUMENTS_ALLOCATION; | 586 if (scope()->arguments() == NULL) return NO_ARGUMENTS_ALLOCATION; |
| 595 ASSERT(scope_->arguments_shadow() != NULL); | 587 ASSERT(scope()->arguments_shadow() != NULL); |
| 596 // We don't want to do lazy arguments allocation for functions that | 588 // We don't want to do lazy arguments allocation for functions that |
| 597 // have heap-allocated contexts, because it interfers with the | 589 // have heap-allocated contexts, because it interfers with the |
| 598 // uninitialized const tracking in the context objects. | 590 // uninitialized const tracking in the context objects. |
| 599 return (scope_->num_heap_slots() > 0) | 591 return (scope()->num_heap_slots() > 0) |
| 600 ? EAGER_ARGUMENTS_ALLOCATION | 592 ? EAGER_ARGUMENTS_ALLOCATION |
| 601 : LAZY_ARGUMENTS_ALLOCATION; | 593 : LAZY_ARGUMENTS_ALLOCATION; |
| 602 } | 594 } |
| 603 | 595 |
| 604 | 596 |
| 605 Result CodeGenerator::StoreArgumentsObject(bool initial) { | 597 Result CodeGenerator::StoreArgumentsObject(bool initial) { |
| 606 ArgumentsAllocationMode mode = ArgumentsMode(); | 598 ArgumentsAllocationMode mode = ArgumentsMode(); |
| 607 ASSERT(mode != NO_ARGUMENTS_ALLOCATION); | 599 ASSERT(mode != NO_ARGUMENTS_ALLOCATION); |
| 608 | 600 |
| 609 Comment cmnt(masm_, "[ store arguments object"); | 601 Comment cmnt(masm_, "[ store arguments object"); |
| 610 if (mode == LAZY_ARGUMENTS_ALLOCATION && initial) { | 602 if (mode == LAZY_ARGUMENTS_ALLOCATION && initial) { |
| 611 // When using lazy arguments allocation, we store the hole value | 603 // When using lazy arguments allocation, we store the hole value |
| 612 // as a sentinel indicating that the arguments object hasn't been | 604 // as a sentinel indicating that the arguments object hasn't been |
| 613 // allocated yet. | 605 // allocated yet. |
| 614 frame_->Push(Factory::the_hole_value()); | 606 frame_->Push(Factory::the_hole_value()); |
| 615 } else { | 607 } else { |
| 616 ArgumentsAccessStub stub(ArgumentsAccessStub::NEW_OBJECT); | 608 ArgumentsAccessStub stub(ArgumentsAccessStub::NEW_OBJECT); |
| 617 frame_->PushFunction(); | 609 frame_->PushFunction(); |
| 618 frame_->PushReceiverSlotAddress(); | 610 frame_->PushReceiverSlotAddress(); |
| 619 frame_->Push(Smi::FromInt(scope_->num_parameters())); | 611 frame_->Push(Smi::FromInt(scope()->num_parameters())); |
| 620 Result result = frame_->CallStub(&stub, 3); | 612 Result result = frame_->CallStub(&stub, 3); |
| 621 frame_->Push(&result); | 613 frame_->Push(&result); |
| 622 } | 614 } |
| 623 | 615 |
| 624 Variable* arguments = scope_->arguments()->var(); | 616 Variable* arguments = scope()->arguments()->var(); |
| 625 Variable* shadow = scope_->arguments_shadow()->var(); | 617 Variable* shadow = scope()->arguments_shadow()->var(); |
| 626 ASSERT(arguments != NULL && arguments->slot() != NULL); | 618 ASSERT(arguments != NULL && arguments->slot() != NULL); |
| 627 ASSERT(shadow != NULL && shadow->slot() != NULL); | 619 ASSERT(shadow != NULL && shadow->slot() != NULL); |
| 628 JumpTarget done; | 620 JumpTarget done; |
| 629 bool skip_arguments = false; | 621 bool skip_arguments = false; |
| 630 if (mode == LAZY_ARGUMENTS_ALLOCATION && !initial) { | 622 if (mode == LAZY_ARGUMENTS_ALLOCATION && !initial) { |
| 631 // We have to skip storing into the arguments slot if it has already | 623 // We have to skip storing into the arguments slot if it has already |
| 632 // been written to. This can happen if the a function has a local | 624 // been written to. This can happen if the a function has a local |
| 633 // variable named 'arguments'. | 625 // variable named 'arguments'. |
| 634 LoadFromSlot(arguments->slot(), NOT_INSIDE_TYPEOF); | 626 LoadFromSlot(arguments->slot(), NOT_INSIDE_TYPEOF); |
| 635 Result probe = frame_->Pop(); | 627 Result probe = frame_->Pop(); |
| (...skipping 1701 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2337 Load(applicand); | 2329 Load(applicand); |
| 2338 Handle<String> name = Factory::LookupAsciiSymbol("apply"); | 2330 Handle<String> name = Factory::LookupAsciiSymbol("apply"); |
| 2339 frame()->Push(name); | 2331 frame()->Push(name); |
| 2340 Result answer = frame()->CallLoadIC(RelocInfo::CODE_TARGET); | 2332 Result answer = frame()->CallLoadIC(RelocInfo::CODE_TARGET); |
| 2341 __ nop(); | 2333 __ nop(); |
| 2342 frame()->Push(&answer); | 2334 frame()->Push(&answer); |
| 2343 | 2335 |
| 2344 // Load the receiver and the existing arguments object onto the | 2336 // Load the receiver and the existing arguments object onto the |
| 2345 // expression stack. Avoid allocating the arguments object here. | 2337 // expression stack. Avoid allocating the arguments object here. |
| 2346 Load(receiver); | 2338 Load(receiver); |
| 2347 LoadFromSlot(scope_->arguments()->var()->slot(), NOT_INSIDE_TYPEOF); | 2339 LoadFromSlot(scope()->arguments()->var()->slot(), NOT_INSIDE_TYPEOF); |
| 2348 | 2340 |
| 2349 // Emit the source position information after having loaded the | 2341 // Emit the source position information after having loaded the |
| 2350 // receiver and the arguments. | 2342 // receiver and the arguments. |
| 2351 CodeForSourcePosition(position); | 2343 CodeForSourcePosition(position); |
| 2352 // Contents of frame at this point: | 2344 // Contents of frame at this point: |
| 2353 // Frame[0]: arguments object of the current function or the hole. | 2345 // Frame[0]: arguments object of the current function or the hole. |
| 2354 // Frame[1]: receiver | 2346 // Frame[1]: receiver |
| 2355 // Frame[2]: applicand.apply | 2347 // Frame[2]: applicand.apply |
| 2356 // Frame[3]: applicand. | 2348 // Frame[3]: applicand. |
| 2357 | 2349 |
| (...skipping 59 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2417 // Copy the arguments to this function possibly from the | 2409 // Copy the arguments to this function possibly from the |
| 2418 // adaptor frame below it. | 2410 // adaptor frame below it. |
| 2419 Label invoke, adapted; | 2411 Label invoke, adapted; |
| 2420 __ mov(edx, Operand(ebp, StandardFrameConstants::kCallerFPOffset)); | 2412 __ mov(edx, Operand(ebp, StandardFrameConstants::kCallerFPOffset)); |
| 2421 __ mov(ecx, Operand(edx, StandardFrameConstants::kContextOffset)); | 2413 __ mov(ecx, Operand(edx, StandardFrameConstants::kContextOffset)); |
| 2422 __ cmp(Operand(ecx), | 2414 __ cmp(Operand(ecx), |
| 2423 Immediate(Smi::FromInt(StackFrame::ARGUMENTS_ADAPTOR))); | 2415 Immediate(Smi::FromInt(StackFrame::ARGUMENTS_ADAPTOR))); |
| 2424 __ j(equal, &adapted); | 2416 __ j(equal, &adapted); |
| 2425 | 2417 |
| 2426 // No arguments adaptor frame. Copy fixed number of arguments. | 2418 // No arguments adaptor frame. Copy fixed number of arguments. |
| 2427 __ mov(eax, Immediate(scope_->num_parameters())); | 2419 __ mov(eax, Immediate(scope()->num_parameters())); |
| 2428 for (int i = 0; i < scope_->num_parameters(); i++) { | 2420 for (int i = 0; i < scope()->num_parameters(); i++) { |
| 2429 __ push(frame_->ParameterAt(i)); | 2421 __ push(frame_->ParameterAt(i)); |
| 2430 } | 2422 } |
| 2431 __ jmp(&invoke); | 2423 __ jmp(&invoke); |
| 2432 | 2424 |
| 2433 // Arguments adaptor frame present. Copy arguments from there, but | 2425 // Arguments adaptor frame present. Copy arguments from there, but |
| 2434 // avoid copying too many arguments to avoid stack overflows. | 2426 // avoid copying too many arguments to avoid stack overflows. |
| 2435 __ bind(&adapted); | 2427 __ bind(&adapted); |
| 2436 static const uint32_t kArgumentsLimit = 1 * KB; | 2428 static const uint32_t kArgumentsLimit = 1 * KB; |
| 2437 __ mov(eax, Operand(edx, ArgumentsAdaptorFrameConstants::kLengthOffset)); | 2429 __ mov(eax, Operand(edx, ArgumentsAdaptorFrameConstants::kLengthOffset)); |
| 2438 __ SmiUntag(eax); | 2430 __ SmiUntag(eax); |
| (...skipping 385 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2824 } | 2816 } |
| 2825 return_value->ToRegister(eax); | 2817 return_value->ToRegister(eax); |
| 2826 | 2818 |
| 2827 // Add a label for checking the size of the code used for returning. | 2819 // Add a label for checking the size of the code used for returning. |
| 2828 Label check_exit_codesize; | 2820 Label check_exit_codesize; |
| 2829 masm_->bind(&check_exit_codesize); | 2821 masm_->bind(&check_exit_codesize); |
| 2830 | 2822 |
| 2831 // Leave the frame and return popping the arguments and the | 2823 // Leave the frame and return popping the arguments and the |
| 2832 // receiver. | 2824 // receiver. |
| 2833 frame_->Exit(); | 2825 frame_->Exit(); |
| 2834 masm_->ret((scope_->num_parameters() + 1) * kPointerSize); | 2826 masm_->ret((scope()->num_parameters() + 1) * kPointerSize); |
| 2835 DeleteFrame(); | 2827 DeleteFrame(); |
| 2836 | 2828 |
| 2837 #ifdef ENABLE_DEBUGGER_SUPPORT | 2829 #ifdef ENABLE_DEBUGGER_SUPPORT |
| 2838 // Check that the size of the code used for returning matches what is | 2830 // Check that the size of the code used for returning matches what is |
| 2839 // expected by the debugger. | 2831 // expected by the debugger. |
| 2840 ASSERT_EQ(Assembler::kJSReturnSequenceLength, | 2832 ASSERT_EQ(Assembler::kJSReturnSequenceLength, |
| 2841 masm_->SizeOfCodeGeneratedSince(&check_exit_codesize)); | 2833 masm_->SizeOfCodeGeneratedSince(&check_exit_codesize)); |
| 2842 #endif | 2834 #endif |
| 2843 } | 2835 } |
| 2844 | 2836 |
| (...skipping 1100 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 3945 frame_->Push(&result); | 3937 frame_->Push(&result); |
| 3946 } | 3938 } |
| 3947 } | 3939 } |
| 3948 | 3940 |
| 3949 | 3941 |
| 3950 void CodeGenerator::VisitFunctionLiteral(FunctionLiteral* node) { | 3942 void CodeGenerator::VisitFunctionLiteral(FunctionLiteral* node) { |
| 3951 Comment cmnt(masm_, "[ FunctionLiteral"); | 3943 Comment cmnt(masm_, "[ FunctionLiteral"); |
| 3952 | 3944 |
| 3953 // Build the function boilerplate and instantiate it. | 3945 // Build the function boilerplate and instantiate it. |
| 3954 Handle<JSFunction> boilerplate = | 3946 Handle<JSFunction> boilerplate = |
| 3955 Compiler::BuildBoilerplate(node, script_, this); | 3947 Compiler::BuildBoilerplate(node, script(), this); |
| 3956 // Check for stack-overflow exception. | 3948 // Check for stack-overflow exception. |
| 3957 if (HasStackOverflow()) return; | 3949 if (HasStackOverflow()) return; |
| 3958 InstantiateBoilerplate(boilerplate); | 3950 InstantiateBoilerplate(boilerplate); |
| 3959 } | 3951 } |
| 3960 | 3952 |
| 3961 | 3953 |
| 3962 void CodeGenerator::VisitFunctionBoilerplateLiteral( | 3954 void CodeGenerator::VisitFunctionBoilerplateLiteral( |
| 3963 FunctionBoilerplateLiteral* node) { | 3955 FunctionBoilerplateLiteral* node) { |
| 3964 Comment cmnt(masm_, "[ FunctionBoilerplateLiteral"); | 3956 Comment cmnt(masm_, "[ FunctionBoilerplateLiteral"); |
| 3965 InstantiateBoilerplate(node->boilerplate()); | 3957 InstantiateBoilerplate(node->boilerplate()); |
| (...skipping 1304 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 5270 Immediate(Smi::FromInt(StackFrame::CONSTRUCT))); | 5262 Immediate(Smi::FromInt(StackFrame::CONSTRUCT))); |
| 5271 fp.Unuse(); | 5263 fp.Unuse(); |
| 5272 destination()->Split(equal); | 5264 destination()->Split(equal); |
| 5273 } | 5265 } |
| 5274 | 5266 |
| 5275 | 5267 |
| 5276 void CodeGenerator::GenerateArgumentsLength(ZoneList<Expression*>* args) { | 5268 void CodeGenerator::GenerateArgumentsLength(ZoneList<Expression*>* args) { |
| 5277 ASSERT(args->length() == 0); | 5269 ASSERT(args->length() == 0); |
| 5278 // ArgumentsAccessStub takes the parameter count as an input argument | 5270 // ArgumentsAccessStub takes the parameter count as an input argument |
| 5279 // in register eax. Create a constant result for it. | 5271 // in register eax. Create a constant result for it. |
| 5280 Result count(Handle<Smi>(Smi::FromInt(scope_->num_parameters()))); | 5272 Result count(Handle<Smi>(Smi::FromInt(scope()->num_parameters()))); |
| 5281 // Call the shared stub to get to the arguments.length. | 5273 // Call the shared stub to get to the arguments.length. |
| 5282 ArgumentsAccessStub stub(ArgumentsAccessStub::READ_LENGTH); | 5274 ArgumentsAccessStub stub(ArgumentsAccessStub::READ_LENGTH); |
| 5283 Result result = frame_->CallStub(&stub, &count); | 5275 Result result = frame_->CallStub(&stub, &count); |
| 5284 frame_->Push(&result); | 5276 frame_->Push(&result); |
| 5285 } | 5277 } |
| 5286 | 5278 |
| 5287 | 5279 |
| 5288 void CodeGenerator::GenerateClassOf(ZoneList<Expression*>* args) { | 5280 void CodeGenerator::GenerateClassOf(ZoneList<Expression*>* args) { |
| 5289 ASSERT(args->length() == 1); | 5281 ASSERT(args->length() == 1); |
| 5290 JumpTarget leave, null, function, non_function_constructor; | 5282 JumpTarget leave, null, function, non_function_constructor; |
| (...skipping 126 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 5417 | 5409 |
| 5418 | 5410 |
| 5419 void CodeGenerator::GenerateArgumentsAccess(ZoneList<Expression*>* args) { | 5411 void CodeGenerator::GenerateArgumentsAccess(ZoneList<Expression*>* args) { |
| 5420 ASSERT(args->length() == 1); | 5412 ASSERT(args->length() == 1); |
| 5421 | 5413 |
| 5422 // ArgumentsAccessStub expects the key in edx and the formal | 5414 // ArgumentsAccessStub expects the key in edx and the formal |
| 5423 // parameter count in eax. | 5415 // parameter count in eax. |
| 5424 Load(args->at(0)); | 5416 Load(args->at(0)); |
| 5425 Result key = frame_->Pop(); | 5417 Result key = frame_->Pop(); |
| 5426 // Explicitly create a constant result. | 5418 // Explicitly create a constant result. |
| 5427 Result count(Handle<Smi>(Smi::FromInt(scope_->num_parameters()))); | 5419 Result count(Handle<Smi>(Smi::FromInt(scope()->num_parameters()))); |
| 5428 // Call the shared stub to get to arguments[key]. | 5420 // Call the shared stub to get to arguments[key]. |
| 5429 ArgumentsAccessStub stub(ArgumentsAccessStub::READ_ELEMENT); | 5421 ArgumentsAccessStub stub(ArgumentsAccessStub::READ_ELEMENT); |
| 5430 Result result = frame_->CallStub(&stub, &key, &count); | 5422 Result result = frame_->CallStub(&stub, &key, &count); |
| 5431 frame_->Push(&result); | 5423 frame_->Push(&result); |
| 5432 } | 5424 } |
| 5433 | 5425 |
| 5434 | 5426 |
| 5435 void CodeGenerator::GenerateObjectEquals(ZoneList<Expression*>* args) { | 5427 void CodeGenerator::GenerateObjectEquals(ZoneList<Expression*>* args) { |
| 5436 ASSERT(args->length() == 2); | 5428 ASSERT(args->length() == 2); |
| 5437 | 5429 |
| (...skipping 4664 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 10102 | 10094 |
| 10103 // Call the runtime; it returns -1 (less), 0 (equal), or 1 (greater) | 10095 // Call the runtime; it returns -1 (less), 0 (equal), or 1 (greater) |
| 10104 // tagged as a small integer. | 10096 // tagged as a small integer. |
| 10105 __ bind(&runtime); | 10097 __ bind(&runtime); |
| 10106 __ TailCallRuntime(ExternalReference(Runtime::kStringCompare), 2, 1); | 10098 __ TailCallRuntime(ExternalReference(Runtime::kStringCompare), 2, 1); |
| 10107 } | 10099 } |
| 10108 | 10100 |
| 10109 #undef __ | 10101 #undef __ |
| 10110 | 10102 |
| 10111 } } // namespace v8::internal | 10103 } } // namespace v8::internal |
| OLD | NEW |