OLD | NEW |
1 // Copyright 2009 the V8 project authors. All rights reserved. | 1 // Copyright 2009 the V8 project authors. All rights reserved. |
2 // Redistribution and use in source and binary forms, with or without | 2 // Redistribution and use in source and binary forms, with or without |
3 // modification, are permitted provided that the following conditions are | 3 // modification, are permitted provided that the following conditions are |
4 // met: | 4 // met: |
5 // | 5 // |
6 // * Redistributions of source code must retain the above copyright | 6 // * Redistributions of source code must retain the above copyright |
7 // notice, this list of conditions and the following disclaimer. | 7 // notice, this list of conditions and the following disclaimer. |
8 // * Redistributions in binary form must reproduce the above | 8 // * Redistributions in binary form must reproduce the above |
9 // copyright notice, this list of conditions and the following | 9 // copyright notice, this list of conditions and the following |
10 // disclaimer in the documentation and/or other materials provided | 10 // disclaimer in the documentation and/or other materials provided |
(...skipping 394 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
405 __ j(not_zero, true_label); | 405 __ j(not_zero, true_label); |
406 __ jmp(false_label); | 406 __ jmp(false_label); |
407 } | 407 } |
408 | 408 |
409 | 409 |
410 void FastCodeGenerator::VisitDeclaration(Declaration* decl) { | 410 void FastCodeGenerator::VisitDeclaration(Declaration* decl) { |
411 Comment cmnt(masm_, "[ Declaration"); | 411 Comment cmnt(masm_, "[ Declaration"); |
412 Variable* var = decl->proxy()->var(); | 412 Variable* var = decl->proxy()->var(); |
413 ASSERT(var != NULL); // Must have been resolved. | 413 ASSERT(var != NULL); // Must have been resolved. |
414 Slot* slot = var->slot(); | 414 Slot* slot = var->slot(); |
415 ASSERT(slot != NULL); // No global declarations here. | 415 Property* prop = var->AsProperty(); |
416 | 416 |
417 // We have 3 cases for slots: LOOKUP, LOCAL, CONTEXT. | 417 if (slot != NULL) { |
418 switch (slot->type()) { | 418 switch (slot->type()) { |
419 case Slot::LOOKUP: { | 419 case Slot::PARAMETER: // Fall through. |
420 __ push(esi); | 420 case Slot::LOCAL: |
421 __ push(Immediate(var->name())); | 421 if (decl->mode() == Variable::CONST) { |
422 // Declaration nodes are always introduced in one of two modes. | 422 __ mov(Operand(ebp, SlotOffset(var->slot())), |
423 ASSERT(decl->mode() == Variable::VAR || decl->mode() == Variable::CONST); | 423 Immediate(Factory::the_hole_value())); |
424 PropertyAttributes attr = | 424 } else if (decl->fun() != NULL) { |
425 (decl->mode() == Variable::VAR) ? NONE : READ_ONLY; | 425 Visit(decl->fun()); |
426 __ push(Immediate(Smi::FromInt(attr))); | 426 __ pop(Operand(ebp, SlotOffset(var->slot()))); |
427 // Push initial value, if any. | 427 } |
428 // Note: For variables we must not push an initial value (such as | 428 break; |
429 // 'undefined') because we may have a (legal) redeclaration and we | 429 |
430 // must not destroy the current value. | 430 case Slot::CONTEXT: |
431 if (decl->mode() == Variable::CONST) { | 431 // The variable in the decl always resides in the current context. |
432 __ push(Immediate(Factory::the_hole_value())); | 432 ASSERT_EQ(0, function_->scope()->ContextChainLength(var->scope())); |
433 } else if (decl->fun() != NULL) { | |
434 Visit(decl->fun()); | |
435 } else { | |
436 __ push(Immediate(Smi::FromInt(0))); // No initial value! | |
437 } | |
438 __ CallRuntime(Runtime::kDeclareContextSlot, 4); | |
439 break; | |
440 } | |
441 case Slot::LOCAL: | |
442 if (decl->mode() == Variable::CONST) { | |
443 __ mov(Operand(ebp, SlotOffset(var->slot())), | |
444 Immediate(Factory::the_hole_value())); | |
445 } else if (decl->fun() != NULL) { | |
446 Visit(decl->fun()); | |
447 __ pop(Operand(ebp, SlotOffset(var->slot()))); | |
448 } | |
449 break; | |
450 case Slot::CONTEXT: | |
451 // The variable in the decl always resides in the current context. | |
452 ASSERT(function_->scope()->ContextChainLength(slot->var()->scope()) == 0); | |
453 if (decl->mode() == Variable::CONST) { | |
454 __ mov(eax, Immediate(Factory::the_hole_value())); | |
455 if (FLAG_debug_code) { | 433 if (FLAG_debug_code) { |
456 // Check if we have the correct context pointer. | 434 // Check if we have the correct context pointer. |
457 __ mov(ebx, | 435 __ mov(ebx, |
458 CodeGenerator::ContextOperand(esi, Context::FCONTEXT_INDEX)); | 436 CodeGenerator::ContextOperand(esi, Context::FCONTEXT_INDEX)); |
459 __ cmp(ebx, Operand(esi)); | 437 __ cmp(ebx, Operand(esi)); |
460 __ Check(equal, "Unexpected declaration in current context."); | 438 __ Check(equal, "Unexpected declaration in current context."); |
461 } | 439 } |
462 __ mov(CodeGenerator::ContextOperand(esi, slot->index()), eax); | 440 if (decl->mode() == Variable::CONST) { |
463 // No write barrier since the_hole_value is in old space. | 441 __ mov(eax, Immediate(Factory::the_hole_value())); |
464 ASSERT(!Heap::InNewSpace(*Factory::the_hole_value())); | 442 __ mov(CodeGenerator::ContextOperand(esi, slot->index()), eax); |
465 } else if (decl->fun() != NULL) { | 443 // No write barrier since the hole value is in old space. |
| 444 } else if (decl->fun() != NULL) { |
| 445 Visit(decl->fun()); |
| 446 __ pop(eax); |
| 447 __ mov(CodeGenerator::ContextOperand(esi, slot->index()), eax); |
| 448 int offset = Context::SlotOffset(slot->index()); |
| 449 __ RecordWrite(esi, offset, eax, ecx); |
| 450 } |
| 451 break; |
| 452 |
| 453 case Slot::LOOKUP: { |
| 454 __ push(esi); |
| 455 __ push(Immediate(var->name())); |
| 456 // Declaration nodes are always introduced in one of two modes. |
| 457 ASSERT(decl->mode() == Variable::VAR || |
| 458 decl->mode() == Variable::CONST); |
| 459 PropertyAttributes attr = |
| 460 (decl->mode() == Variable::VAR) ? NONE : READ_ONLY; |
| 461 __ push(Immediate(Smi::FromInt(attr))); |
| 462 // Push initial value, if any. |
| 463 // Note: For variables we must not push an initial value (such as |
| 464 // 'undefined') because we may have a (legal) redeclaration and we |
| 465 // must not destroy the current value. |
| 466 if (decl->mode() == Variable::CONST) { |
| 467 __ push(Immediate(Factory::the_hole_value())); |
| 468 } else if (decl->fun() != NULL) { |
| 469 Visit(decl->fun()); |
| 470 } else { |
| 471 __ push(Immediate(Smi::FromInt(0))); // No initial value! |
| 472 } |
| 473 __ CallRuntime(Runtime::kDeclareContextSlot, 4); |
| 474 break; |
| 475 } |
| 476 } |
| 477 |
| 478 } else if (prop != NULL) { |
| 479 if (decl->fun() != NULL || decl->mode() == Variable::CONST) { |
| 480 // We are declaring a function or constant that rewrites to a |
| 481 // property. Use (keyed) IC to set the initial value. |
| 482 ASSERT_EQ(Expression::kValue, prop->obj()->context()); |
| 483 Visit(prop->obj()); |
| 484 ASSERT_EQ(Expression::kValue, prop->key()->context()); |
| 485 Visit(prop->key()); |
| 486 |
| 487 if (decl->fun() != NULL) { |
| 488 ASSERT_EQ(Expression::kValue, decl->fun()->context()); |
466 Visit(decl->fun()); | 489 Visit(decl->fun()); |
467 __ pop(eax); | 490 __ pop(eax); |
468 if (FLAG_debug_code) { | 491 } else { |
469 // Check if we have the correct context pointer. | 492 __ Set(eax, Immediate(Factory::the_hole_value())); |
470 __ mov(ebx, | |
471 CodeGenerator::ContextOperand(esi, Context::FCONTEXT_INDEX)); | |
472 __ cmp(ebx, Operand(esi)); | |
473 __ Check(equal, "Unexpected declaration in current context."); | |
474 } | |
475 __ mov(CodeGenerator::ContextOperand(esi, slot->index()), eax); | |
476 int offset = Context::SlotOffset(slot->index()); | |
477 __ RecordWrite(esi, offset, eax, ecx); | |
478 } | 493 } |
479 break; | 494 |
480 default: | 495 Handle<Code> ic(Builtins::builtin(Builtins::KeyedStoreIC_Initialize)); |
481 UNREACHABLE(); | 496 __ call(ic, RelocInfo::CODE_TARGET); |
| 497 // Absence of a test eax instruction following the call |
| 498 // indicates that none of the load was inlined. |
| 499 |
| 500 // Value in eax is ignored (declarations are statements). Receiver |
| 501 // and key on stack are discarded. |
| 502 __ add(Operand(esp), Immediate(2 * kPointerSize)); |
| 503 } |
482 } | 504 } |
483 } | 505 } |
484 | 506 |
485 | 507 |
486 void FastCodeGenerator::DeclareGlobals(Handle<FixedArray> pairs) { | 508 void FastCodeGenerator::DeclareGlobals(Handle<FixedArray> pairs) { |
487 // Call the runtime to declare the globals. | 509 // Call the runtime to declare the globals. |
488 __ push(esi); // The context is the first argument. | 510 __ push(esi); // The context is the first argument. |
489 __ push(Immediate(pairs)); | 511 __ push(Immediate(pairs)); |
490 __ push(Immediate(Smi::FromInt(is_eval_ ? 1 : 0))); | 512 __ push(Immediate(Smi::FromInt(is_eval_ ? 1 : 0))); |
491 __ CallRuntime(Runtime::kDeclareGlobals, 3); | 513 __ CallRuntime(Runtime::kDeclareGlobals, 3); |
(...skipping 1190 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1682 true_label_ = saved_true; | 1704 true_label_ = saved_true; |
1683 false_label_ = saved_false; | 1705 false_label_ = saved_false; |
1684 // Convert current context to test context: End post-test code. | 1706 // Convert current context to test context: End post-test code. |
1685 } | 1707 } |
1686 | 1708 |
1687 | 1709 |
1688 #undef __ | 1710 #undef __ |
1689 | 1711 |
1690 | 1712 |
1691 } } // namespace v8::internal | 1713 } } // namespace v8::internal |
OLD | NEW |