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 260 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
271 | 271 |
272 __ movq(kScratchRegister, pairs, RelocInfo::EMBEDDED_OBJECT); | 272 __ movq(kScratchRegister, pairs, RelocInfo::EMBEDDED_OBJECT); |
273 frame_->EmitPush(rsi); // The context is the first argument. | 273 frame_->EmitPush(rsi); // The context is the first argument. |
274 frame_->EmitPush(kScratchRegister); | 274 frame_->EmitPush(kScratchRegister); |
275 frame_->EmitPush(Smi::FromInt(is_eval() ? 1 : 0)); | 275 frame_->EmitPush(Smi::FromInt(is_eval() ? 1 : 0)); |
276 Result ignored = frame_->CallRuntime(Runtime::kDeclareGlobals, 3); | 276 Result ignored = frame_->CallRuntime(Runtime::kDeclareGlobals, 3); |
277 // Return value is ignored. | 277 // Return value is ignored. |
278 } | 278 } |
279 | 279 |
280 | 280 |
281 void CodeGenerator::GenCode(FunctionLiteral* function, CompilationInfo* info) { | 281 void CodeGenerator::Generate(FunctionLiteral* function, |
| 282 Mode mode, |
| 283 CompilationInfo* info) { |
282 // Record the position for debugging purposes. | 284 // Record the position for debugging purposes. |
283 CodeForFunctionPosition(function); | 285 CodeForFunctionPosition(function); |
284 ZoneList<Statement*>* body = function->body(); | 286 ZoneList<Statement*>* body = function->body(); |
285 | 287 |
286 // Initialize state. | 288 // Initialize state. |
287 ASSERT(scope_ == NULL); | 289 ASSERT(scope_ == NULL); |
288 scope_ = function->scope(); | 290 scope_ = function->scope(); |
289 ASSERT(allocator_ == NULL); | 291 ASSERT(allocator_ == NULL); |
290 RegisterAllocator register_allocator(this); | 292 RegisterAllocator register_allocator(this); |
291 allocator_ = ®ister_allocator; | 293 allocator_ = ®ister_allocator; |
(...skipping 19 matching lines...) Expand all Loading... |
311 HistogramTimerScope codegen_timer(&Counters::code_generation); | 313 HistogramTimerScope codegen_timer(&Counters::code_generation); |
312 CodeGenState state(this); | 314 CodeGenState state(this); |
313 | 315 |
314 // Entry: | 316 // Entry: |
315 // Stack: receiver, arguments, return address. | 317 // Stack: receiver, arguments, return address. |
316 // rbp: caller's frame pointer | 318 // rbp: caller's frame pointer |
317 // rsp: stack pointer | 319 // rsp: stack pointer |
318 // rdi: called JS function | 320 // rdi: called JS function |
319 // rsi: callee's context | 321 // rsi: callee's context |
320 allocator_->Initialize(); | 322 allocator_->Initialize(); |
321 frame_->Enter(); | |
322 | 323 |
323 // Allocate space for locals and initialize them. | 324 if (mode == PRIMARY) { |
324 frame_->AllocateStackSlots(); | 325 frame_->Enter(); |
| 326 |
| 327 // Allocate space for locals and initialize them. |
| 328 frame_->AllocateStackSlots(); |
| 329 |
| 330 // Allocate the local context if needed. |
| 331 int heap_slots = scope_->num_heap_slots(); |
| 332 if (heap_slots > 0) { |
| 333 Comment cmnt(masm_, "[ allocate local context"); |
| 334 // Allocate local context. |
| 335 // Get outer context and create a new context based on it. |
| 336 frame_->PushFunction(); |
| 337 Result context; |
| 338 if (heap_slots <= FastNewContextStub::kMaximumSlots) { |
| 339 FastNewContextStub stub(heap_slots); |
| 340 context = frame_->CallStub(&stub, 1); |
| 341 } else { |
| 342 context = frame_->CallRuntime(Runtime::kNewContext, 1); |
| 343 } |
| 344 |
| 345 // Update context local. |
| 346 frame_->SaveContextRegister(); |
| 347 |
| 348 // Verify that the runtime call result and rsi agree. |
| 349 if (FLAG_debug_code) { |
| 350 __ cmpq(context.reg(), rsi); |
| 351 __ Assert(equal, "Runtime::NewContext should end up in rsi"); |
| 352 } |
| 353 } |
| 354 |
| 355 // TODO(1241774): Improve this code: |
| 356 // 1) only needed if we have a context |
| 357 // 2) no need to recompute context ptr every single time |
| 358 // 3) don't copy parameter operand code from SlotOperand! |
| 359 { |
| 360 Comment cmnt2(masm_, "[ copy context parameters into .context"); |
| 361 |
| 362 // Note that iteration order is relevant here! If we have the same |
| 363 // parameter twice (e.g., function (x, y, x)), and that parameter |
| 364 // needs to be copied into the context, it must be the last argument |
| 365 // passed to the parameter that needs to be copied. This is a rare |
| 366 // case so we don't check for it, instead we rely on the copying |
| 367 // order: such a parameter is copied repeatedly into the same |
| 368 // context location and thus the last value is what is seen inside |
| 369 // the function. |
| 370 for (int i = 0; i < scope_->num_parameters(); i++) { |
| 371 Variable* par = scope_->parameter(i); |
| 372 Slot* slot = par->slot(); |
| 373 if (slot != NULL && slot->type() == Slot::CONTEXT) { |
| 374 // The use of SlotOperand below is safe in unspilled code |
| 375 // because the slot is guaranteed to be a context slot. |
| 376 // |
| 377 // There are no parameters in the global scope. |
| 378 ASSERT(!scope_->is_global_scope()); |
| 379 frame_->PushParameterAt(i); |
| 380 Result value = frame_->Pop(); |
| 381 value.ToRegister(); |
| 382 |
| 383 // SlotOperand loads context.reg() with the context object |
| 384 // stored to, used below in RecordWrite. |
| 385 Result context = allocator_->Allocate(); |
| 386 ASSERT(context.is_valid()); |
| 387 __ movq(SlotOperand(slot, context.reg()), value.reg()); |
| 388 int offset = FixedArray::kHeaderSize + slot->index() * kPointerSize; |
| 389 Result scratch = allocator_->Allocate(); |
| 390 ASSERT(scratch.is_valid()); |
| 391 frame_->Spill(context.reg()); |
| 392 frame_->Spill(value.reg()); |
| 393 __ RecordWrite(context.reg(), offset, value.reg(), scratch.reg()); |
| 394 } |
| 395 } |
| 396 } |
| 397 |
| 398 // Store the arguments object. This must happen after context |
| 399 // initialization because the arguments object may be stored in |
| 400 // the context. |
| 401 if (ArgumentsMode() != NO_ARGUMENTS_ALLOCATION) { |
| 402 StoreArgumentsObject(true); |
| 403 } |
| 404 |
| 405 // Initialize ThisFunction reference if present. |
| 406 if (scope_->is_function_scope() && scope_->function() != NULL) { |
| 407 frame_->Push(Factory::the_hole_value()); |
| 408 StoreToSlot(scope_->function()->slot(), NOT_CONST_INIT); |
| 409 } |
| 410 } else { |
| 411 // When used as the secondary compiler for splitting, rbp, rsi, |
| 412 // and rdi have been pushed on the stack. Adjust the virtual |
| 413 // frame to match this state. |
| 414 frame_->Adjust(3); |
| 415 allocator_->Unuse(rdi); |
| 416 } |
| 417 |
325 // Initialize the function return target after the locals are set | 418 // Initialize the function return target after the locals are set |
326 // up, because it needs the expected frame height from the frame. | 419 // up, because it needs the expected frame height from the frame. |
327 function_return_.set_direction(JumpTarget::BIDIRECTIONAL); | 420 function_return_.set_direction(JumpTarget::BIDIRECTIONAL); |
328 function_return_is_shadowed_ = false; | 421 function_return_is_shadowed_ = false; |
329 | 422 |
330 // Allocate the local context if needed. | |
331 int heap_slots = scope_->num_heap_slots(); | |
332 if (heap_slots > 0) { | |
333 Comment cmnt(masm_, "[ allocate local context"); | |
334 // Allocate local context. | |
335 // Get outer context and create a new context based on it. | |
336 frame_->PushFunction(); | |
337 Result context; | |
338 if (heap_slots <= FastNewContextStub::kMaximumSlots) { | |
339 FastNewContextStub stub(heap_slots); | |
340 context = frame_->CallStub(&stub, 1); | |
341 } else { | |
342 context = frame_->CallRuntime(Runtime::kNewContext, 1); | |
343 } | |
344 | |
345 // Update context local. | |
346 frame_->SaveContextRegister(); | |
347 | |
348 // Verify that the runtime call result and rsi agree. | |
349 if (FLAG_debug_code) { | |
350 __ cmpq(context.reg(), rsi); | |
351 __ Assert(equal, "Runtime::NewContext should end up in rsi"); | |
352 } | |
353 } | |
354 | |
355 // TODO(1241774): Improve this code: | |
356 // 1) only needed if we have a context | |
357 // 2) no need to recompute context ptr every single time | |
358 // 3) don't copy parameter operand code from SlotOperand! | |
359 { | |
360 Comment cmnt2(masm_, "[ copy context parameters into .context"); | |
361 | |
362 // Note that iteration order is relevant here! If we have the same | |
363 // parameter twice (e.g., function (x, y, x)), and that parameter | |
364 // needs to be copied into the context, it must be the last argument | |
365 // passed to the parameter that needs to be copied. This is a rare | |
366 // case so we don't check for it, instead we rely on the copying | |
367 // order: such a parameter is copied repeatedly into the same | |
368 // context location and thus the last value is what is seen inside | |
369 // the function. | |
370 for (int i = 0; i < scope_->num_parameters(); i++) { | |
371 Variable* par = scope_->parameter(i); | |
372 Slot* slot = par->slot(); | |
373 if (slot != NULL && slot->type() == Slot::CONTEXT) { | |
374 // The use of SlotOperand below is safe in unspilled code | |
375 // because the slot is guaranteed to be a context slot. | |
376 // | |
377 // There are no parameters in the global scope. | |
378 ASSERT(!scope_->is_global_scope()); | |
379 frame_->PushParameterAt(i); | |
380 Result value = frame_->Pop(); | |
381 value.ToRegister(); | |
382 | |
383 // SlotOperand loads context.reg() with the context object | |
384 // stored to, used below in RecordWrite. | |
385 Result context = allocator_->Allocate(); | |
386 ASSERT(context.is_valid()); | |
387 __ movq(SlotOperand(slot, context.reg()), value.reg()); | |
388 int offset = FixedArray::kHeaderSize + slot->index() * kPointerSize; | |
389 Result scratch = allocator_->Allocate(); | |
390 ASSERT(scratch.is_valid()); | |
391 frame_->Spill(context.reg()); | |
392 frame_->Spill(value.reg()); | |
393 __ RecordWrite(context.reg(), offset, value.reg(), scratch.reg()); | |
394 } | |
395 } | |
396 } | |
397 | |
398 // Store the arguments object. This must happen after context | |
399 // initialization because the arguments object may be stored in | |
400 // the context. | |
401 if (ArgumentsMode() != NO_ARGUMENTS_ALLOCATION) { | |
402 StoreArgumentsObject(true); | |
403 } | |
404 | |
405 // Initialize ThisFunction reference if present. | |
406 if (scope_->is_function_scope() && scope_->function() != NULL) { | |
407 frame_->Push(Factory::the_hole_value()); | |
408 StoreToSlot(scope_->function()->slot(), NOT_CONST_INIT); | |
409 } | |
410 | |
411 // Generate code to 'execute' declarations and initialize functions | 423 // Generate code to 'execute' declarations and initialize functions |
412 // (source elements). In case of an illegal redeclaration we need to | 424 // (source elements). In case of an illegal redeclaration we need to |
413 // handle that instead of processing the declarations. | 425 // handle that instead of processing the declarations. |
414 if (scope_->HasIllegalRedeclaration()) { | 426 if (scope_->HasIllegalRedeclaration()) { |
415 Comment cmnt(masm_, "[ illegal redeclarations"); | 427 Comment cmnt(masm_, "[ illegal redeclarations"); |
416 scope_->VisitIllegalRedeclaration(this); | 428 scope_->VisitIllegalRedeclaration(this); |
417 } else { | 429 } else { |
418 Comment cmnt(masm_, "[ declarations"); | 430 Comment cmnt(masm_, "[ declarations"); |
419 ProcessDeclarations(scope_->declarations()); | 431 ProcessDeclarations(scope_->declarations()); |
420 // Bail out if a stack-overflow exception occurred when processing | 432 // Bail out if a stack-overflow exception occurred when processing |
(...skipping 8765 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
9186 // Call the function from C++. | 9198 // Call the function from C++. |
9187 return FUNCTION_CAST<ModuloFunction>(buffer); | 9199 return FUNCTION_CAST<ModuloFunction>(buffer); |
9188 } | 9200 } |
9189 | 9201 |
9190 #endif | 9202 #endif |
9191 | 9203 |
9192 | 9204 |
9193 #undef __ | 9205 #undef __ |
9194 | 9206 |
9195 } } // namespace v8::internal | 9207 } } // namespace v8::internal |
OLD | NEW |