| 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 424 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 435 if (!result_saved) __ push(eax); | 435 if (!result_saved) __ push(eax); |
| 436 break; | 436 break; |
| 437 } | 437 } |
| 438 } | 438 } |
| 439 | 439 |
| 440 | 440 |
| 441 void FastCodeGenerator::VisitAssignment(Assignment* expr) { | 441 void FastCodeGenerator::VisitAssignment(Assignment* expr) { |
| 442 Comment cmnt(masm_, "[ Assignment"); | 442 Comment cmnt(masm_, "[ Assignment"); |
| 443 ASSERT(expr->op() == Token::ASSIGN || expr->op() == Token::INIT_VAR); | 443 ASSERT(expr->op() == Token::ASSIGN || expr->op() == Token::INIT_VAR); |
| 444 | 444 |
| 445 // Left-hand side can only be a global or a (parameter or local) slot. | 445 // Record the source position for the assignment. |
| 446 SetSourcePosition(expr->position()); |
| 447 |
| 448 // Left-hand side can only be a property, a global or |
| 449 // a (parameter or local) slot. |
| 446 Variable* var = expr->target()->AsVariableProxy()->AsVariable(); | 450 Variable* var = expr->target()->AsVariableProxy()->AsVariable(); |
| 447 ASSERT(var != NULL); | |
| 448 ASSERT(var->is_global() || var->slot() != NULL); | |
| 449 | |
| 450 Expression* rhs = expr->value(); | 451 Expression* rhs = expr->value(); |
| 451 if (var->is_global()) { | 452 if (var == NULL) { |
| 453 // Assignment to a property. |
| 454 ASSERT(expr->target()->AsProperty() != NULL); |
| 455 Property* prop = expr->target()->AsProperty(); |
| 456 Visit(prop->obj()); |
| 457 Literal* literal_key = prop->key()->AsLiteral(); |
| 458 uint32_t dummy; |
| 459 if (literal_key != NULL && |
| 460 literal_key->handle()->IsSymbol() && |
| 461 !String::cast(*(literal_key->handle()))->AsArrayIndex(&dummy)) { |
| 462 // NAMED property assignment |
| 463 Visit(rhs); |
| 464 Move(eax, rhs->location()); |
| 465 __ mov(ecx, Immediate(literal_key->handle())); |
| 466 Handle<Code> ic(Builtins::builtin(Builtins::StoreIC_Initialize)); |
| 467 __ call(ic, RelocInfo::CODE_TARGET); |
| 468 __ nop(); |
| 469 } else { |
| 470 // KEYED property assignment |
| 471 Visit(prop->key()); |
| 472 Visit(rhs); |
| 473 Move(eax, rhs->location()); |
| 474 Handle<Code> ic(Builtins::builtin(Builtins::KeyedStoreIC_Initialize)); |
| 475 __ call(ic, RelocInfo::CODE_TARGET); |
| 476 __ nop(); |
| 477 // Drop key from the stack |
| 478 __ add(Operand(esp), Immediate(kPointerSize)); |
| 479 } |
| 480 // Overwrite the receiver on the stack with the result if needed. |
| 481 DropAndMove(expr->location(), eax); |
| 482 } else if (var->is_global()) { |
| 452 // Assignment to a global variable, use inline caching. Right-hand-side | 483 // Assignment to a global variable, use inline caching. Right-hand-side |
| 453 // value is passed in eax, variable name in ecx, and the global object | 484 // value is passed in eax, variable name in ecx, and the global object |
| 454 // on the stack. | 485 // on the stack. |
| 455 | 486 |
| 456 // Code for the right-hand-side expression depends on its type. | 487 // Code for the right-hand-side expression depends on its type. |
| 457 if (rhs->AsLiteral() != NULL) { | 488 if (rhs->AsLiteral() != NULL) { |
| 458 __ mov(eax, rhs->AsLiteral()->handle()); | 489 __ mov(eax, rhs->AsLiteral()->handle()); |
| 459 } else { | 490 } else { |
| 460 ASSERT(rhs->location().is_value()); | 491 ASSERT(rhs->location().is_value()); |
| 461 Visit(rhs); | 492 Visit(rhs); |
| 462 __ pop(eax); | 493 __ pop(eax); |
| 463 } | 494 } |
| 464 __ mov(ecx, var->name()); | 495 __ mov(ecx, var->name()); |
| 465 __ push(CodeGenerator::GlobalObject()); | 496 __ push(CodeGenerator::GlobalObject()); |
| 466 Handle<Code> ic(Builtins::builtin(Builtins::StoreIC_Initialize)); | 497 Handle<Code> ic(Builtins::builtin(Builtins::StoreIC_Initialize)); |
| 467 __ call(ic, RelocInfo::CODE_TARGET); | 498 __ call(ic, RelocInfo::CODE_TARGET); |
| 468 // Overwrite the global object on the stack with the result if needed. | 499 // Overwrite the global object on the stack with the result if needed. |
| 469 DropAndMove(expr->location(), eax); | 500 DropAndMove(expr->location(), eax); |
| 470 } else { | 501 } else { |
| 471 // Local or parameter assignment. | 502 // Local or parameter assignment. |
| 503 ASSERT(var->slot() != NULL); |
| 472 | 504 |
| 473 // Code for the right-hand side expression depends on its type. | 505 // Code for the right-hand side expression depends on its type. |
| 474 if (rhs->AsLiteral() != NULL) { | 506 if (rhs->AsLiteral() != NULL) { |
| 475 // Two cases: 'temp <- (var = constant)', or 'var = constant' with a | 507 // Two cases: 'temp <- (var = constant)', or 'var = constant' with a |
| 476 // discarded result. Always perform the assignment. | 508 // discarded result. Always perform the assignment. |
| 477 __ mov(eax, rhs->AsLiteral()->handle()); | 509 __ mov(eax, rhs->AsLiteral()->handle()); |
| 478 __ mov(Operand(ebp, SlotOffset(var->slot())), eax); | 510 __ mov(Operand(ebp, SlotOffset(var->slot())), eax); |
| 479 Move(expr->location(), eax); | 511 Move(expr->location(), eax); |
| 480 } else { | 512 } else { |
| 481 ASSERT(rhs->location().is_value()); | 513 ASSERT(rhs->location().is_value()); |
| (...skipping 20 matching lines...) Expand all Loading... |
| 502 void FastCodeGenerator::VisitProperty(Property* expr) { | 534 void FastCodeGenerator::VisitProperty(Property* expr) { |
| 503 Comment cmnt(masm_, "[ Property"); | 535 Comment cmnt(masm_, "[ Property"); |
| 504 Expression* key = expr->key(); | 536 Expression* key = expr->key(); |
| 505 uint32_t dummy; | 537 uint32_t dummy; |
| 506 | 538 |
| 507 // Record the source position for the property load. | 539 // Record the source position for the property load. |
| 508 SetSourcePosition(expr->position()); | 540 SetSourcePosition(expr->position()); |
| 509 | 541 |
| 510 // Evaluate receiver. | 542 // Evaluate receiver. |
| 511 Visit(expr->obj()); | 543 Visit(expr->obj()); |
| 512 | |
| 513 if (key->AsLiteral() != NULL && key->AsLiteral()->handle()->IsSymbol() && | 544 if (key->AsLiteral() != NULL && key->AsLiteral()->handle()->IsSymbol() && |
| 514 !String::cast(*(key->AsLiteral()->handle()))->AsArrayIndex(&dummy)) { | 545 !String::cast(*(key->AsLiteral()->handle()))->AsArrayIndex(&dummy)) { |
| 515 // Do a NAMED property load. | 546 // Do a NAMED property load. |
| 516 // The IC expects the property name in ecx and the receiver on the stack. | 547 // The IC expects the property name in ecx and the receiver on the stack. |
| 517 __ mov(ecx, Immediate(key->AsLiteral()->handle())); | 548 __ mov(ecx, Immediate(key->AsLiteral()->handle())); |
| 518 Handle<Code> ic(Builtins::builtin(Builtins::LoadIC_Initialize)); | 549 Handle<Code> ic(Builtins::builtin(Builtins::LoadIC_Initialize)); |
| 519 __ call(ic, RelocInfo::CODE_TARGET); | 550 __ call(ic, RelocInfo::CODE_TARGET); |
| 520 // By emitting a nop we make sure that we do not have a test eax | 551 // By emitting a nop we make sure that we do not have a test eax |
| 521 // instruction after the call it is treated specially by the LoadIC code. | 552 // instruction after the call it is treated specially by the LoadIC code. |
| 522 __ nop(); | 553 __ nop(); |
| 523 } else { | 554 } else { |
| 524 // Do a KEYED property load. | 555 // Do a KEYED property load. |
| 525 Visit(expr->key()); | 556 Visit(expr->key()); |
| 526 Handle<Code> ic(Builtins::builtin(Builtins::KeyedLoadIC_Initialize)); | 557 Handle<Code> ic(Builtins::builtin(Builtins::KeyedLoadIC_Initialize)); |
| 527 __ call(ic, RelocInfo::CODE_TARGET); | 558 __ call(ic, RelocInfo::CODE_TARGET); |
| 528 // By emitting a nop we make sure that we do not have a "test eax,..." | 559 // By emitting a nop we make sure that we do not have a "test eax,..." |
| 529 // instruction after the call it is treated specially by the LoadIC code. | 560 // instruction after the call it is treated specially by the LoadIC code. |
| 530 __ nop(); | 561 __ nop(); |
| 531 // Drop key left on the stack by IC. | 562 // Drop key left on the stack by IC. |
| 532 __ add(Operand(esp), Immediate(kPointerSize)); | 563 __ add(Operand(esp), Immediate(kPointerSize)); |
| 533 } | 564 } |
| 534 switch (expr->location().type()) { | 565 DropAndMove(expr->location(), eax); |
| 535 case Location::kUninitialized: | |
| 536 UNREACHABLE(); | |
| 537 case Location::kValue: | |
| 538 __ mov(Operand(esp, 0), eax); | |
| 539 break; | |
| 540 case Location::kEffect: | |
| 541 __ add(Operand(esp), Immediate(kPointerSize)); | |
| 542 break; | |
| 543 } | |
| 544 } | 566 } |
| 545 | 567 |
| 546 | 568 |
| 547 void FastCodeGenerator::VisitCall(Call* expr) { | 569 void FastCodeGenerator::VisitCall(Call* expr) { |
| 548 Expression* fun = expr->expression(); | 570 Expression* fun = expr->expression(); |
| 549 ZoneList<Expression*>* args = expr->arguments(); | 571 ZoneList<Expression*>* args = expr->arguments(); |
| 550 Variable* var = fun->AsVariableProxy()->AsVariable(); | 572 Variable* var = fun->AsVariableProxy()->AsVariable(); |
| 551 ASSERT(var != NULL && !var->is_this() && var->is_global()); | 573 ASSERT(var != NULL && !var->is_this() && var->is_global()); |
| 552 ASSERT(!var->is_possibly_eval()); | 574 ASSERT(!var->is_possibly_eval()); |
| 553 | 575 |
| (...skipping 200 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 754 } | 776 } |
| 755 // Save or discard the right-hand value as needed. | 777 // Save or discard the right-hand value as needed. |
| 756 Visit(right); | 778 Visit(right); |
| 757 ASSERT_EQ(destination.type(), right->location().type()); | 779 ASSERT_EQ(destination.type(), right->location().type()); |
| 758 | 780 |
| 759 __ bind(&done); | 781 __ bind(&done); |
| 760 } | 782 } |
| 761 | 783 |
| 762 | 784 |
| 763 } } // namespace v8::internal | 785 } } // namespace v8::internal |
| OLD | NEW |