| 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 |
| 11 // with the distribution. | 11 // with the distribution. |
| 12 // * Neither the name of Google Inc. nor the names of its | 12 // * Neither the name of Google Inc. nor the names of its |
| 13 // contributors may be used to endorse or promote products derived | 13 // contributors may be used to endorse or promote products derived |
| 14 // from this software without specific prior written permission. | 14 // from this software without specific prior written permission. |
| 15 // | 15 // |
| 16 // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS | 16 // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS |
| 17 // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT | 17 // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT |
| 18 // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR | 18 // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR |
| 19 // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT | 19 // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT |
| 20 // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, | 20 // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, |
| 21 // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT | 21 // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT |
| 22 // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, | 22 // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, |
| 23 // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY | 23 // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY |
| 24 // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT | 24 // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT |
| 25 // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE | 25 // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE |
| 26 // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. | 26 // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
| 27 | 27 |
| 28 #include "v8.h" | 28 #include "v8.h" |
| 29 | 29 |
| 30 #if defined(V8_TARGET_ARCH_ARM) |
| 31 |
| 30 #include "codegen-inl.h" | 32 #include "codegen-inl.h" |
| 31 #include "compiler.h" | 33 #include "compiler.h" |
| 32 #include "debug.h" | 34 #include "debug.h" |
| 33 #include "full-codegen.h" | 35 #include "full-codegen.h" |
| 34 #include "parser.h" | 36 #include "parser.h" |
| 35 #include "scopes.h" | 37 #include "scopes.h" |
| 36 | 38 |
| 37 namespace v8 { | 39 namespace v8 { |
| 38 namespace internal { | 40 namespace internal { |
| 39 | 41 |
| (...skipping 350 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 390 case Expression::kUninitialized: | 392 case Expression::kUninitialized: |
| 391 | 393 |
| 392 case Expression::kEffect: | 394 case Expression::kEffect: |
| 393 ASSERT_EQ(materialize_true, materialize_false); | 395 ASSERT_EQ(materialize_true, materialize_false); |
| 394 __ bind(materialize_true); | 396 __ bind(materialize_true); |
| 395 break; | 397 break; |
| 396 | 398 |
| 397 case Expression::kValue: { | 399 case Expression::kValue: { |
| 398 Label done; | 400 Label done; |
| 399 __ bind(materialize_true); | 401 __ bind(materialize_true); |
| 400 __ mov(result_register(), Operand(Factory::true_value())); | 402 __ LoadRoot(result_register(), Heap::kTrueValueRootIndex); |
| 401 __ jmp(&done); | 403 __ jmp(&done); |
| 402 __ bind(materialize_false); | 404 __ bind(materialize_false); |
| 403 __ mov(result_register(), Operand(Factory::false_value())); | 405 __ LoadRoot(result_register(), Heap::kFalseValueRootIndex); |
| 404 __ bind(&done); | 406 __ bind(&done); |
| 405 switch (location_) { | 407 switch (location_) { |
| 406 case kAccumulator: | 408 case kAccumulator: |
| 407 break; | 409 break; |
| 408 case kStack: | 410 case kStack: |
| 409 __ push(result_register()); | 411 __ push(result_register()); |
| 410 break; | 412 break; |
| 411 } | 413 } |
| 412 break; | 414 break; |
| 413 } | 415 } |
| 414 | 416 |
| 415 case Expression::kTest: | 417 case Expression::kTest: |
| 416 break; | 418 break; |
| 417 | 419 |
| 418 case Expression::kValueTest: | 420 case Expression::kValueTest: |
| 419 __ bind(materialize_true); | 421 __ bind(materialize_true); |
| 420 __ mov(result_register(), Operand(Factory::true_value())); | 422 __ LoadRoot(result_register(), Heap::kTrueValueRootIndex); |
| 421 switch (location_) { | 423 switch (location_) { |
| 422 case kAccumulator: | 424 case kAccumulator: |
| 423 break; | 425 break; |
| 424 case kStack: | 426 case kStack: |
| 425 __ push(result_register()); | 427 __ push(result_register()); |
| 426 break; | 428 break; |
| 427 } | 429 } |
| 428 __ jmp(true_label_); | 430 __ jmp(true_label_); |
| 429 break; | 431 break; |
| 430 | 432 |
| 431 case Expression::kTestValue: | 433 case Expression::kTestValue: |
| 432 __ bind(materialize_false); | 434 __ bind(materialize_false); |
| 433 __ mov(result_register(), Operand(Factory::false_value())); | 435 __ LoadRoot(result_register(), Heap::kFalseValueRootIndex); |
| 434 switch (location_) { | 436 switch (location_) { |
| 435 case kAccumulator: | 437 case kAccumulator: |
| 436 break; | 438 break; |
| 437 case kStack: | 439 case kStack: |
| 438 __ push(result_register()); | 440 __ push(result_register()); |
| 439 break; | 441 break; |
| 440 } | 442 } |
| 441 __ jmp(false_label_); | 443 __ jmp(false_label_); |
| 442 break; | 444 break; |
| 443 } | 445 } |
| (...skipping 189 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 633 VisitForValue(prop->obj(), kStack); | 635 VisitForValue(prop->obj(), kStack); |
| 634 VisitForValue(prop->key(), kStack); | 636 VisitForValue(prop->key(), kStack); |
| 635 | 637 |
| 636 if (decl->fun() != NULL) { | 638 if (decl->fun() != NULL) { |
| 637 VisitForValue(decl->fun(), kAccumulator); | 639 VisitForValue(decl->fun(), kAccumulator); |
| 638 } else { | 640 } else { |
| 639 __ LoadRoot(result_register(), Heap::kTheHoleValueRootIndex); | 641 __ LoadRoot(result_register(), Heap::kTheHoleValueRootIndex); |
| 640 } | 642 } |
| 641 | 643 |
| 642 Handle<Code> ic(Builtins::builtin(Builtins::KeyedStoreIC_Initialize)); | 644 Handle<Code> ic(Builtins::builtin(Builtins::KeyedStoreIC_Initialize)); |
| 645 __ pop(r1); // Key. |
| 646 __ pop(r2); // Receiver. |
| 643 __ Call(ic, RelocInfo::CODE_TARGET); | 647 __ Call(ic, RelocInfo::CODE_TARGET); |
| 644 | 648 |
| 645 // Value in r0 is ignored (declarations are statements). Receiver | 649 // Value in r0 is ignored (declarations are statements). |
| 646 // and key on stack are discarded. | |
| 647 __ Drop(2); | |
| 648 } | 650 } |
| 649 } | 651 } |
| 650 } | 652 } |
| 651 | 653 |
| 652 | 654 |
| 653 void FullCodeGenerator::DeclareGlobals(Handle<FixedArray> pairs) { | 655 void FullCodeGenerator::DeclareGlobals(Handle<FixedArray> pairs) { |
| 654 // Call the runtime to declare the globals. | 656 // Call the runtime to declare the globals. |
| 655 // The context is the first argument. | 657 // The context is the first argument. |
| 656 __ mov(r1, Operand(pairs)); | 658 __ mov(r1, Operand(pairs)); |
| 657 __ mov(r0, Operand(Smi::FromInt(is_eval() ? 1 : 0))); | 659 __ mov(r0, Operand(Smi::FromInt(is_eval() ? 1 : 0))); |
| 658 __ stm(db_w, sp, cp.bit() | r1.bit() | r0.bit()); | 660 __ stm(db_w, sp, cp.bit() | r1.bit() | r0.bit()); |
| 659 __ CallRuntime(Runtime::kDeclareGlobals, 3); | 661 __ CallRuntime(Runtime::kDeclareGlobals, 3); |
| 660 // Return value is ignored. | 662 // Return value is ignored. |
| 661 } | 663 } |
| 662 | 664 |
| 663 | 665 |
| 664 void FullCodeGenerator::VisitFunctionLiteral(FunctionLiteral* expr) { | 666 void FullCodeGenerator::VisitSwitchStatement(SwitchStatement* stmt) { |
| 665 Comment cmnt(masm_, "[ FunctionLiteral"); | 667 UNREACHABLE(); |
| 668 } |
| 666 | 669 |
| 667 // Build the shared function info and instantiate the function based | |
| 668 // on it. | |
| 669 Handle<SharedFunctionInfo> function_info = | |
| 670 Compiler::BuildFunctionInfo(expr, script(), this); | |
| 671 if (HasStackOverflow()) return; | |
| 672 | 670 |
| 673 // Create a new closure. | 671 void FullCodeGenerator::VisitForInStatement(ForInStatement* stmt) { |
| 674 __ mov(r0, Operand(function_info)); | 672 UNREACHABLE(); |
| 675 __ stm(db_w, sp, cp.bit() | r0.bit()); | 673 } |
| 676 __ CallRuntime(Runtime::kNewClosure, 2); | 674 |
| 675 |
| 676 void FullCodeGenerator::EmitNewClosure(Handle<SharedFunctionInfo> info) { |
| 677 // Use the fast case closure allocation code that allocates in new |
| 678 // space for nested functions that don't need literals cloning. |
| 679 if (scope()->is_function_scope() && info->num_literals() == 0) { |
| 680 FastNewClosureStub stub; |
| 681 __ mov(r0, Operand(info)); |
| 682 __ push(r0); |
| 683 __ CallStub(&stub); |
| 684 } else { |
| 685 __ mov(r0, Operand(info)); |
| 686 __ stm(db_w, sp, cp.bit() | r0.bit()); |
| 687 __ CallRuntime(Runtime::kNewClosure, 2); |
| 688 } |
| 677 Apply(context_, r0); | 689 Apply(context_, r0); |
| 678 } | 690 } |
| 679 | 691 |
| 680 | 692 |
| 681 void FullCodeGenerator::VisitVariableProxy(VariableProxy* expr) { | 693 void FullCodeGenerator::VisitVariableProxy(VariableProxy* expr) { |
| 682 Comment cmnt(masm_, "[ VariableProxy"); | 694 Comment cmnt(masm_, "[ VariableProxy"); |
| 683 EmitVariableLoad(expr->var(), context_); | 695 EmitVariableLoad(expr->var(), context_); |
| 684 } | 696 } |
| 685 | 697 |
| 686 | 698 |
| 687 void FullCodeGenerator::EmitVariableLoad(Variable* var, | 699 void FullCodeGenerator::EmitVariableLoad(Variable* var, |
| 688 Expression::Context context) { | 700 Expression::Context context) { |
| 689 // Four cases: non-this global variables, lookup slots, all other | 701 // Four cases: non-this global variables, lookup slots, all other |
| 690 // types of slots, and parameters that rewrite to explicit property | 702 // types of slots, and parameters that rewrite to explicit property |
| 691 // accesses on the arguments object. | 703 // accesses on the arguments object. |
| 692 Slot* slot = var->slot(); | 704 Slot* slot = var->slot(); |
| 693 Property* property = var->AsProperty(); | 705 Property* property = var->AsProperty(); |
| 694 | 706 |
| 695 if (var->is_global() && !var->is_this()) { | 707 if (var->is_global() && !var->is_this()) { |
| 696 Comment cmnt(masm_, "Global variable"); | 708 Comment cmnt(masm_, "Global variable"); |
| 697 // Use inline caching. Variable name is passed in r2 and the global | 709 // Use inline caching. Variable name is passed in r2 and the global |
| 698 // object on the stack. | 710 // object (receiver) in r0. |
| 699 __ ldr(r0, CodeGenerator::GlobalObject()); | 711 __ ldr(r0, CodeGenerator::GlobalObject()); |
| 700 __ push(r0); | |
| 701 __ mov(r2, Operand(var->name())); | 712 __ mov(r2, Operand(var->name())); |
| 702 Handle<Code> ic(Builtins::builtin(Builtins::LoadIC_Initialize)); | 713 Handle<Code> ic(Builtins::builtin(Builtins::LoadIC_Initialize)); |
| 703 __ Call(ic, RelocInfo::CODE_TARGET_CONTEXT); | 714 __ Call(ic, RelocInfo::CODE_TARGET_CONTEXT); |
| 704 DropAndApply(1, context, r0); | 715 Apply(context, r0); |
| 705 | 716 |
| 706 } else if (slot != NULL && slot->type() == Slot::LOOKUP) { | 717 } else if (slot != NULL && slot->type() == Slot::LOOKUP) { |
| 707 Comment cmnt(masm_, "Lookup slot"); | 718 Comment cmnt(masm_, "Lookup slot"); |
| 708 __ mov(r1, Operand(var->name())); | 719 __ mov(r1, Operand(var->name())); |
| 709 __ stm(db_w, sp, cp.bit() | r1.bit()); // Context and name. | 720 __ stm(db_w, sp, cp.bit() | r1.bit()); // Context and name. |
| 710 __ CallRuntime(Runtime::kLoadContextSlot, 2); | 721 __ CallRuntime(Runtime::kLoadContextSlot, 2); |
| 711 Apply(context, r0); | 722 Apply(context, r0); |
| 712 | 723 |
| 713 } else if (slot != NULL) { | 724 } else if (slot != NULL) { |
| 714 Comment cmnt(masm_, (slot->type() == Slot::CONTEXT) | 725 Comment cmnt(masm_, (slot->type() == Slot::CONTEXT) |
| (...skipping 182 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 897 if (result_saved) { | 908 if (result_saved) { |
| 898 ApplyTOS(context_); | 909 ApplyTOS(context_); |
| 899 } else { | 910 } else { |
| 900 Apply(context_, r0); | 911 Apply(context_, r0); |
| 901 } | 912 } |
| 902 } | 913 } |
| 903 | 914 |
| 904 | 915 |
| 905 void FullCodeGenerator::VisitAssignment(Assignment* expr) { | 916 void FullCodeGenerator::VisitAssignment(Assignment* expr) { |
| 906 Comment cmnt(masm_, "[ Assignment"); | 917 Comment cmnt(masm_, "[ Assignment"); |
| 907 ASSERT(expr->op() != Token::INIT_CONST); | 918 // Invalid left-hand sides are rewritten to have a 'throw ReferenceError' |
| 919 // on the left-hand side. |
| 920 if (!expr->target()->IsValidLeftHandSide()) { |
| 921 VisitForEffect(expr->target()); |
| 922 return; |
| 923 } |
| 924 |
| 908 // Left-hand side can only be a property, a global or a (parameter or local) | 925 // Left-hand side can only be a property, a global or a (parameter or local) |
| 909 // slot. Variables with rewrite to .arguments are treated as KEYED_PROPERTY. | 926 // slot. Variables with rewrite to .arguments are treated as KEYED_PROPERTY. |
| 910 enum LhsKind { VARIABLE, NAMED_PROPERTY, KEYED_PROPERTY }; | 927 enum LhsKind { VARIABLE, NAMED_PROPERTY, KEYED_PROPERTY }; |
| 911 LhsKind assign_type = VARIABLE; | 928 LhsKind assign_type = VARIABLE; |
| 912 Property* prop = expr->target()->AsProperty(); | 929 Property* prop = expr->target()->AsProperty(); |
| 913 if (prop != NULL) { | 930 if (prop != NULL) { |
| 914 assign_type = | 931 assign_type = |
| 915 (prop->key()->IsPropertyName()) ? NAMED_PROPERTY : KEYED_PROPERTY; | 932 (prop->key()->IsPropertyName()) ? NAMED_PROPERTY : KEYED_PROPERTY; |
| 916 } | 933 } |
| 917 | 934 |
| (...skipping 59 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 977 location_ = saved_location; | 994 location_ = saved_location; |
| 978 } | 995 } |
| 979 | 996 |
| 980 // Record source position before possible IC call. | 997 // Record source position before possible IC call. |
| 981 SetSourcePosition(expr->position()); | 998 SetSourcePosition(expr->position()); |
| 982 | 999 |
| 983 // Store the value. | 1000 // Store the value. |
| 984 switch (assign_type) { | 1001 switch (assign_type) { |
| 985 case VARIABLE: | 1002 case VARIABLE: |
| 986 EmitVariableAssignment(expr->target()->AsVariableProxy()->var(), | 1003 EmitVariableAssignment(expr->target()->AsVariableProxy()->var(), |
| 1004 expr->op(), |
| 987 context_); | 1005 context_); |
| 988 break; | 1006 break; |
| 989 case NAMED_PROPERTY: | 1007 case NAMED_PROPERTY: |
| 990 EmitNamedPropertyAssignment(expr); | 1008 EmitNamedPropertyAssignment(expr); |
| 991 break; | 1009 break; |
| 992 case KEYED_PROPERTY: | 1010 case KEYED_PROPERTY: |
| 993 EmitKeyedPropertyAssignment(expr); | 1011 EmitKeyedPropertyAssignment(expr); |
| 994 break; | 1012 break; |
| 995 } | 1013 } |
| 996 } | 1014 } |
| 997 | 1015 |
| 998 | 1016 |
| 999 void FullCodeGenerator::EmitNamedPropertyLoad(Property* prop) { | 1017 void FullCodeGenerator::EmitNamedPropertyLoad(Property* prop) { |
| 1000 SetSourcePosition(prop->position()); | 1018 SetSourcePosition(prop->position()); |
| 1001 Literal* key = prop->key()->AsLiteral(); | 1019 Literal* key = prop->key()->AsLiteral(); |
| 1002 __ mov(r2, Operand(key->handle())); | 1020 __ mov(r2, Operand(key->handle())); |
| 1003 __ ldr(r0, MemOperand(sp, 0)); | 1021 // Call load IC. It has arguments receiver and property name r0 and r2. |
| 1004 Handle<Code> ic(Builtins::builtin(Builtins::LoadIC_Initialize)); | 1022 Handle<Code> ic(Builtins::builtin(Builtins::LoadIC_Initialize)); |
| 1005 __ Call(ic, RelocInfo::CODE_TARGET); | 1023 __ Call(ic, RelocInfo::CODE_TARGET); |
| 1006 } | 1024 } |
| 1007 | 1025 |
| 1008 | 1026 |
| 1009 void FullCodeGenerator::EmitKeyedPropertyLoad(Property* prop) { | 1027 void FullCodeGenerator::EmitKeyedPropertyLoad(Property* prop) { |
| 1010 SetSourcePosition(prop->position()); | 1028 SetSourcePosition(prop->position()); |
| 1011 // Call keyed load IC. It has arguments key and receiver in r0 and r1. | 1029 // Call keyed load IC. It has arguments key and receiver in r0 and r1. |
| 1012 Handle<Code> ic(Builtins::builtin(Builtins::KeyedLoadIC_Initialize)); | 1030 Handle<Code> ic(Builtins::builtin(Builtins::KeyedLoadIC_Initialize)); |
| 1013 __ Call(ic, RelocInfo::CODE_TARGET); | 1031 __ Call(ic, RelocInfo::CODE_TARGET); |
| 1014 } | 1032 } |
| 1015 | 1033 |
| 1016 | 1034 |
| 1017 void FullCodeGenerator::EmitBinaryOp(Token::Value op, | 1035 void FullCodeGenerator::EmitBinaryOp(Token::Value op, |
| 1018 Expression::Context context) { | 1036 Expression::Context context) { |
| 1019 __ pop(r1); | 1037 __ pop(r1); |
| 1020 GenericBinaryOpStub stub(op, NO_OVERWRITE, r1, r0); | 1038 GenericBinaryOpStub stub(op, NO_OVERWRITE, r1, r0); |
| 1021 __ CallStub(&stub); | 1039 __ CallStub(&stub); |
| 1022 Apply(context, r0); | 1040 Apply(context, r0); |
| 1023 } | 1041 } |
| 1024 | 1042 |
| 1025 | 1043 |
| 1026 void FullCodeGenerator::EmitVariableAssignment(Variable* var, | 1044 void FullCodeGenerator::EmitVariableAssignment(Variable* var, |
| 1045 Token::Value op, |
| 1027 Expression::Context context) { | 1046 Expression::Context context) { |
| 1028 // Three main cases: global variables, lookup slots, and all other | 1047 // Left-hand sides that rewrite to explicit property accesses do not reach |
| 1029 // types of slots. Left-hand-side parameters that rewrite to | 1048 // here. |
| 1030 // explicit property accesses do not reach here. | |
| 1031 ASSERT(var != NULL); | 1049 ASSERT(var != NULL); |
| 1032 ASSERT(var->is_global() || var->slot() != NULL); | 1050 ASSERT(var->is_global() || var->slot() != NULL); |
| 1033 | 1051 |
| 1034 Slot* slot = var->slot(); | |
| 1035 if (var->is_global()) { | 1052 if (var->is_global()) { |
| 1036 ASSERT(!var->is_this()); | 1053 ASSERT(!var->is_this()); |
| 1037 // Assignment to a global variable. Use inline caching for the | 1054 // Assignment to a global variable. Use inline caching for the |
| 1038 // assignment. Right-hand-side value is passed in r0, variable name in | 1055 // assignment. Right-hand-side value is passed in r0, variable name in |
| 1039 // r2, and the global object in r1. | 1056 // r2, and the global object in r1. |
| 1040 __ mov(r2, Operand(var->name())); | 1057 __ mov(r2, Operand(var->name())); |
| 1041 __ ldr(r1, CodeGenerator::GlobalObject()); | 1058 __ ldr(r1, CodeGenerator::GlobalObject()); |
| 1042 Handle<Code> ic(Builtins::builtin(Builtins::StoreIC_Initialize)); | 1059 Handle<Code> ic(Builtins::builtin(Builtins::StoreIC_Initialize)); |
| 1043 __ Call(ic, RelocInfo::CODE_TARGET); | 1060 __ Call(ic, RelocInfo::CODE_TARGET); |
| 1044 | 1061 |
| 1045 } else if (slot != NULL && slot->type() == Slot::LOOKUP) { | 1062 } else if (var->mode() != Variable::CONST || op == Token::INIT_CONST) { |
| 1046 __ push(result_register()); // Value. | 1063 // Perform the assignment for non-const variables and for initialization |
| 1047 __ mov(r1, Operand(var->name())); | 1064 // of const variables. Const assignments are simply skipped. |
| 1048 __ stm(db_w, sp, cp.bit() | r1.bit()); // Context and name. | 1065 Label done; |
| 1049 __ CallRuntime(Runtime::kStoreContextSlot, 3); | |
| 1050 | |
| 1051 } else if (var->slot() != NULL) { | |
| 1052 Slot* slot = var->slot(); | 1066 Slot* slot = var->slot(); |
| 1053 switch (slot->type()) { | 1067 switch (slot->type()) { |
| 1068 case Slot::PARAMETER: |
| 1054 case Slot::LOCAL: | 1069 case Slot::LOCAL: |
| 1055 case Slot::PARAMETER: | 1070 if (op == Token::INIT_CONST) { |
| 1071 // Detect const reinitialization by checking for the hole value. |
| 1072 __ ldr(r1, MemOperand(fp, SlotOffset(slot))); |
| 1073 __ LoadRoot(ip, Heap::kTheHoleValueRootIndex); |
| 1074 __ cmp(r1, ip); |
| 1075 __ b(ne, &done); |
| 1076 } |
| 1077 // Perform the assignment. |
| 1056 __ str(result_register(), MemOperand(fp, SlotOffset(slot))); | 1078 __ str(result_register(), MemOperand(fp, SlotOffset(slot))); |
| 1057 break; | 1079 break; |
| 1058 | 1080 |
| 1059 case Slot::CONTEXT: { | 1081 case Slot::CONTEXT: { |
| 1060 MemOperand target = EmitSlotSearch(slot, r1); | 1082 MemOperand target = EmitSlotSearch(slot, r1); |
| 1083 if (op == Token::INIT_CONST) { |
| 1084 // Detect const reinitialization by checking for the hole value. |
| 1085 __ ldr(r1, target); |
| 1086 __ LoadRoot(ip, Heap::kTheHoleValueRootIndex); |
| 1087 __ cmp(r1, ip); |
| 1088 __ b(ne, &done); |
| 1089 } |
| 1090 // Perform the assignment and issue the write barrier. |
| 1061 __ str(result_register(), target); | 1091 __ str(result_register(), target); |
| 1062 | |
| 1063 // RecordWrite may destroy all its register arguments. | 1092 // RecordWrite may destroy all its register arguments. |
| 1064 __ mov(r3, result_register()); | 1093 __ mov(r3, result_register()); |
| 1065 int offset = FixedArray::kHeaderSize + slot->index() * kPointerSize; | 1094 int offset = FixedArray::kHeaderSize + slot->index() * kPointerSize; |
| 1066 | |
| 1067 __ mov(r2, Operand(offset)); | 1095 __ mov(r2, Operand(offset)); |
| 1068 __ RecordWrite(r1, r2, r3); | 1096 __ RecordWrite(r1, r2, r3); |
| 1069 break; | 1097 break; |
| 1070 } | 1098 } |
| 1071 | 1099 |
| 1072 case Slot::LOOKUP: | 1100 case Slot::LOOKUP: |
| 1073 UNREACHABLE(); | 1101 // Call the runtime for the assignment. The runtime will ignore |
| 1102 // const reinitialization. |
| 1103 __ push(r0); // Value. |
| 1104 __ mov(r0, Operand(slot->var()->name())); |
| 1105 __ Push(cp, r0); // Context and name. |
| 1106 if (op == Token::INIT_CONST) { |
| 1107 // The runtime will ignore const redeclaration. |
| 1108 __ CallRuntime(Runtime::kInitializeConstContextSlot, 3); |
| 1109 } else { |
| 1110 __ CallRuntime(Runtime::kStoreContextSlot, 3); |
| 1111 } |
| 1074 break; | 1112 break; |
| 1075 } | 1113 } |
| 1114 __ bind(&done); |
| 1115 } |
| 1076 | 1116 |
| 1077 } else { | |
| 1078 // Variables rewritten as properties are not treated as variables in | |
| 1079 // assignments. | |
| 1080 UNREACHABLE(); | |
| 1081 } | |
| 1082 Apply(context, result_register()); | 1117 Apply(context, result_register()); |
| 1083 } | 1118 } |
| 1084 | 1119 |
| 1085 | 1120 |
| 1086 void FullCodeGenerator::EmitNamedPropertyAssignment(Assignment* expr) { | 1121 void FullCodeGenerator::EmitNamedPropertyAssignment(Assignment* expr) { |
| 1087 // Assignment to a property, using a named store IC. | 1122 // Assignment to a property, using a named store IC. |
| 1088 Property* prop = expr->target()->AsProperty(); | 1123 Property* prop = expr->target()->AsProperty(); |
| 1089 ASSERT(prop != NULL); | 1124 ASSERT(prop != NULL); |
| 1090 ASSERT(prop->key()->AsLiteral() != NULL); | 1125 ASSERT(prop->key()->AsLiteral() != NULL); |
| 1091 | 1126 |
| 1092 // If the assignment starts a block of assignments to the same object, | 1127 // If the assignment starts a block of assignments to the same object, |
| 1093 // change to slow case to avoid the quadratic behavior of repeatedly | 1128 // change to slow case to avoid the quadratic behavior of repeatedly |
| 1094 // adding fast properties. | 1129 // adding fast properties. |
| 1095 if (expr->starts_initialization_block()) { | 1130 if (expr->starts_initialization_block()) { |
| 1096 __ push(result_register()); | 1131 __ push(result_register()); |
| 1097 __ ldr(ip, MemOperand(sp, kPointerSize)); // Receiver is now under value. | 1132 __ ldr(ip, MemOperand(sp, kPointerSize)); // Receiver is now under value. |
| 1098 __ push(ip); | 1133 __ push(ip); |
| 1099 __ CallRuntime(Runtime::kToSlowProperties, 1); | 1134 __ CallRuntime(Runtime::kToSlowProperties, 1); |
| 1100 __ pop(result_register()); | 1135 __ pop(result_register()); |
| 1101 } | 1136 } |
| 1102 | 1137 |
| 1103 // Record source code position before IC call. | 1138 // Record source code position before IC call. |
| 1104 SetSourcePosition(expr->position()); | 1139 SetSourcePosition(expr->position()); |
| 1105 __ mov(r2, Operand(prop->key()->AsLiteral()->handle())); | 1140 __ mov(r2, Operand(prop->key()->AsLiteral()->handle())); |
| 1141 // Load receiver to r1. Leave a copy in the stack if needed for turning the |
| 1142 // receiver into fast case. |
| 1106 if (expr->ends_initialization_block()) { | 1143 if (expr->ends_initialization_block()) { |
| 1107 __ ldr(r1, MemOperand(sp)); | 1144 __ ldr(r1, MemOperand(sp)); |
| 1108 } else { | 1145 } else { |
| 1109 __ pop(r1); | 1146 __ pop(r1); |
| 1110 } | 1147 } |
| 1111 | 1148 |
| 1112 Handle<Code> ic(Builtins::builtin(Builtins::StoreIC_Initialize)); | 1149 Handle<Code> ic(Builtins::builtin(Builtins::StoreIC_Initialize)); |
| 1113 __ Call(ic, RelocInfo::CODE_TARGET); | 1150 __ Call(ic, RelocInfo::CODE_TARGET); |
| 1114 | 1151 |
| 1115 // If the assignment ends an initialization block, revert to fast case. | 1152 // If the assignment ends an initialization block, revert to fast case. |
| 1116 if (expr->ends_initialization_block()) { | 1153 if (expr->ends_initialization_block()) { |
| 1117 __ push(r0); // Result of assignment, saved even if not needed. | 1154 __ push(r0); // Result of assignment, saved even if not needed. |
| 1118 __ ldr(ip, MemOperand(sp, kPointerSize)); // Receiver is under value. | 1155 // Receiver is under the result value. |
| 1156 __ ldr(ip, MemOperand(sp, kPointerSize)); |
| 1119 __ push(ip); | 1157 __ push(ip); |
| 1120 __ CallRuntime(Runtime::kToFastProperties, 1); | 1158 __ CallRuntime(Runtime::kToFastProperties, 1); |
| 1121 __ pop(r0); | 1159 __ pop(r0); |
| 1122 DropAndApply(1, context_, r0); | 1160 DropAndApply(1, context_, r0); |
| 1123 } else { | 1161 } else { |
| 1124 Apply(context_, r0); | 1162 Apply(context_, r0); |
| 1125 } | 1163 } |
| 1126 } | 1164 } |
| 1127 | 1165 |
| 1128 | 1166 |
| 1129 void FullCodeGenerator::EmitKeyedPropertyAssignment(Assignment* expr) { | 1167 void FullCodeGenerator::EmitKeyedPropertyAssignment(Assignment* expr) { |
| 1130 // Assignment to a property, using a keyed store IC. | 1168 // Assignment to a property, using a keyed store IC. |
| 1131 | 1169 |
| 1132 // If the assignment starts a block of assignments to the same object, | 1170 // If the assignment starts a block of assignments to the same object, |
| 1133 // change to slow case to avoid the quadratic behavior of repeatedly | 1171 // change to slow case to avoid the quadratic behavior of repeatedly |
| 1134 // adding fast properties. | 1172 // adding fast properties. |
| 1135 if (expr->starts_initialization_block()) { | 1173 if (expr->starts_initialization_block()) { |
| 1136 __ push(result_register()); | 1174 __ push(result_register()); |
| 1137 // Receiver is now under the key and value. | 1175 // Receiver is now under the key and value. |
| 1138 __ ldr(ip, MemOperand(sp, 2 * kPointerSize)); | 1176 __ ldr(ip, MemOperand(sp, 2 * kPointerSize)); |
| 1139 __ push(ip); | 1177 __ push(ip); |
| 1140 __ CallRuntime(Runtime::kToSlowProperties, 1); | 1178 __ CallRuntime(Runtime::kToSlowProperties, 1); |
| 1141 __ pop(result_register()); | 1179 __ pop(result_register()); |
| 1142 } | 1180 } |
| 1143 | 1181 |
| 1144 // Record source code position before IC call. | 1182 // Record source code position before IC call. |
| 1145 SetSourcePosition(expr->position()); | 1183 SetSourcePosition(expr->position()); |
| 1184 __ pop(r1); // Key. |
| 1185 // Load receiver to r2. Leave a copy in the stack if needed for turning the |
| 1186 // receiver into fast case. |
| 1187 if (expr->ends_initialization_block()) { |
| 1188 __ ldr(r2, MemOperand(sp)); |
| 1189 } else { |
| 1190 __ pop(r2); |
| 1191 } |
| 1192 |
| 1146 Handle<Code> ic(Builtins::builtin(Builtins::KeyedStoreIC_Initialize)); | 1193 Handle<Code> ic(Builtins::builtin(Builtins::KeyedStoreIC_Initialize)); |
| 1147 __ Call(ic, RelocInfo::CODE_TARGET); | 1194 __ Call(ic, RelocInfo::CODE_TARGET); |
| 1148 | 1195 |
| 1149 // If the assignment ends an initialization block, revert to fast case. | 1196 // If the assignment ends an initialization block, revert to fast case. |
| 1150 if (expr->ends_initialization_block()) { | 1197 if (expr->ends_initialization_block()) { |
| 1151 __ push(r0); // Result of assignment, saved even if not needed. | 1198 __ push(r0); // Result of assignment, saved even if not needed. |
| 1152 // Receiver is under the key and value. | 1199 // Receiver is under the result value. |
| 1153 __ ldr(ip, MemOperand(sp, 2 * kPointerSize)); | 1200 __ ldr(ip, MemOperand(sp, kPointerSize)); |
| 1154 __ push(ip); | 1201 __ push(ip); |
| 1155 __ CallRuntime(Runtime::kToFastProperties, 1); | 1202 __ CallRuntime(Runtime::kToFastProperties, 1); |
| 1156 __ pop(r0); | 1203 __ pop(r0); |
| 1204 DropAndApply(1, context_, r0); |
| 1205 } else { |
| 1206 Apply(context_, r0); |
| 1157 } | 1207 } |
| 1158 | |
| 1159 // Receiver and key are still on stack. | |
| 1160 DropAndApply(2, context_, r0); | |
| 1161 } | 1208 } |
| 1162 | 1209 |
| 1163 | 1210 |
| 1164 void FullCodeGenerator::VisitProperty(Property* expr) { | 1211 void FullCodeGenerator::VisitProperty(Property* expr) { |
| 1165 Comment cmnt(masm_, "[ Property"); | 1212 Comment cmnt(masm_, "[ Property"); |
| 1166 Expression* key = expr->key(); | 1213 Expression* key = expr->key(); |
| 1167 | 1214 |
| 1168 // Evaluate receiver. | |
| 1169 VisitForValue(expr->obj(), kStack); | |
| 1170 | |
| 1171 if (key->IsPropertyName()) { | 1215 if (key->IsPropertyName()) { |
| 1216 VisitForValue(expr->obj(), kAccumulator); |
| 1172 EmitNamedPropertyLoad(expr); | 1217 EmitNamedPropertyLoad(expr); |
| 1173 // Drop receiver left on the stack by IC. | 1218 Apply(context_, r0); |
| 1174 DropAndApply(1, context_, r0); | |
| 1175 } else { | 1219 } else { |
| 1220 VisitForValue(expr->obj(), kStack); |
| 1176 VisitForValue(expr->key(), kAccumulator); | 1221 VisitForValue(expr->key(), kAccumulator); |
| 1177 __ pop(r1); | 1222 __ pop(r1); |
| 1178 EmitKeyedPropertyLoad(expr); | 1223 EmitKeyedPropertyLoad(expr); |
| 1179 Apply(context_, r0); | 1224 Apply(context_, r0); |
| 1180 } | 1225 } |
| 1181 } | 1226 } |
| 1182 | 1227 |
| 1183 void FullCodeGenerator::EmitCallWithIC(Call* expr, | 1228 void FullCodeGenerator::EmitCallWithIC(Call* expr, |
| 1184 Handle<Object> name, | 1229 Handle<Object> name, |
| 1185 RelocInfo::Mode mode) { | 1230 RelocInfo::Mode mode) { |
| (...skipping 252 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1438 } | 1483 } |
| 1439 | 1484 |
| 1440 case Token::TYPEOF: { | 1485 case Token::TYPEOF: { |
| 1441 Comment cmnt(masm_, "[ UnaryOperation (TYPEOF)"); | 1486 Comment cmnt(masm_, "[ UnaryOperation (TYPEOF)"); |
| 1442 VariableProxy* proxy = expr->expression()->AsVariableProxy(); | 1487 VariableProxy* proxy = expr->expression()->AsVariableProxy(); |
| 1443 if (proxy != NULL && | 1488 if (proxy != NULL && |
| 1444 !proxy->var()->is_this() && | 1489 !proxy->var()->is_this() && |
| 1445 proxy->var()->is_global()) { | 1490 proxy->var()->is_global()) { |
| 1446 Comment cmnt(masm_, "Global variable"); | 1491 Comment cmnt(masm_, "Global variable"); |
| 1447 __ ldr(r0, CodeGenerator::GlobalObject()); | 1492 __ ldr(r0, CodeGenerator::GlobalObject()); |
| 1448 __ push(r0); | |
| 1449 __ mov(r2, Operand(proxy->name())); | 1493 __ mov(r2, Operand(proxy->name())); |
| 1450 Handle<Code> ic(Builtins::builtin(Builtins::LoadIC_Initialize)); | 1494 Handle<Code> ic(Builtins::builtin(Builtins::LoadIC_Initialize)); |
| 1451 // Use a regular load, not a contextual load, to avoid a reference | 1495 // Use a regular load, not a contextual load, to avoid a reference |
| 1452 // error. | 1496 // error. |
| 1453 __ Call(ic, RelocInfo::CODE_TARGET); | 1497 __ Call(ic, RelocInfo::CODE_TARGET); |
| 1454 __ str(r0, MemOperand(sp)); | 1498 __ push(r0); |
| 1455 } else if (proxy != NULL && | 1499 } else if (proxy != NULL && |
| 1456 proxy->var()->slot() != NULL && | 1500 proxy->var()->slot() != NULL && |
| 1457 proxy->var()->slot()->type() == Slot::LOOKUP) { | 1501 proxy->var()->slot()->type() == Slot::LOOKUP) { |
| 1458 __ mov(r0, Operand(proxy->name())); | 1502 __ mov(r0, Operand(proxy->name())); |
| 1459 __ stm(db_w, sp, cp.bit() | r0.bit()); | 1503 __ stm(db_w, sp, cp.bit() | r0.bit()); |
| 1460 __ CallRuntime(Runtime::kLoadContextSlotNoReferenceError, 2); | 1504 __ CallRuntime(Runtime::kLoadContextSlotNoReferenceError, 2); |
| 1461 __ push(r0); | 1505 __ push(r0); |
| 1462 } else { | 1506 } else { |
| 1463 // This expression cannot throw a reference error at the top level. | 1507 // This expression cannot throw a reference error at the top level. |
| 1464 VisitForValue(expr->expression(), kStack); | 1508 VisitForValue(expr->expression(), kStack); |
| (...skipping 85 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1550 location_ = kAccumulator; | 1594 location_ = kAccumulator; |
| 1551 EmitVariableLoad(expr->expression()->AsVariableProxy()->var(), | 1595 EmitVariableLoad(expr->expression()->AsVariableProxy()->var(), |
| 1552 Expression::kValue); | 1596 Expression::kValue); |
| 1553 location_ = saved_location; | 1597 location_ = saved_location; |
| 1554 } else { | 1598 } else { |
| 1555 // Reserve space for result of postfix operation. | 1599 // Reserve space for result of postfix operation. |
| 1556 if (expr->is_postfix() && context_ != Expression::kEffect) { | 1600 if (expr->is_postfix() && context_ != Expression::kEffect) { |
| 1557 __ mov(ip, Operand(Smi::FromInt(0))); | 1601 __ mov(ip, Operand(Smi::FromInt(0))); |
| 1558 __ push(ip); | 1602 __ push(ip); |
| 1559 } | 1603 } |
| 1560 VisitForValue(prop->obj(), kStack); | |
| 1561 if (assign_type == NAMED_PROPERTY) { | 1604 if (assign_type == NAMED_PROPERTY) { |
| 1605 // Put the object both on the stack and in the accumulator. |
| 1606 VisitForValue(prop->obj(), kAccumulator); |
| 1607 __ push(r0); |
| 1562 EmitNamedPropertyLoad(prop); | 1608 EmitNamedPropertyLoad(prop); |
| 1563 } else { | 1609 } else { |
| 1610 VisitForValue(prop->obj(), kStack); |
| 1564 VisitForValue(prop->key(), kAccumulator); | 1611 VisitForValue(prop->key(), kAccumulator); |
| 1565 __ ldr(r1, MemOperand(sp, 0)); | 1612 __ ldr(r1, MemOperand(sp, 0)); |
| 1566 __ push(r0); | 1613 __ push(r0); |
| 1567 EmitKeyedPropertyLoad(prop); | 1614 EmitKeyedPropertyLoad(prop); |
| 1568 } | 1615 } |
| 1569 } | 1616 } |
| 1570 | 1617 |
| 1571 // Call ToNumber only if operand is not a smi. | 1618 // Call ToNumber only if operand is not a smi. |
| 1572 Label no_conversion; | 1619 Label no_conversion; |
| 1573 __ tst(r0, Operand(kSmiTagMask)); | 1620 __ tst(r0, Operand(kSmiTagMask)); |
| (...skipping 50 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1624 __ mov(r1, Operand(Smi::FromInt(count_value))); | 1671 __ mov(r1, Operand(Smi::FromInt(count_value))); |
| 1625 GenericBinaryOpStub stub(Token::ADD, NO_OVERWRITE, r1, r0); | 1672 GenericBinaryOpStub stub(Token::ADD, NO_OVERWRITE, r1, r0); |
| 1626 __ CallStub(&stub); | 1673 __ CallStub(&stub); |
| 1627 __ bind(&done); | 1674 __ bind(&done); |
| 1628 | 1675 |
| 1629 // Store the value returned in r0. | 1676 // Store the value returned in r0. |
| 1630 switch (assign_type) { | 1677 switch (assign_type) { |
| 1631 case VARIABLE: | 1678 case VARIABLE: |
| 1632 if (expr->is_postfix()) { | 1679 if (expr->is_postfix()) { |
| 1633 EmitVariableAssignment(expr->expression()->AsVariableProxy()->var(), | 1680 EmitVariableAssignment(expr->expression()->AsVariableProxy()->var(), |
| 1681 Token::ASSIGN, |
| 1634 Expression::kEffect); | 1682 Expression::kEffect); |
| 1635 // For all contexts except kEffect: We have the result on | 1683 // For all contexts except kEffect: We have the result on |
| 1636 // top of the stack. | 1684 // top of the stack. |
| 1637 if (context_ != Expression::kEffect) { | 1685 if (context_ != Expression::kEffect) { |
| 1638 ApplyTOS(context_); | 1686 ApplyTOS(context_); |
| 1639 } | 1687 } |
| 1640 } else { | 1688 } else { |
| 1641 EmitVariableAssignment(expr->expression()->AsVariableProxy()->var(), | 1689 EmitVariableAssignment(expr->expression()->AsVariableProxy()->var(), |
| 1690 Token::ASSIGN, |
| 1642 context_); | 1691 context_); |
| 1643 } | 1692 } |
| 1644 break; | 1693 break; |
| 1645 case NAMED_PROPERTY: { | 1694 case NAMED_PROPERTY: { |
| 1646 __ mov(r2, Operand(prop->key()->AsLiteral()->handle())); | 1695 __ mov(r2, Operand(prop->key()->AsLiteral()->handle())); |
| 1647 __ pop(r1); | 1696 __ pop(r1); |
| 1648 Handle<Code> ic(Builtins::builtin(Builtins::StoreIC_Initialize)); | 1697 Handle<Code> ic(Builtins::builtin(Builtins::StoreIC_Initialize)); |
| 1649 __ Call(ic, RelocInfo::CODE_TARGET); | 1698 __ Call(ic, RelocInfo::CODE_TARGET); |
| 1650 if (expr->is_postfix()) { | 1699 if (expr->is_postfix()) { |
| 1651 if (context_ != Expression::kEffect) { | 1700 if (context_ != Expression::kEffect) { |
| 1652 ApplyTOS(context_); | 1701 ApplyTOS(context_); |
| 1653 } | 1702 } |
| 1654 } else { | 1703 } else { |
| 1655 Apply(context_, r0); | 1704 Apply(context_, r0); |
| 1656 } | 1705 } |
| 1657 break; | 1706 break; |
| 1658 } | 1707 } |
| 1659 case KEYED_PROPERTY: { | 1708 case KEYED_PROPERTY: { |
| 1709 __ pop(r1); // Key. |
| 1710 __ pop(r2); // Receiver. |
| 1660 Handle<Code> ic(Builtins::builtin(Builtins::KeyedStoreIC_Initialize)); | 1711 Handle<Code> ic(Builtins::builtin(Builtins::KeyedStoreIC_Initialize)); |
| 1661 __ Call(ic, RelocInfo::CODE_TARGET); | 1712 __ Call(ic, RelocInfo::CODE_TARGET); |
| 1662 if (expr->is_postfix()) { | 1713 if (expr->is_postfix()) { |
| 1663 __ Drop(2); // Result is on the stack under the key and the receiver. | |
| 1664 if (context_ != Expression::kEffect) { | 1714 if (context_ != Expression::kEffect) { |
| 1665 ApplyTOS(context_); | 1715 ApplyTOS(context_); |
| 1666 } | 1716 } |
| 1667 } else { | 1717 } else { |
| 1668 DropAndApply(2, context_, r0); | 1718 Apply(context_, r0); |
| 1669 } | 1719 } |
| 1670 break; | 1720 break; |
| 1671 } | 1721 } |
| 1672 } | 1722 } |
| 1673 } | 1723 } |
| 1674 | 1724 |
| 1675 | 1725 |
| 1676 void FullCodeGenerator::VisitBinaryOperation(BinaryOperation* expr) { | 1726 void FullCodeGenerator::VisitBinaryOperation(BinaryOperation* expr) { |
| 1677 Comment cmnt(masm_, "[ BinaryOperation"); | 1727 Comment cmnt(masm_, "[ BinaryOperation"); |
| 1678 switch (expr->op()) { | 1728 switch (expr->op()) { |
| (...skipping 191 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1870 __ pop(result_register()); | 1920 __ pop(result_register()); |
| 1871 ASSERT_EQ(1, kSmiTagSize + kSmiShiftSize); | 1921 ASSERT_EQ(1, kSmiTagSize + kSmiShiftSize); |
| 1872 __ mov(r1, Operand(r1, ASR, 1)); // Un-smi-tag value. | 1922 __ mov(r1, Operand(r1, ASR, 1)); // Un-smi-tag value. |
| 1873 __ add(pc, r1, Operand(masm_->CodeObject())); | 1923 __ add(pc, r1, Operand(masm_->CodeObject())); |
| 1874 } | 1924 } |
| 1875 | 1925 |
| 1876 | 1926 |
| 1877 #undef __ | 1927 #undef __ |
| 1878 | 1928 |
| 1879 } } // namespace v8::internal | 1929 } } // namespace v8::internal |
| 1930 |
| 1931 #endif // V8_TARGET_ARCH_ARM |
| OLD | NEW |