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 |