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 275 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
286 Visit(expr->value()); | 286 Visit(expr->value()); |
287 } | 287 } |
288 | 288 |
289 | 289 |
290 void FastCodeGenSyntaxChecker::VisitThrow(Throw* expr) { | 290 void FastCodeGenSyntaxChecker::VisitThrow(Throw* expr) { |
291 BAILOUT("Throw"); | 291 BAILOUT("Throw"); |
292 } | 292 } |
293 | 293 |
294 | 294 |
295 void FastCodeGenSyntaxChecker::VisitProperty(Property* expr) { | 295 void FastCodeGenSyntaxChecker::VisitProperty(Property* expr) { |
296 BAILOUT("Property"); | 296 // We support named this property references. |
| 297 VariableProxy* proxy = expr->obj()->AsVariableProxy(); |
| 298 if (proxy == NULL || !proxy->var()->is_this()) { |
| 299 BAILOUT("Non-this-property reference"); |
| 300 } |
| 301 if (!expr->key()->IsPropertyName()) { |
| 302 BAILOUT("Non-named-property reference"); |
| 303 } |
| 304 |
| 305 // We will only specialize for fields on the object itself. |
| 306 // Expression::IsPropertyName implies that the name is a literal |
| 307 // symbol but we do not assume that. |
| 308 Literal* key = expr->key()->AsLiteral(); |
| 309 if (key != NULL && key->handle()->IsString()) { |
| 310 Handle<Object> receiver = info()->receiver(); |
| 311 Handle<String> name = Handle<String>::cast(key->handle()); |
| 312 LookupResult lookup; |
| 313 receiver->Lookup(*name, &lookup); |
| 314 if (lookup.holder() != *receiver) BAILOUT("Non-own property reference"); |
| 315 if (!lookup.type() == FIELD) BAILOUT("Non-field property reference"); |
| 316 } else { |
| 317 UNREACHABLE(); |
| 318 BAILOUT("Unexpected non-string-literal property key"); |
| 319 } |
297 } | 320 } |
298 | 321 |
299 | 322 |
300 void FastCodeGenSyntaxChecker::VisitCall(Call* expr) { | 323 void FastCodeGenSyntaxChecker::VisitCall(Call* expr) { |
301 BAILOUT("Call"); | 324 BAILOUT("Call"); |
302 } | 325 } |
303 | 326 |
304 | 327 |
305 void FastCodeGenSyntaxChecker::VisitCallNew(CallNew* expr) { | 328 void FastCodeGenSyntaxChecker::VisitCallNew(CallNew* expr) { |
306 BAILOUT("CallNew"); | 329 BAILOUT("CallNew"); |
307 } | 330 } |
308 | 331 |
309 | 332 |
310 void FastCodeGenSyntaxChecker::VisitCallRuntime(CallRuntime* expr) { | 333 void FastCodeGenSyntaxChecker::VisitCallRuntime(CallRuntime* expr) { |
311 BAILOUT("CallRuntime"); | 334 BAILOUT("CallRuntime"); |
312 } | 335 } |
313 | 336 |
314 | 337 |
315 void FastCodeGenSyntaxChecker::VisitUnaryOperation(UnaryOperation* expr) { | 338 void FastCodeGenSyntaxChecker::VisitUnaryOperation(UnaryOperation* expr) { |
316 BAILOUT("UnaryOperation"); | 339 BAILOUT("UnaryOperation"); |
317 } | 340 } |
318 | 341 |
319 | 342 |
320 void FastCodeGenSyntaxChecker::VisitCountOperation(CountOperation* expr) { | 343 void FastCodeGenSyntaxChecker::VisitCountOperation(CountOperation* expr) { |
321 BAILOUT("CountOperation"); | 344 BAILOUT("CountOperation"); |
322 } | 345 } |
323 | 346 |
324 | 347 |
325 void FastCodeGenSyntaxChecker::VisitBinaryOperation(BinaryOperation* expr) { | 348 void FastCodeGenSyntaxChecker::VisitBinaryOperation(BinaryOperation* expr) { |
326 BAILOUT("BinaryOperation"); | 349 // We support bitwise OR. |
| 350 switch (expr->op()) { |
| 351 case Token::COMMA: |
| 352 BAILOUT("BinaryOperation COMMA"); |
| 353 case Token::OR: |
| 354 BAILOUT("BinaryOperation OR"); |
| 355 case Token::AND: |
| 356 BAILOUT("BinaryOperation AND"); |
| 357 |
| 358 case Token::BIT_OR: |
| 359 // We support expressions nested on the left because they only require |
| 360 // a pair of registers to keep all intermediate values in registers |
| 361 // (i.e., the expression stack has height no more than two). |
| 362 if (!expr->right()->IsLeaf()) BAILOUT("expression nested on right"); |
| 363 Visit(expr->left()); |
| 364 CHECK_BAILOUT; |
| 365 Visit(expr->right()); |
| 366 break; |
| 367 |
| 368 case Token::BIT_XOR: |
| 369 BAILOUT("BinaryOperation BIT_XOR"); |
| 370 case Token::BIT_AND: |
| 371 BAILOUT("BinaryOperation BIT_AND"); |
| 372 case Token::SHL: |
| 373 BAILOUT("BinaryOperation SHL"); |
| 374 case Token::SAR: |
| 375 BAILOUT("BinaryOperation SAR"); |
| 376 case Token::SHR: |
| 377 BAILOUT("BinaryOperation SHR"); |
| 378 case Token::ADD: |
| 379 BAILOUT("BinaryOperation ADD"); |
| 380 case Token::SUB: |
| 381 BAILOUT("BinaryOperation SUB"); |
| 382 case Token::MUL: |
| 383 BAILOUT("BinaryOperation MUL"); |
| 384 case Token::DIV: |
| 385 BAILOUT("BinaryOperation DIV"); |
| 386 case Token::MOD: |
| 387 BAILOUT("BinaryOperation MOD"); |
| 388 default: |
| 389 UNREACHABLE(); |
| 390 } |
327 } | 391 } |
328 | 392 |
329 | 393 |
330 void FastCodeGenSyntaxChecker::VisitCompareOperation(CompareOperation* expr) { | 394 void FastCodeGenSyntaxChecker::VisitCompareOperation(CompareOperation* expr) { |
331 BAILOUT("CompareOperation"); | 395 BAILOUT("CompareOperation"); |
332 } | 396 } |
333 | 397 |
334 | 398 |
335 void FastCodeGenSyntaxChecker::VisitThisFunction(ThisFunction* expr) { | 399 void FastCodeGenSyntaxChecker::VisitThisFunction(ThisFunction* expr) { |
336 BAILOUT("ThisFunction"); | 400 BAILOUT("ThisFunction"); |
(...skipping 145 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
482 } | 546 } |
483 | 547 |
484 | 548 |
485 void FastCodeGenerator::VisitSlot(Slot* expr) { | 549 void FastCodeGenerator::VisitSlot(Slot* expr) { |
486 UNREACHABLE(); | 550 UNREACHABLE(); |
487 } | 551 } |
488 | 552 |
489 | 553 |
490 void FastCodeGenerator::VisitVariableProxy(VariableProxy* expr) { | 554 void FastCodeGenerator::VisitVariableProxy(VariableProxy* expr) { |
491 ASSERT(expr->var()->is_global() && !expr->var()->is_this()); | 555 ASSERT(expr->var()->is_global() && !expr->var()->is_this()); |
492 Comment cmnt(masm(), ";; Global"); | |
493 if (FLAG_print_ir) { | |
494 SmartPointer<char> name = expr->name()->ToCString(); | |
495 PrintF("%d: t%d = Global(%s)\n", expr->num(), expr->num(), *name); | |
496 } | |
497 | |
498 // Check if we can compile a global variable load directly from the cell. | 556 // Check if we can compile a global variable load directly from the cell. |
499 ASSERT(info()->has_global_object()); | 557 ASSERT(info()->has_global_object()); |
500 LookupResult lookup; | 558 LookupResult lookup; |
501 info()->global_object()->Lookup(*expr->name(), &lookup); | 559 info()->global_object()->Lookup(*expr->name(), &lookup); |
502 // We only support DontDelete properties for now. | 560 // We only support DontDelete properties for now. |
503 ASSERT(lookup.IsValid()); | 561 ASSERT(lookup.IsValid()); |
504 ASSERT(lookup.IsDontDelete()); | 562 ASSERT(lookup.IsDontDelete()); |
505 Handle<Object> cell(info()->global_object()->GetPropertyCell(&lookup)); | 563 Handle<Object> cell(info()->global_object()->GetPropertyCell(&lookup)); |
506 EmitGlobalVariableLoad(cell); | 564 |
| 565 // Global variable lookups do not have side effects, so we do not need to |
| 566 // emit code if we are in an effect context. |
| 567 if (!destination().is(no_reg)) { |
| 568 Comment cmnt(masm(), ";; Global"); |
| 569 if (FLAG_print_ir) { |
| 570 SmartPointer<char> name = expr->name()->ToCString(); |
| 571 PrintF("%d: t%d = Global(%s)\n", expr->num(), expr->num(), *name); |
| 572 } |
| 573 EmitGlobalVariableLoad(cell); |
| 574 } |
507 } | 575 } |
508 | 576 |
509 | 577 |
510 void FastCodeGenerator::VisitLiteral(Literal* expr) { | 578 void FastCodeGenerator::VisitLiteral(Literal* expr) { |
511 UNREACHABLE(); | 579 UNREACHABLE(); |
512 } | 580 } |
513 | 581 |
514 | 582 |
515 void FastCodeGenerator::VisitRegExpLiteral(RegExpLiteral* expr) { | 583 void FastCodeGenerator::VisitRegExpLiteral(RegExpLiteral* expr) { |
516 UNREACHABLE(); | 584 UNREACHABLE(); |
517 } | 585 } |
518 | 586 |
519 | 587 |
520 void FastCodeGenerator::VisitObjectLiteral(ObjectLiteral* expr) { | 588 void FastCodeGenerator::VisitObjectLiteral(ObjectLiteral* expr) { |
521 UNREACHABLE(); | 589 UNREACHABLE(); |
522 } | 590 } |
523 | 591 |
524 | 592 |
525 void FastCodeGenerator::VisitArrayLiteral(ArrayLiteral* expr) { | 593 void FastCodeGenerator::VisitArrayLiteral(ArrayLiteral* expr) { |
526 UNREACHABLE(); | 594 UNREACHABLE(); |
527 } | 595 } |
528 | 596 |
529 | 597 |
530 void FastCodeGenerator::VisitCatchExtensionObject(CatchExtensionObject* expr) { | 598 void FastCodeGenerator::VisitCatchExtensionObject(CatchExtensionObject* expr) { |
531 UNREACHABLE(); | 599 UNREACHABLE(); |
532 } | 600 } |
533 | 601 |
534 | 602 |
535 void FastCodeGenerator::VisitAssignment(Assignment* expr) { | 603 void FastCodeGenerator::VisitAssignment(Assignment* expr) { |
536 // Known to be a simple this property assignment. | 604 // Known to be a simple this property assignment. Effectively a unary |
537 Visit(expr->value()); | 605 // operation. |
| 606 { Register my_destination = destination(); |
| 607 set_destination(accumulator0()); |
| 608 Visit(expr->value()); |
| 609 set_destination(my_destination); |
| 610 } |
538 | 611 |
539 Property* prop = expr->target()->AsProperty(); | 612 Property* prop = expr->target()->AsProperty(); |
540 ASSERT_NOT_NULL(prop); | 613 ASSERT_NOT_NULL(prop); |
541 ASSERT_NOT_NULL(prop->obj()->AsVariableProxy()); | 614 ASSERT_NOT_NULL(prop->obj()->AsVariableProxy()); |
542 ASSERT(prop->obj()->AsVariableProxy()->var()->is_this()); | 615 ASSERT(prop->obj()->AsVariableProxy()->var()->is_this()); |
543 ASSERT(prop->key()->IsPropertyName()); | 616 ASSERT(prop->key()->IsPropertyName()); |
544 Handle<String> name = | 617 Handle<String> name = |
545 Handle<String>::cast(prop->key()->AsLiteral()->handle()); | 618 Handle<String>::cast(prop->key()->AsLiteral()->handle()); |
546 | 619 |
547 Comment cmnt(masm(), ";; Store(this)"); | 620 Comment cmnt(masm(), ";; Store to this"); |
548 if (FLAG_print_ir) { | 621 if (FLAG_print_ir) { |
549 SmartPointer<char> name_string = name->ToCString(); | 622 SmartPointer<char> name_string = name->ToCString(); |
550 PrintF("%d: t%d = Store(this, \"%s\", t%d)\n", | 623 PrintF("%d: ", expr->num()); |
551 expr->num(), expr->num(), *name_string, expr->value()->num()); | 624 if (!destination().is(no_reg)) PrintF("t%d = ", expr->num()); |
| 625 PrintF("Store(this, \"%s\", t%d)\n", *name_string, expr->value()->num()); |
552 } | 626 } |
553 | 627 |
554 EmitThisPropertyStore(name); | 628 EmitThisPropertyStore(name); |
555 } | 629 } |
556 | 630 |
557 | 631 |
558 void FastCodeGenerator::VisitThrow(Throw* expr) { | 632 void FastCodeGenerator::VisitThrow(Throw* expr) { |
559 UNREACHABLE(); | 633 UNREACHABLE(); |
560 } | 634 } |
561 | 635 |
562 | 636 |
563 void FastCodeGenerator::VisitProperty(Property* expr) { | 637 void FastCodeGenerator::VisitProperty(Property* expr) { |
564 UNREACHABLE(); | 638 ASSERT_NOT_NULL(expr->obj()->AsVariableProxy()); |
| 639 ASSERT(expr->obj()->AsVariableProxy()->var()->is_this()); |
| 640 ASSERT(expr->key()->IsPropertyName()); |
| 641 if (!destination().is(no_reg)) { |
| 642 Handle<String> name = |
| 643 Handle<String>::cast(expr->key()->AsLiteral()->handle()); |
| 644 |
| 645 Comment cmnt(masm(), ";; Load from this"); |
| 646 if (FLAG_print_ir) { |
| 647 SmartPointer<char> name_string = name->ToCString(); |
| 648 PrintF("%d: t%d = Load(this, \"%s\")\n", |
| 649 expr->num(), expr->num(), *name_string); |
| 650 } |
| 651 EmitThisPropertyLoad(name); |
| 652 } |
565 } | 653 } |
566 | 654 |
567 | 655 |
568 void FastCodeGenerator::VisitCall(Call* expr) { | 656 void FastCodeGenerator::VisitCall(Call* expr) { |
569 UNREACHABLE(); | 657 UNREACHABLE(); |
570 } | 658 } |
571 | 659 |
572 | 660 |
573 void FastCodeGenerator::VisitCallNew(CallNew* expr) { | 661 void FastCodeGenerator::VisitCallNew(CallNew* expr) { |
574 UNREACHABLE(); | 662 UNREACHABLE(); |
575 } | 663 } |
576 | 664 |
577 | 665 |
578 void FastCodeGenerator::VisitCallRuntime(CallRuntime* expr) { | 666 void FastCodeGenerator::VisitCallRuntime(CallRuntime* expr) { |
579 UNREACHABLE(); | 667 UNREACHABLE(); |
580 } | 668 } |
581 | 669 |
582 | 670 |
583 void FastCodeGenerator::VisitUnaryOperation(UnaryOperation* expr) { | 671 void FastCodeGenerator::VisitUnaryOperation(UnaryOperation* expr) { |
584 UNREACHABLE(); | 672 UNREACHABLE(); |
585 } | 673 } |
586 | 674 |
587 | 675 |
588 void FastCodeGenerator::VisitCountOperation(CountOperation* expr) { | 676 void FastCodeGenerator::VisitCountOperation(CountOperation* expr) { |
589 UNREACHABLE(); | 677 UNREACHABLE(); |
590 } | 678 } |
591 | 679 |
592 | 680 |
593 void FastCodeGenerator::VisitBinaryOperation(BinaryOperation* expr) { | 681 void FastCodeGenerator::VisitBinaryOperation(BinaryOperation* expr) { |
594 UNREACHABLE(); | 682 // We support limited binary operations: bitwise OR only allowed to be |
| 683 // nested on the left. |
| 684 ASSERT(expr->op() == Token::BIT_OR); |
| 685 ASSERT(expr->right()->IsLeaf()); |
| 686 |
| 687 { Register my_destination = destination(); |
| 688 set_destination(accumulator1()); |
| 689 Visit(expr->left()); |
| 690 set_destination(accumulator0()); |
| 691 Visit(expr->right()); |
| 692 set_destination(my_destination); |
| 693 } |
| 694 |
| 695 Comment cmnt(masm(), ";; BIT_OR"); |
| 696 if (FLAG_print_ir) { |
| 697 PrintF("%d: ", expr->num()); |
| 698 if (!destination().is(no_reg)) PrintF("t%d = ", expr->num()); |
| 699 PrintF("BIT_OR(t%d, t%d)\n", expr->left()->num(), expr->right()->num()); |
| 700 } |
| 701 EmitBitOr(); |
595 } | 702 } |
596 | 703 |
597 | 704 |
598 void FastCodeGenerator::VisitCompareOperation(CompareOperation* expr) { | 705 void FastCodeGenerator::VisitCompareOperation(CompareOperation* expr) { |
599 UNREACHABLE(); | 706 UNREACHABLE(); |
600 } | 707 } |
601 | 708 |
602 | 709 |
603 void FastCodeGenerator::VisitThisFunction(ThisFunction* expr) { | 710 void FastCodeGenerator::VisitThisFunction(ThisFunction* expr) { |
604 UNREACHABLE(); | 711 UNREACHABLE(); |
605 } | 712 } |
606 | 713 |
607 #undef __ | 714 #undef __ |
608 | 715 |
609 | 716 |
610 } } // namespace v8::internal | 717 } } // namespace v8::internal |
OLD | NEW |