| OLD | NEW |
| 1 // Copyright 2011 the V8 project authors. All rights reserved. | 1 // Copyright 2011 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 734 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 745 kDontSaveFPRegs, | 745 kDontSaveFPRegs, |
| 746 EMIT_REMEMBERED_SET, | 746 EMIT_REMEMBERED_SET, |
| 747 OMIT_SMI_CHECK); | 747 OMIT_SMI_CHECK); |
| 748 } | 748 } |
| 749 break; | 749 break; |
| 750 | 750 |
| 751 case Slot::LOOKUP: { | 751 case Slot::LOOKUP: { |
| 752 __ mov(r2, Operand(variable->name())); | 752 __ mov(r2, Operand(variable->name())); |
| 753 // Declaration nodes are always introduced in one of two modes. | 753 // Declaration nodes are always introduced in one of two modes. |
| 754 ASSERT(mode == Variable::VAR || | 754 ASSERT(mode == Variable::VAR || |
| 755 mode == Variable::CONST); | 755 mode == Variable::CONST || |
| 756 PropertyAttributes attr = | 756 mode == Variable::LET); |
| 757 (mode == Variable::VAR) ? NONE : READ_ONLY; | 757 PropertyAttributes attr = (mode == Variable::CONST) ? READ_ONLY : NONE; |
| 758 __ mov(r1, Operand(Smi::FromInt(attr))); | 758 __ mov(r1, Operand(Smi::FromInt(attr))); |
| 759 // Push initial value, if any. | 759 // Push initial value, if any. |
| 760 // Note: For variables we must not push an initial value (such as | 760 // Note: For variables we must not push an initial value (such as |
| 761 // 'undefined') because we may have a (legal) redeclaration and we | 761 // 'undefined') because we may have a (legal) redeclaration and we |
| 762 // must not destroy the current value. | 762 // must not destroy the current value. |
| 763 if (mode == Variable::CONST) { | 763 if (mode == Variable::CONST) { |
| 764 __ LoadRoot(r0, Heap::kTheHoleValueRootIndex); | 764 __ LoadRoot(r0, Heap::kTheHoleValueRootIndex); |
| 765 __ Push(cp, r2, r1, r0); | 765 __ Push(cp, r2, r1, r0); |
| 766 } else if (function != NULL) { | 766 } else if (function != NULL) { |
| 767 __ Push(cp, r2, r1); | 767 __ Push(cp, r2, r1); |
| (...skipping 113 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 881 __ b(ne, &next_test); | 881 __ b(ne, &next_test); |
| 882 __ Drop(1); // Switch value is no longer needed. | 882 __ Drop(1); // Switch value is no longer needed. |
| 883 __ b(clause->body_target()); | 883 __ b(clause->body_target()); |
| 884 } | 884 } |
| 885 | 885 |
| 886 // Discard the test value and jump to the default if present, otherwise to | 886 // Discard the test value and jump to the default if present, otherwise to |
| 887 // the end of the statement. | 887 // the end of the statement. |
| 888 __ bind(&next_test); | 888 __ bind(&next_test); |
| 889 __ Drop(1); // Switch value is no longer needed. | 889 __ Drop(1); // Switch value is no longer needed. |
| 890 if (default_clause == NULL) { | 890 if (default_clause == NULL) { |
| 891 __ b(nested_statement.break_target()); | 891 __ b(nested_statement.break_label()); |
| 892 } else { | 892 } else { |
| 893 __ b(default_clause->body_target()); | 893 __ b(default_clause->body_target()); |
| 894 } | 894 } |
| 895 | 895 |
| 896 // Compile all the case bodies. | 896 // Compile all the case bodies. |
| 897 for (int i = 0; i < clauses->length(); i++) { | 897 for (int i = 0; i < clauses->length(); i++) { |
| 898 Comment cmnt(masm_, "[ Case body"); | 898 Comment cmnt(masm_, "[ Case body"); |
| 899 CaseClause* clause = clauses->at(i); | 899 CaseClause* clause = clauses->at(i); |
| 900 __ bind(clause->body_target()); | 900 __ bind(clause->body_target()); |
| 901 PrepareForBailoutForId(clause->EntryId(), NO_REGISTERS); | 901 PrepareForBailoutForId(clause->EntryId(), NO_REGISTERS); |
| 902 VisitStatements(clause->statements()); | 902 VisitStatements(clause->statements()); |
| 903 } | 903 } |
| 904 | 904 |
| 905 __ bind(nested_statement.break_target()); | 905 __ bind(nested_statement.break_label()); |
| 906 PrepareForBailoutForId(stmt->ExitId(), NO_REGISTERS); | 906 PrepareForBailoutForId(stmt->ExitId(), NO_REGISTERS); |
| 907 } | 907 } |
| 908 | 908 |
| 909 | 909 |
| 910 void FullCodeGenerator::VisitForInStatement(ForInStatement* stmt) { | 910 void FullCodeGenerator::VisitForInStatement(ForInStatement* stmt) { |
| 911 Comment cmnt(masm_, "[ ForInStatement"); | 911 Comment cmnt(masm_, "[ ForInStatement"); |
| 912 SetStatementPosition(stmt); | 912 SetStatementPosition(stmt); |
| 913 | 913 |
| 914 Label loop, exit; | 914 Label loop, exit; |
| 915 ForIn loop_statement(this, stmt); | 915 ForIn loop_statement(this, stmt); |
| (...skipping 110 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1026 __ Push(r1, r0); | 1026 __ Push(r1, r0); |
| 1027 __ ldr(r1, FieldMemOperand(r0, FixedArray::kLengthOffset)); | 1027 __ ldr(r1, FieldMemOperand(r0, FixedArray::kLengthOffset)); |
| 1028 __ mov(r0, Operand(Smi::FromInt(0))); | 1028 __ mov(r0, Operand(Smi::FromInt(0))); |
| 1029 __ Push(r1, r0); // Fixed array length (as smi) and initial index. | 1029 __ Push(r1, r0); // Fixed array length (as smi) and initial index. |
| 1030 | 1030 |
| 1031 // Generate code for doing the condition check. | 1031 // Generate code for doing the condition check. |
| 1032 __ bind(&loop); | 1032 __ bind(&loop); |
| 1033 // Load the current count to r0, load the length to r1. | 1033 // Load the current count to r0, load the length to r1. |
| 1034 __ Ldrd(r0, r1, MemOperand(sp, 0 * kPointerSize)); | 1034 __ Ldrd(r0, r1, MemOperand(sp, 0 * kPointerSize)); |
| 1035 __ cmp(r0, r1); // Compare to the array length. | 1035 __ cmp(r0, r1); // Compare to the array length. |
| 1036 __ b(hs, loop_statement.break_target()); | 1036 __ b(hs, loop_statement.break_label()); |
| 1037 | 1037 |
| 1038 // Get the current entry of the array into register r3. | 1038 // Get the current entry of the array into register r3. |
| 1039 __ ldr(r2, MemOperand(sp, 2 * kPointerSize)); | 1039 __ ldr(r2, MemOperand(sp, 2 * kPointerSize)); |
| 1040 __ add(r2, r2, Operand(FixedArray::kHeaderSize - kHeapObjectTag)); | 1040 __ add(r2, r2, Operand(FixedArray::kHeaderSize - kHeapObjectTag)); |
| 1041 __ ldr(r3, MemOperand(r2, r0, LSL, kPointerSizeLog2 - kSmiTagSize)); | 1041 __ ldr(r3, MemOperand(r2, r0, LSL, kPointerSizeLog2 - kSmiTagSize)); |
| 1042 | 1042 |
| 1043 // Get the expected map from the stack or a zero map in the | 1043 // Get the expected map from the stack or a zero map in the |
| 1044 // permanent slow case into register r2. | 1044 // permanent slow case into register r2. |
| 1045 __ ldr(r2, MemOperand(sp, 3 * kPointerSize)); | 1045 __ ldr(r2, MemOperand(sp, 3 * kPointerSize)); |
| 1046 | 1046 |
| 1047 // Check if the expected map still matches that of the enumerable. | 1047 // Check if the expected map still matches that of the enumerable. |
| 1048 // If not, we have to filter the key. | 1048 // If not, we have to filter the key. |
| 1049 Label update_each; | 1049 Label update_each; |
| 1050 __ ldr(r1, MemOperand(sp, 4 * kPointerSize)); | 1050 __ ldr(r1, MemOperand(sp, 4 * kPointerSize)); |
| 1051 __ ldr(r4, FieldMemOperand(r1, HeapObject::kMapOffset)); | 1051 __ ldr(r4, FieldMemOperand(r1, HeapObject::kMapOffset)); |
| 1052 __ cmp(r4, Operand(r2)); | 1052 __ cmp(r4, Operand(r2)); |
| 1053 __ b(eq, &update_each); | 1053 __ b(eq, &update_each); |
| 1054 | 1054 |
| 1055 // Convert the entry to a string or (smi) 0 if it isn't a property | 1055 // Convert the entry to a string or (smi) 0 if it isn't a property |
| 1056 // any more. If the property has been removed while iterating, we | 1056 // any more. If the property has been removed while iterating, we |
| 1057 // just skip it. | 1057 // just skip it. |
| 1058 __ push(r1); // Enumerable. | 1058 __ push(r1); // Enumerable. |
| 1059 __ push(r3); // Current entry. | 1059 __ push(r3); // Current entry. |
| 1060 __ InvokeBuiltin(Builtins::FILTER_KEY, CALL_FUNCTION); | 1060 __ InvokeBuiltin(Builtins::FILTER_KEY, CALL_FUNCTION); |
| 1061 __ mov(r3, Operand(r0), SetCC); | 1061 __ mov(r3, Operand(r0), SetCC); |
| 1062 __ b(eq, loop_statement.continue_target()); | 1062 __ b(eq, loop_statement.continue_label()); |
| 1063 | 1063 |
| 1064 // Update the 'each' property or variable from the possibly filtered | 1064 // Update the 'each' property or variable from the possibly filtered |
| 1065 // entry in register r3. | 1065 // entry in register r3. |
| 1066 __ bind(&update_each); | 1066 __ bind(&update_each); |
| 1067 __ mov(result_register(), r3); | 1067 __ mov(result_register(), r3); |
| 1068 // Perform the assignment as if via '='. | 1068 // Perform the assignment as if via '='. |
| 1069 { EffectContext context(this); | 1069 { EffectContext context(this); |
| 1070 EmitAssignment(stmt->each(), stmt->AssignmentId()); | 1070 EmitAssignment(stmt->each(), stmt->AssignmentId()); |
| 1071 } | 1071 } |
| 1072 | 1072 |
| 1073 // Generate code for the body of the loop. | 1073 // Generate code for the body of the loop. |
| 1074 Visit(stmt->body()); | 1074 Visit(stmt->body()); |
| 1075 | 1075 |
| 1076 // Generate code for the going to the next element by incrementing | 1076 // Generate code for the going to the next element by incrementing |
| 1077 // the index (smi) stored on top of the stack. | 1077 // the index (smi) stored on top of the stack. |
| 1078 __ bind(loop_statement.continue_target()); | 1078 __ bind(loop_statement.continue_label()); |
| 1079 __ pop(r0); | 1079 __ pop(r0); |
| 1080 __ add(r0, r0, Operand(Smi::FromInt(1))); | 1080 __ add(r0, r0, Operand(Smi::FromInt(1))); |
| 1081 __ push(r0); | 1081 __ push(r0); |
| 1082 | 1082 |
| 1083 EmitStackCheck(stmt); | 1083 EmitStackCheck(stmt); |
| 1084 __ b(&loop); | 1084 __ b(&loop); |
| 1085 | 1085 |
| 1086 // Remove the pointers stored on the stack. | 1086 // Remove the pointers stored on the stack. |
| 1087 __ bind(loop_statement.break_target()); | 1087 __ bind(loop_statement.break_label()); |
| 1088 __ Drop(5); | 1088 __ Drop(5); |
| 1089 | 1089 |
| 1090 // Exit and decrement the loop depth. | 1090 // Exit and decrement the loop depth. |
| 1091 __ bind(&exit); | 1091 __ bind(&exit); |
| 1092 decrement_loop_depth(); | 1092 decrement_loop_depth(); |
| 1093 } | 1093 } |
| 1094 | 1094 |
| 1095 | 1095 |
| 1096 void FullCodeGenerator::EmitNewClosure(Handle<SharedFunctionInfo> info, | 1096 void FullCodeGenerator::EmitNewClosure(Handle<SharedFunctionInfo> info, |
| 1097 bool pretenure) { | 1097 bool pretenure) { |
| (...skipping 2949 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 4047 __ CompareObjectType(r0, r0, r1, FIRST_NONSTRING_TYPE); | 4047 __ CompareObjectType(r0, r0, r1, FIRST_NONSTRING_TYPE); |
| 4048 __ b(ge, if_false); | 4048 __ b(ge, if_false); |
| 4049 __ ldrb(r1, FieldMemOperand(r0, Map::kBitFieldOffset)); | 4049 __ ldrb(r1, FieldMemOperand(r0, Map::kBitFieldOffset)); |
| 4050 __ tst(r1, Operand(1 << Map::kIsUndetectable)); | 4050 __ tst(r1, Operand(1 << Map::kIsUndetectable)); |
| 4051 Split(eq, if_true, if_false, fall_through); | 4051 Split(eq, if_true, if_false, fall_through); |
| 4052 } else if (check->Equals(isolate()->heap()->boolean_symbol())) { | 4052 } else if (check->Equals(isolate()->heap()->boolean_symbol())) { |
| 4053 __ CompareRoot(r0, Heap::kTrueValueRootIndex); | 4053 __ CompareRoot(r0, Heap::kTrueValueRootIndex); |
| 4054 __ b(eq, if_true); | 4054 __ b(eq, if_true); |
| 4055 __ CompareRoot(r0, Heap::kFalseValueRootIndex); | 4055 __ CompareRoot(r0, Heap::kFalseValueRootIndex); |
| 4056 Split(eq, if_true, if_false, fall_through); | 4056 Split(eq, if_true, if_false, fall_through); |
| 4057 } else if (FLAG_harmony_typeof && |
| 4058 check->Equals(isolate()->heap()->null_symbol())) { |
| 4059 __ CompareRoot(r0, Heap::kNullValueRootIndex); |
| 4060 Split(eq, if_true, if_false, fall_through); |
| 4057 } else if (check->Equals(isolate()->heap()->undefined_symbol())) { | 4061 } else if (check->Equals(isolate()->heap()->undefined_symbol())) { |
| 4058 __ CompareRoot(r0, Heap::kUndefinedValueRootIndex); | 4062 __ CompareRoot(r0, Heap::kUndefinedValueRootIndex); |
| 4059 __ b(eq, if_true); | 4063 __ b(eq, if_true); |
| 4060 __ JumpIfSmi(r0, if_false); | 4064 __ JumpIfSmi(r0, if_false); |
| 4061 // Check for undetectable objects => true. | 4065 // Check for undetectable objects => true. |
| 4062 __ ldr(r0, FieldMemOperand(r0, HeapObject::kMapOffset)); | 4066 __ ldr(r0, FieldMemOperand(r0, HeapObject::kMapOffset)); |
| 4063 __ ldrb(r1, FieldMemOperand(r0, Map::kBitFieldOffset)); | 4067 __ ldrb(r1, FieldMemOperand(r0, Map::kBitFieldOffset)); |
| 4064 __ tst(r1, Operand(1 << Map::kIsUndetectable)); | 4068 __ tst(r1, Operand(1 << Map::kIsUndetectable)); |
| 4065 Split(ne, if_true, if_false, fall_through); | 4069 Split(ne, if_true, if_false, fall_through); |
| 4066 | 4070 |
| 4067 } else if (check->Equals(isolate()->heap()->function_symbol())) { | 4071 } else if (check->Equals(isolate()->heap()->function_symbol())) { |
| 4068 __ JumpIfSmi(r0, if_false); | 4072 __ JumpIfSmi(r0, if_false); |
| 4069 __ CompareObjectType(r0, r1, r0, FIRST_CALLABLE_SPEC_OBJECT_TYPE); | 4073 __ CompareObjectType(r0, r1, r0, FIRST_CALLABLE_SPEC_OBJECT_TYPE); |
| 4070 Split(ge, if_true, if_false, fall_through); | 4074 Split(ge, if_true, if_false, fall_through); |
| 4071 | 4075 |
| 4072 } else if (check->Equals(isolate()->heap()->object_symbol())) { | 4076 } else if (check->Equals(isolate()->heap()->object_symbol())) { |
| 4073 __ JumpIfSmi(r0, if_false); | 4077 __ JumpIfSmi(r0, if_false); |
| 4074 __ CompareRoot(r0, Heap::kNullValueRootIndex); | 4078 if (!FLAG_harmony_typeof) { |
| 4075 __ b(eq, if_true); | 4079 __ CompareRoot(r0, Heap::kNullValueRootIndex); |
| 4080 __ b(eq, if_true); |
| 4081 } |
| 4076 // Check for JS objects => true. | 4082 // Check for JS objects => true. |
| 4077 __ CompareObjectType(r0, r0, r1, FIRST_NONCALLABLE_SPEC_OBJECT_TYPE); | 4083 __ CompareObjectType(r0, r0, r1, FIRST_NONCALLABLE_SPEC_OBJECT_TYPE); |
| 4078 __ b(lt, if_false); | 4084 __ b(lt, if_false); |
| 4079 __ CompareInstanceType(r0, r1, LAST_NONCALLABLE_SPEC_OBJECT_TYPE); | 4085 __ CompareInstanceType(r0, r1, LAST_NONCALLABLE_SPEC_OBJECT_TYPE); |
| 4080 __ b(gt, if_false); | 4086 __ b(gt, if_false); |
| 4081 // Check for undetectable objects => false. | 4087 // Check for undetectable objects => false. |
| 4082 __ ldrb(r1, FieldMemOperand(r0, Map::kBitFieldOffset)); | 4088 __ ldrb(r1, FieldMemOperand(r0, Map::kBitFieldOffset)); |
| 4083 __ tst(r1, Operand(1 << Map::kIsUndetectable)); | 4089 __ tst(r1, Operand(1 << Map::kIsUndetectable)); |
| 4084 Split(eq, if_true, if_false, fall_through); | 4090 Split(eq, if_true, if_false, fall_through); |
| 4085 } else { | 4091 } else { |
| (...skipping 54 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 4140 PrepareForBailoutBeforeSplit(TOS_REG, true, if_true, if_false); | 4146 PrepareForBailoutBeforeSplit(TOS_REG, true, if_true, if_false); |
| 4141 // The stub returns 0 for true. | 4147 // The stub returns 0 for true. |
| 4142 __ tst(r0, r0); | 4148 __ tst(r0, r0); |
| 4143 Split(eq, if_true, if_false, fall_through); | 4149 Split(eq, if_true, if_false, fall_through); |
| 4144 break; | 4150 break; |
| 4145 } | 4151 } |
| 4146 | 4152 |
| 4147 default: { | 4153 default: { |
| 4148 VisitForAccumulatorValue(expr->right()); | 4154 VisitForAccumulatorValue(expr->right()); |
| 4149 Condition cond = eq; | 4155 Condition cond = eq; |
| 4150 bool strict = false; | |
| 4151 switch (op) { | 4156 switch (op) { |
| 4152 case Token::EQ_STRICT: | 4157 case Token::EQ_STRICT: |
| 4153 strict = true; | |
| 4154 // Fall through | |
| 4155 case Token::EQ: | 4158 case Token::EQ: |
| 4156 cond = eq; | 4159 cond = eq; |
| 4157 __ pop(r1); | 4160 __ pop(r1); |
| 4158 break; | 4161 break; |
| 4159 case Token::LT: | 4162 case Token::LT: |
| 4160 cond = lt; | 4163 cond = lt; |
| 4161 __ pop(r1); | 4164 __ pop(r1); |
| 4162 break; | 4165 break; |
| 4163 case Token::GT: | 4166 case Token::GT: |
| 4164 // Reverse left and right sides to obtain ECMA-262 conversion order. | 4167 // Reverse left and right sides to obtain ECMA-262 conversion order. |
| (...skipping 151 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 4316 __ mov(r1, Operand(r1, ASR, 1)); // Un-smi-tag value. | 4319 __ mov(r1, Operand(r1, ASR, 1)); // Un-smi-tag value. |
| 4317 __ add(pc, r1, Operand(masm_->CodeObject())); | 4320 __ add(pc, r1, Operand(masm_->CodeObject())); |
| 4318 } | 4321 } |
| 4319 | 4322 |
| 4320 | 4323 |
| 4321 #undef __ | 4324 #undef __ |
| 4322 | 4325 |
| 4323 } } // namespace v8::internal | 4326 } } // namespace v8::internal |
| 4324 | 4327 |
| 4325 #endif // V8_TARGET_ARCH_ARM | 4328 #endif // V8_TARGET_ARCH_ARM |
| OLD | NEW |