| 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 |