OLD | NEW |
1 // Copyright 2006-2008 the V8 project authors. All rights reserved. | 1 // Copyright 2006-2008 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 501 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
512 } | 512 } |
513 ASSERT(!has_cc()); | 513 ASSERT(!has_cc()); |
514 } | 514 } |
515 | 515 |
516 | 516 |
517 void CodeGenerator::LoadGlobal() { | 517 void CodeGenerator::LoadGlobal() { |
518 frame_->Push(GlobalObject()); | 518 frame_->Push(GlobalObject()); |
519 } | 519 } |
520 | 520 |
521 | 521 |
| 522 void CodeGenerator::LoadGlobalReceiver(Register scratch) { |
| 523 __ mov(scratch, ContextOperand(esi, Context::GLOBAL_INDEX)); |
| 524 __ push(FieldOperand(scratch, GlobalObject::kGlobalReceiverOffset)); |
| 525 } |
| 526 |
| 527 |
522 // TODO(1241834): Get rid of this function in favor of just using Load, now | 528 // TODO(1241834): Get rid of this function in favor of just using Load, now |
523 // that we have the INSIDE_TYPEOF typeof state. => Need to handle global | 529 // that we have the INSIDE_TYPEOF typeof state. => Need to handle global |
524 // variables w/o reference errors elsewhere. | 530 // variables w/o reference errors elsewhere. |
525 void CodeGenerator::LoadTypeofExpression(Expression* x) { | 531 void CodeGenerator::LoadTypeofExpression(Expression* x) { |
| 532 |
526 Variable* variable = x->AsVariableProxy()->AsVariable(); | 533 Variable* variable = x->AsVariableProxy()->AsVariable(); |
527 if (variable != NULL && !variable->is_this() && variable->is_global()) { | 534 if (variable != NULL && !variable->is_this() && variable->is_global()) { |
528 // NOTE: This is somewhat nasty. We force the compiler to load | 535 // NOTE: This is somewhat nasty. We force the compiler to load |
529 // the variable as if through '<global>.<variable>' to make sure we | 536 // the variable as if through '<global>.<variable>' to make sure we |
530 // do not get reference errors. | 537 // do not get reference errors. |
531 Slot global(variable, Slot::CONTEXT, Context::GLOBAL_INDEX); | 538 Slot global(variable, Slot::CONTEXT, Context::GLOBAL_INDEX); |
532 Literal key(variable->name()); | 539 Literal key(variable->name()); |
533 // TODO(1241834): Fetch the position from the variable instead of using | 540 // TODO(1241834): Fetch the position from the variable instead of using |
534 // no position. | 541 // no position. |
535 Property property(&global, &key, RelocInfo::kNoPosition); | 542 Property property(&global, &key, RelocInfo::kNoPosition); |
(...skipping 2107 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2643 // is resolved in cache misses (this also holds for megamorphic calls). | 2650 // is resolved in cache misses (this also holds for megamorphic calls). |
2644 // ------------------------------------------------------------------------ | 2651 // ------------------------------------------------------------------------ |
2645 | 2652 |
2646 if (var != NULL && !var->is_this() && var->is_global()) { | 2653 if (var != NULL && !var->is_this() && var->is_global()) { |
2647 // ---------------------------------- | 2654 // ---------------------------------- |
2648 // JavaScript example: 'foo(1, 2, 3)' // foo is global | 2655 // JavaScript example: 'foo(1, 2, 3)' // foo is global |
2649 // ---------------------------------- | 2656 // ---------------------------------- |
2650 | 2657 |
2651 // Push the name of the function and the receiver onto the stack. | 2658 // Push the name of the function and the receiver onto the stack. |
2652 frame_->Push(Immediate(var->name())); | 2659 frame_->Push(Immediate(var->name())); |
2653 LoadGlobal(); | 2660 |
| 2661 // TODO(120): use the JSGlobalObject for function lookup and inline cache, |
| 2662 // and use outer global as 'this' object. |
| 2663 LoadGlobalReceiver(eax); |
2654 | 2664 |
2655 // Load the arguments. | 2665 // Load the arguments. |
2656 for (int i = 0; i < args->length(); i++) { | 2666 for (int i = 0; i < args->length(); i++) { |
2657 Load(args->at(i)); | 2667 Load(args->at(i)); |
2658 } | 2668 } |
2659 | 2669 |
2660 // Setup the receiver register and call the IC initialization code. | 2670 // Setup the receiver register and call the IC initialization code. |
2661 Handle<Code> stub = ComputeCallInitialize(args->length()); | 2671 Handle<Code> stub = ComputeCallInitialize(args->length()); |
2662 __ RecordPosition(node->position()); | 2672 __ RecordPosition(node->position()); |
2663 __ call(stub, RelocInfo::CODE_TARGET_CONTEXT); | 2673 __ call(stub, RelocInfo::CODE_TARGET_CONTEXT); |
(...skipping 65 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2729 | 2739 |
2730 } else { | 2740 } else { |
2731 // ---------------------------------- | 2741 // ---------------------------------- |
2732 // JavaScript example: 'foo(1, 2, 3)' // foo is not global | 2742 // JavaScript example: 'foo(1, 2, 3)' // foo is not global |
2733 // ---------------------------------- | 2743 // ---------------------------------- |
2734 | 2744 |
2735 // Load the function. | 2745 // Load the function. |
2736 Load(function); | 2746 Load(function); |
2737 | 2747 |
2738 // Pass the global object as the receiver. | 2748 // Pass the global object as the receiver. |
2739 LoadGlobal(); | 2749 // TODO(120): use JSGlobalObject for method lookup, and use JSGlobalProxy |
| 2750 // as 'this' for method invocation. |
| 2751 LoadGlobalReceiver(eax); |
2740 | 2752 |
2741 // Call the function. | 2753 // Call the function. |
2742 CallWithArguments(args, node->position()); | 2754 CallWithArguments(args, node->position()); |
2743 } | 2755 } |
2744 } | 2756 } |
2745 | 2757 |
2746 | 2758 |
2747 void CodeGenerator::VisitCallNew(CallNew* node) { | 2759 void CodeGenerator::VisitCallNew(CallNew* node) { |
2748 Comment cmnt(masm_, "[ CallNew"); | 2760 Comment cmnt(masm_, "[ CallNew"); |
2749 | 2761 |
2750 // According to ECMA-262, section 11.2.2, page 44, the function | 2762 // According to ECMA-262, section 11.2.2, page 44, the function |
2751 // expression in new calls must be evaluated before the | 2763 // expression in new calls must be evaluated before the |
2752 // arguments. This is different from ordinary calls, where the | 2764 // arguments. This is different from ordinary calls, where the |
2753 // actual function to call is resolved after the arguments have been | 2765 // actual function to call is resolved after the arguments have been |
2754 // evaluated. | 2766 // evaluated. |
2755 | 2767 |
2756 // Compute function to call and use the global object as the | 2768 // Compute function to call and use the global object as the |
2757 // receiver. | 2769 // receiver. |
2758 Load(node->expression()); | 2770 Load(node->expression()); |
2759 LoadGlobal(); | 2771 LoadGlobalReceiver(eax); |
2760 | 2772 |
2761 // Push the arguments ("left-to-right") on the stack. | 2773 // Push the arguments ("left-to-right") on the stack. |
2762 ZoneList<Expression*>* args = node->arguments(); | 2774 ZoneList<Expression*>* args = node->arguments(); |
2763 for (int i = 0; i < args->length(); i++) Load(args->at(i)); | 2775 for (int i = 0; i < args->length(); i++) Load(args->at(i)); |
2764 | 2776 |
2765 // Constructors are called with the number of arguments in register | 2777 // Constructors are called with the number of arguments in register |
2766 // eax for now. Another option would be to have separate construct | 2778 // eax for now. Another option would be to have separate construct |
2767 // call trampolines per different arguments counts encountered. | 2779 // call trampolines per different arguments counts encountered. |
2768 __ Set(eax, Immediate(args->length())); | 2780 __ Set(eax, Immediate(args->length())); |
2769 | 2781 |
(...skipping 719 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
3489 // Get the expressions from the node. | 3501 // Get the expressions from the node. |
3490 Expression* left = node->left(); | 3502 Expression* left = node->left(); |
3491 Expression* right = node->right(); | 3503 Expression* right = node->right(); |
3492 Token::Value op = node->op(); | 3504 Token::Value op = node->op(); |
3493 | 3505 |
3494 // NOTE: To make null checks efficient, we check if either left or | 3506 // NOTE: To make null checks efficient, we check if either left or |
3495 // right is the literal 'null'. If so, we optimize the code by | 3507 // right is the literal 'null'. If so, we optimize the code by |
3496 // inlining a null check instead of calling the (very) general | 3508 // inlining a null check instead of calling the (very) general |
3497 // runtime routine for checking equality. | 3509 // runtime routine for checking equality. |
3498 | 3510 |
3499 bool left_is_null = | |
3500 left->AsLiteral() != NULL && left->AsLiteral()->IsNull(); | |
3501 bool right_is_null = | |
3502 right->AsLiteral() != NULL && right->AsLiteral()->IsNull(); | |
3503 | |
3504 if (op == Token::EQ || op == Token::EQ_STRICT) { | 3511 if (op == Token::EQ || op == Token::EQ_STRICT) { |
| 3512 bool left_is_null = |
| 3513 left->AsLiteral() != NULL && left->AsLiteral()->IsNull(); |
| 3514 bool right_is_null = |
| 3515 right->AsLiteral() != NULL && right->AsLiteral()->IsNull(); |
3505 // The 'null' value is only equal to 'null' or 'undefined'. | 3516 // The 'null' value is only equal to 'null' or 'undefined'. |
3506 if (left_is_null || right_is_null) { | 3517 if (left_is_null || right_is_null) { |
3507 Load(left_is_null ? right : left); | 3518 Load(left_is_null ? right : left); |
3508 Label exit, undetectable; | 3519 Label exit, undetectable; |
3509 frame_->Pop(eax); | 3520 frame_->Pop(eax); |
3510 __ cmp(eax, Factory::null_value()); | 3521 __ cmp(eax, Factory::null_value()); |
3511 | 3522 |
3512 // The 'null' value is only equal to 'undefined' if using | 3523 // The 'null' value is only equal to 'undefined' if using |
3513 // non-strict comparisons. | 3524 // non-strict comparisons. |
3514 if (op != Token::EQ_STRICT) { | 3525 if (op != Token::EQ_STRICT) { |
(...skipping 14 matching lines...) Expand all Loading... |
3529 __ cmp(ecx, 1 << Map::kIsUndetectable); | 3540 __ cmp(ecx, 1 << Map::kIsUndetectable); |
3530 } | 3541 } |
3531 | 3542 |
3532 __ bind(&exit); | 3543 __ bind(&exit); |
3533 | 3544 |
3534 cc_reg_ = equal; | 3545 cc_reg_ = equal; |
3535 return; | 3546 return; |
3536 } | 3547 } |
3537 } | 3548 } |
3538 | 3549 |
3539 | |
3540 // NOTE: To make typeof testing for natives implemented in | 3550 // NOTE: To make typeof testing for natives implemented in |
3541 // JavaScript really efficient, we generate special code for | 3551 // JavaScript really efficient, we generate special code for |
3542 // expressions of the form: 'typeof <expression> == <string>'. | 3552 // expressions of the form: 'typeof <expression> == <string>'. |
3543 | 3553 |
3544 UnaryOperation* operation = left->AsUnaryOperation(); | 3554 UnaryOperation* operation = left->AsUnaryOperation(); |
3545 if ((op == Token::EQ || op == Token::EQ_STRICT) && | 3555 if ((op == Token::EQ || op == Token::EQ_STRICT) && |
3546 (operation != NULL && operation->op() == Token::TYPEOF) && | 3556 (operation != NULL && operation->op() == Token::TYPEOF) && |
3547 (right->AsLiteral() != NULL && | 3557 (right->AsLiteral() != NULL && |
3548 right->AsLiteral()->handle()->IsString())) { | 3558 right->AsLiteral()->handle()->IsString())) { |
3549 Handle<String> check(String::cast(*right->AsLiteral()->handle())); | 3559 Handle<String> check(String::cast(*right->AsLiteral()->handle())); |
(...skipping 1561 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
5111 | 5121 |
5112 // Slow-case: Go through the JavaScript implementation. | 5122 // Slow-case: Go through the JavaScript implementation. |
5113 __ bind(&slow); | 5123 __ bind(&slow); |
5114 __ InvokeBuiltin(Builtins::INSTANCE_OF, JUMP_FUNCTION); | 5124 __ InvokeBuiltin(Builtins::INSTANCE_OF, JUMP_FUNCTION); |
5115 } | 5125 } |
5116 | 5126 |
5117 | 5127 |
5118 #undef __ | 5128 #undef __ |
5119 | 5129 |
5120 } } // namespace v8::internal | 5130 } } // namespace v8::internal |
OLD | NEW |