Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(206)

Side by Side Diff: src/arm/full-codegen-arm.cc

Issue 2084017: Version 2.2.11... (Closed) Base URL: http://v8.googlecode.com/svn/trunk/
Patch Set: Created 10 years, 7 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
« no previous file with comments | « src/arm/frames-arm.cc ('k') | src/arm/ic-arm.cc » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
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
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
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
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
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
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
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
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
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
OLDNEW
« no previous file with comments | « src/arm/frames-arm.cc ('k') | src/arm/ic-arm.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698