| OLD | NEW |
| 1 // Copyright 2015 the V8 project authors. All rights reserved. | 1 // Copyright 2015 the V8 project authors. All rights reserved. |
| 2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
| 4 | 4 |
| 5 #include "src/code-factory.h" | 5 #include "src/code-factory.h" |
| 6 #include "src/compiler/code-assembler.h" | 6 #include "src/compiler/code-assembler.h" |
| 7 #include "src/isolate.h" | 7 #include "src/isolate.h" |
| 8 #include "test/cctest/compiler/code-assembler-tester.h" | 8 #include "test/cctest/compiler/code-assembler-tester.h" |
| 9 #include "test/cctest/compiler/function-tester.h" | 9 #include "test/cctest/compiler/function-tester.h" |
| 10 | 10 |
| 11 namespace v8 { | 11 namespace v8 { |
| 12 namespace internal { | 12 namespace internal { |
| 13 namespace compiler { | 13 namespace compiler { |
| 14 | 14 |
| 15 typedef CodeAssemblerTesterImpl<CodeAssembler> CodeAssemblerTester; | |
| 16 | |
| 17 namespace { | 15 namespace { |
| 18 | 16 |
| 19 Node* SmiTag(CodeAssemblerTester& m, Node* value) { | 17 Node* SmiTag(CodeAssembler& m, Node* value) { |
| 20 int32_t constant_value; | 18 int32_t constant_value; |
| 21 if (m.ToInt32Constant(value, constant_value) && | 19 if (m.ToInt32Constant(value, constant_value) && |
| 22 Smi::IsValid(constant_value)) { | 20 Smi::IsValid(constant_value)) { |
| 23 return m.SmiConstant(Smi::FromInt(constant_value)); | 21 return m.SmiConstant(Smi::FromInt(constant_value)); |
| 24 } | 22 } |
| 25 return m.WordShl(value, m.IntPtrConstant(kSmiShiftSize + kSmiTagSize)); | 23 return m.WordShl(value, m.IntPtrConstant(kSmiShiftSize + kSmiTagSize)); |
| 26 } | 24 } |
| 27 | 25 |
| 28 Node* UndefinedConstant(CodeAssemblerTester& m) { | 26 Node* UndefinedConstant(CodeAssembler& m) { |
| 29 return m.LoadRoot(Heap::kUndefinedValueRootIndex); | 27 return m.LoadRoot(Heap::kUndefinedValueRootIndex); |
| 30 } | 28 } |
| 31 | 29 |
| 32 Node* LoadObjectField(CodeAssemblerTester& m, Node* object, int offset, | 30 Node* LoadObjectField(CodeAssembler& m, Node* object, int offset, |
| 33 MachineType rep = MachineType::AnyTagged()) { | 31 MachineType rep = MachineType::AnyTagged()) { |
| 34 return m.Load(rep, object, m.IntPtrConstant(offset - kHeapObjectTag)); | 32 return m.Load(rep, object, m.IntPtrConstant(offset - kHeapObjectTag)); |
| 35 } | 33 } |
| 36 | 34 |
| 37 } // namespace | 35 } // namespace |
| 38 | 36 |
| 39 TEST(SimpleSmiReturn) { | 37 TEST(SimpleSmiReturn) { |
| 40 Isolate* isolate(CcTest::InitIsolateOnce()); | 38 Isolate* isolate(CcTest::InitIsolateOnce()); |
| 41 VoidDescriptor descriptor(isolate); | 39 CodeAssemblerTester data(isolate); |
| 42 CodeAssemblerTester m(isolate, descriptor); | 40 CodeAssembler m(data.state()); |
| 43 m.Return(SmiTag(m, m.Int32Constant(37))); | 41 m.Return(SmiTag(m, m.Int32Constant(37))); |
| 44 Handle<Code> code = m.GenerateCode(); | 42 Handle<Code> code = data.GenerateCode(); |
| 45 FunctionTester ft(descriptor, code); | 43 FunctionTester ft(code); |
| 46 MaybeHandle<Object> result = ft.Call(); | 44 MaybeHandle<Object> result = ft.Call(); |
| 47 CHECK_EQ(37, Handle<Smi>::cast(result.ToHandleChecked())->value()); | 45 CHECK_EQ(37, Handle<Smi>::cast(result.ToHandleChecked())->value()); |
| 48 } | 46 } |
| 49 | 47 |
| 50 TEST(SimpleIntPtrReturn) { | 48 TEST(SimpleIntPtrReturn) { |
| 51 Isolate* isolate(CcTest::InitIsolateOnce()); | 49 Isolate* isolate(CcTest::InitIsolateOnce()); |
| 52 VoidDescriptor descriptor(isolate); | 50 CodeAssemblerTester data(isolate); |
| 53 CodeAssemblerTester m(isolate, descriptor); | 51 CodeAssembler m(data.state()); |
| 54 int test; | 52 int test; |
| 55 m.Return(m.IntPtrConstant(reinterpret_cast<intptr_t>(&test))); | 53 m.Return(m.IntPtrConstant(reinterpret_cast<intptr_t>(&test))); |
| 56 Handle<Code> code = m.GenerateCode(); | 54 Handle<Code> code = data.GenerateCode(); |
| 57 FunctionTester ft(descriptor, code); | 55 FunctionTester ft(code); |
| 58 MaybeHandle<Object> result = ft.Call(); | 56 MaybeHandle<Object> result = ft.Call(); |
| 59 CHECK_EQ(reinterpret_cast<intptr_t>(&test), | 57 CHECK_EQ(reinterpret_cast<intptr_t>(&test), |
| 60 reinterpret_cast<intptr_t>(*result.ToHandleChecked())); | 58 reinterpret_cast<intptr_t>(*result.ToHandleChecked())); |
| 61 } | 59 } |
| 62 | 60 |
| 63 TEST(SimpleDoubleReturn) { | 61 TEST(SimpleDoubleReturn) { |
| 64 Isolate* isolate(CcTest::InitIsolateOnce()); | 62 Isolate* isolate(CcTest::InitIsolateOnce()); |
| 65 VoidDescriptor descriptor(isolate); | 63 CodeAssemblerTester data(isolate); |
| 66 CodeAssemblerTester m(isolate, descriptor); | 64 CodeAssembler m(data.state()); |
| 67 m.Return(m.NumberConstant(0.5)); | 65 m.Return(m.NumberConstant(0.5)); |
| 68 Handle<Code> code = m.GenerateCode(); | 66 Handle<Code> code = data.GenerateCode(); |
| 69 FunctionTester ft(descriptor, code); | 67 FunctionTester ft(code); |
| 70 MaybeHandle<Object> result = ft.Call(); | 68 MaybeHandle<Object> result = ft.Call(); |
| 71 CHECK_EQ(0.5, Handle<HeapNumber>::cast(result.ToHandleChecked())->value()); | 69 CHECK_EQ(0.5, Handle<HeapNumber>::cast(result.ToHandleChecked())->value()); |
| 72 } | 70 } |
| 73 | 71 |
| 74 TEST(SimpleCallRuntime1Arg) { | 72 TEST(SimpleCallRuntime1Arg) { |
| 75 Isolate* isolate(CcTest::InitIsolateOnce()); | 73 Isolate* isolate(CcTest::InitIsolateOnce()); |
| 76 VoidDescriptor descriptor(isolate); | 74 CodeAssemblerTester data(isolate); |
| 77 CodeAssemblerTester m(isolate, descriptor); | 75 CodeAssembler m(data.state()); |
| 78 Node* context = m.HeapConstant(Handle<Context>(isolate->native_context())); | 76 Node* context = m.HeapConstant(Handle<Context>(isolate->native_context())); |
| 79 Node* b = SmiTag(m, m.Int32Constant(0)); | 77 Node* b = SmiTag(m, m.Int32Constant(0)); |
| 80 m.Return(m.CallRuntime(Runtime::kNumberToSmi, context, b)); | 78 m.Return(m.CallRuntime(Runtime::kNumberToSmi, context, b)); |
| 81 Handle<Code> code = m.GenerateCode(); | 79 Handle<Code> code = data.GenerateCode(); |
| 82 FunctionTester ft(descriptor, code); | 80 FunctionTester ft(code); |
| 83 MaybeHandle<Object> result = ft.Call(); | 81 MaybeHandle<Object> result = ft.Call(); |
| 84 CHECK_EQ(0, Handle<Smi>::cast(result.ToHandleChecked())->value()); | 82 CHECK_EQ(0, Handle<Smi>::cast(result.ToHandleChecked())->value()); |
| 85 } | 83 } |
| 86 | 84 |
| 87 TEST(SimpleTailCallRuntime1Arg) { | 85 TEST(SimpleTailCallRuntime1Arg) { |
| 88 Isolate* isolate(CcTest::InitIsolateOnce()); | 86 Isolate* isolate(CcTest::InitIsolateOnce()); |
| 89 VoidDescriptor descriptor(isolate); | 87 CodeAssemblerTester data(isolate); |
| 90 CodeAssemblerTester m(isolate, descriptor); | 88 CodeAssembler m(data.state()); |
| 91 Node* context = m.HeapConstant(Handle<Context>(isolate->native_context())); | 89 Node* context = m.HeapConstant(Handle<Context>(isolate->native_context())); |
| 92 Node* b = SmiTag(m, m.Int32Constant(0)); | 90 Node* b = SmiTag(m, m.Int32Constant(0)); |
| 93 m.TailCallRuntime(Runtime::kNumberToSmi, context, b); | 91 m.TailCallRuntime(Runtime::kNumberToSmi, context, b); |
| 94 Handle<Code> code = m.GenerateCode(); | 92 Handle<Code> code = data.GenerateCode(); |
| 95 FunctionTester ft(descriptor, code); | 93 FunctionTester ft(code); |
| 96 MaybeHandle<Object> result = ft.Call(); | 94 MaybeHandle<Object> result = ft.Call(); |
| 97 CHECK_EQ(0, Handle<Smi>::cast(result.ToHandleChecked())->value()); | 95 CHECK_EQ(0, Handle<Smi>::cast(result.ToHandleChecked())->value()); |
| 98 } | 96 } |
| 99 | 97 |
| 100 TEST(SimpleCallRuntime2Arg) { | 98 TEST(SimpleCallRuntime2Arg) { |
| 101 Isolate* isolate(CcTest::InitIsolateOnce()); | 99 Isolate* isolate(CcTest::InitIsolateOnce()); |
| 102 VoidDescriptor descriptor(isolate); | 100 CodeAssemblerTester data(isolate); |
| 103 CodeAssemblerTester m(isolate, descriptor); | 101 CodeAssembler m(data.state()); |
| 104 Node* context = m.HeapConstant(Handle<Context>(isolate->native_context())); | 102 Node* context = m.HeapConstant(Handle<Context>(isolate->native_context())); |
| 105 Node* a = SmiTag(m, m.Int32Constant(2)); | 103 Node* a = SmiTag(m, m.Int32Constant(2)); |
| 106 Node* b = SmiTag(m, m.Int32Constant(4)); | 104 Node* b = SmiTag(m, m.Int32Constant(4)); |
| 107 m.Return(m.CallRuntime(Runtime::kAdd, context, a, b)); | 105 m.Return(m.CallRuntime(Runtime::kAdd, context, a, b)); |
| 108 Handle<Code> code = m.GenerateCode(); | 106 Handle<Code> code = data.GenerateCode(); |
| 109 FunctionTester ft(descriptor, code); | 107 FunctionTester ft(code); |
| 110 MaybeHandle<Object> result = ft.Call(); | 108 MaybeHandle<Object> result = ft.Call(); |
| 111 CHECK_EQ(6, Handle<Smi>::cast(result.ToHandleChecked())->value()); | 109 CHECK_EQ(6, Handle<Smi>::cast(result.ToHandleChecked())->value()); |
| 112 } | 110 } |
| 113 | 111 |
| 114 TEST(SimpleTailCallRuntime2Arg) { | 112 TEST(SimpleTailCallRuntime2Arg) { |
| 115 Isolate* isolate(CcTest::InitIsolateOnce()); | 113 Isolate* isolate(CcTest::InitIsolateOnce()); |
| 116 VoidDescriptor descriptor(isolate); | 114 CodeAssemblerTester data(isolate); |
| 117 CodeAssemblerTester m(isolate, descriptor); | 115 CodeAssembler m(data.state()); |
| 118 Node* context = m.HeapConstant(Handle<Context>(isolate->native_context())); | 116 Node* context = m.HeapConstant(Handle<Context>(isolate->native_context())); |
| 119 Node* a = SmiTag(m, m.Int32Constant(2)); | 117 Node* a = SmiTag(m, m.Int32Constant(2)); |
| 120 Node* b = SmiTag(m, m.Int32Constant(4)); | 118 Node* b = SmiTag(m, m.Int32Constant(4)); |
| 121 m.TailCallRuntime(Runtime::kAdd, context, a, b); | 119 m.TailCallRuntime(Runtime::kAdd, context, a, b); |
| 122 Handle<Code> code = m.GenerateCode(); | 120 Handle<Code> code = data.GenerateCode(); |
| 123 FunctionTester ft(descriptor, code); | 121 FunctionTester ft(code); |
| 124 MaybeHandle<Object> result = ft.Call(); | 122 MaybeHandle<Object> result = ft.Call(); |
| 125 CHECK_EQ(6, Handle<Smi>::cast(result.ToHandleChecked())->value()); | 123 CHECK_EQ(6, Handle<Smi>::cast(result.ToHandleChecked())->value()); |
| 126 } | 124 } |
| 127 | 125 |
| 128 namespace { | 126 namespace { |
| 129 | 127 |
| 130 Handle<JSFunction> CreateSumAllArgumentsFunction(FunctionTester& ft) { | 128 Handle<JSFunction> CreateSumAllArgumentsFunction(FunctionTester& ft) { |
| 131 const char* source = | 129 const char* source = |
| 132 "(function() {\n" | 130 "(function() {\n" |
| 133 " var sum = 0 + this;\n" | 131 " var sum = 0 + this;\n" |
| 134 " for (var i = 0; i < arguments.length; i++) {\n" | 132 " for (var i = 0; i < arguments.length; i++) {\n" |
| 135 " sum += arguments[i];\n" | 133 " sum += arguments[i];\n" |
| 136 " }\n" | 134 " }\n" |
| 137 " return sum;\n" | 135 " return sum;\n" |
| 138 "})"; | 136 "})"; |
| 139 return ft.NewFunction(source); | 137 return ft.NewFunction(source); |
| 140 } | 138 } |
| 141 | 139 |
| 142 } // namespace | 140 } // namespace |
| 143 | 141 |
| 144 TEST(SimpleCallJSFunction0Arg) { | 142 TEST(SimpleCallJSFunction0Arg) { |
| 145 Isolate* isolate(CcTest::InitIsolateOnce()); | 143 Isolate* isolate(CcTest::InitIsolateOnce()); |
| 146 const int kNumParams = 1; | 144 const int kNumParams = 1; |
| 147 CodeAssemblerTester m(isolate, kNumParams); | 145 CodeAssemblerTester data(isolate, kNumParams); |
| 146 CodeAssembler m(data.state()); |
| 148 { | 147 { |
| 149 Node* function = m.Parameter(0); | 148 Node* function = m.Parameter(0); |
| 150 Node* context = m.Parameter(kNumParams + 2); | 149 Node* context = m.Parameter(kNumParams + 2); |
| 151 | 150 |
| 152 Node* receiver = SmiTag(m, m.Int32Constant(42)); | 151 Node* receiver = SmiTag(m, m.Int32Constant(42)); |
| 153 | 152 |
| 154 Callable callable = CodeFactory::Call(isolate); | 153 Callable callable = CodeFactory::Call(isolate); |
| 155 Node* result = m.CallJS(callable, context, function, receiver); | 154 Node* result = m.CallJS(callable, context, function, receiver); |
| 156 m.Return(result); | 155 m.Return(result); |
| 157 } | 156 } |
| 158 Handle<Code> code = m.GenerateCode(); | 157 Handle<Code> code = data.GenerateCode(); |
| 159 FunctionTester ft(code, kNumParams); | 158 FunctionTester ft(code, kNumParams); |
| 160 | 159 |
| 161 Handle<JSFunction> sum = CreateSumAllArgumentsFunction(ft); | 160 Handle<JSFunction> sum = CreateSumAllArgumentsFunction(ft); |
| 162 MaybeHandle<Object> result = ft.Call(sum); | 161 MaybeHandle<Object> result = ft.Call(sum); |
| 163 CHECK_EQ(Smi::FromInt(42), *result.ToHandleChecked()); | 162 CHECK_EQ(Smi::FromInt(42), *result.ToHandleChecked()); |
| 164 } | 163 } |
| 165 | 164 |
| 166 TEST(SimpleCallJSFunction1Arg) { | 165 TEST(SimpleCallJSFunction1Arg) { |
| 167 Isolate* isolate(CcTest::InitIsolateOnce()); | 166 Isolate* isolate(CcTest::InitIsolateOnce()); |
| 168 const int kNumParams = 2; | 167 const int kNumParams = 2; |
| 169 CodeAssemblerTester m(isolate, kNumParams); | 168 CodeAssemblerTester data(isolate, kNumParams); |
| 169 CodeAssembler m(data.state()); |
| 170 { | 170 { |
| 171 Node* function = m.Parameter(0); | 171 Node* function = m.Parameter(0); |
| 172 Node* context = m.Parameter(1); | 172 Node* context = m.Parameter(1); |
| 173 | 173 |
| 174 Node* receiver = SmiTag(m, m.Int32Constant(42)); | 174 Node* receiver = SmiTag(m, m.Int32Constant(42)); |
| 175 Node* a = SmiTag(m, m.Int32Constant(13)); | 175 Node* a = SmiTag(m, m.Int32Constant(13)); |
| 176 | 176 |
| 177 Callable callable = CodeFactory::Call(isolate); | 177 Callable callable = CodeFactory::Call(isolate); |
| 178 Node* result = m.CallJS(callable, context, function, receiver, a); | 178 Node* result = m.CallJS(callable, context, function, receiver, a); |
| 179 m.Return(result); | 179 m.Return(result); |
| 180 } | 180 } |
| 181 Handle<Code> code = m.GenerateCode(); | 181 Handle<Code> code = data.GenerateCode(); |
| 182 FunctionTester ft(code, kNumParams); | 182 FunctionTester ft(code, kNumParams); |
| 183 | 183 |
| 184 Handle<JSFunction> sum = CreateSumAllArgumentsFunction(ft); | 184 Handle<JSFunction> sum = CreateSumAllArgumentsFunction(ft); |
| 185 MaybeHandle<Object> result = ft.Call(sum); | 185 MaybeHandle<Object> result = ft.Call(sum); |
| 186 CHECK_EQ(Smi::FromInt(55), *result.ToHandleChecked()); | 186 CHECK_EQ(Smi::FromInt(55), *result.ToHandleChecked()); |
| 187 } | 187 } |
| 188 | 188 |
| 189 TEST(SimpleCallJSFunction2Arg) { | 189 TEST(SimpleCallJSFunction2Arg) { |
| 190 Isolate* isolate(CcTest::InitIsolateOnce()); | 190 Isolate* isolate(CcTest::InitIsolateOnce()); |
| 191 const int kNumParams = 2; | 191 const int kNumParams = 2; |
| 192 CodeAssemblerTester m(isolate, kNumParams); | 192 CodeAssemblerTester data(isolate, kNumParams); |
| 193 CodeAssembler m(data.state()); |
| 193 { | 194 { |
| 194 Node* function = m.Parameter(0); | 195 Node* function = m.Parameter(0); |
| 195 Node* context = m.Parameter(1); | 196 Node* context = m.Parameter(1); |
| 196 | 197 |
| 197 Node* receiver = SmiTag(m, m.Int32Constant(42)); | 198 Node* receiver = SmiTag(m, m.Int32Constant(42)); |
| 198 Node* a = SmiTag(m, m.Int32Constant(13)); | 199 Node* a = SmiTag(m, m.Int32Constant(13)); |
| 199 Node* b = SmiTag(m, m.Int32Constant(153)); | 200 Node* b = SmiTag(m, m.Int32Constant(153)); |
| 200 | 201 |
| 201 Callable callable = CodeFactory::Call(isolate); | 202 Callable callable = CodeFactory::Call(isolate); |
| 202 Node* result = m.CallJS(callable, context, function, receiver, a, b); | 203 Node* result = m.CallJS(callable, context, function, receiver, a, b); |
| 203 m.Return(result); | 204 m.Return(result); |
| 204 } | 205 } |
| 205 Handle<Code> code = m.GenerateCode(); | 206 Handle<Code> code = data.GenerateCode(); |
| 206 FunctionTester ft(code, kNumParams); | 207 FunctionTester ft(code, kNumParams); |
| 207 | 208 |
| 208 Handle<JSFunction> sum = CreateSumAllArgumentsFunction(ft); | 209 Handle<JSFunction> sum = CreateSumAllArgumentsFunction(ft); |
| 209 MaybeHandle<Object> result = ft.Call(sum); | 210 MaybeHandle<Object> result = ft.Call(sum); |
| 210 CHECK_EQ(Smi::FromInt(208), *result.ToHandleChecked()); | 211 CHECK_EQ(Smi::FromInt(208), *result.ToHandleChecked()); |
| 211 } | 212 } |
| 212 | 213 |
| 213 TEST(VariableMerge1) { | 214 TEST(VariableMerge1) { |
| 214 Isolate* isolate(CcTest::InitIsolateOnce()); | 215 Isolate* isolate(CcTest::InitIsolateOnce()); |
| 215 VoidDescriptor descriptor(isolate); | 216 CodeAssemblerTester data(isolate); |
| 216 CodeAssemblerTester m(isolate, descriptor); | 217 CodeAssembler m(data.state()); |
| 217 CodeStubAssembler::Variable var1(&m, MachineRepresentation::kTagged); | 218 CodeStubAssembler::Variable var1(&m, MachineRepresentation::kTagged); |
| 218 CodeStubAssembler::Label l1(&m), l2(&m), merge(&m); | 219 CodeStubAssembler::Label l1(&m), l2(&m), merge(&m); |
| 219 Node* temp = m.Int32Constant(0); | 220 Node* temp = m.Int32Constant(0); |
| 220 var1.Bind(temp); | 221 var1.Bind(temp); |
| 221 m.Branch(m.Int32Constant(1), &l1, &l2); | 222 m.Branch(m.Int32Constant(1), &l1, &l2); |
| 222 m.Bind(&l1); | 223 m.Bind(&l1); |
| 223 CHECK_EQ(var1.value(), temp); | 224 CHECK_EQ(var1.value(), temp); |
| 224 m.Goto(&merge); | 225 m.Goto(&merge); |
| 225 m.Bind(&l2); | 226 m.Bind(&l2); |
| 226 CHECK_EQ(var1.value(), temp); | 227 CHECK_EQ(var1.value(), temp); |
| 227 m.Goto(&merge); | 228 m.Goto(&merge); |
| 228 m.Bind(&merge); | 229 m.Bind(&merge); |
| 229 CHECK_EQ(var1.value(), temp); | 230 CHECK_EQ(var1.value(), temp); |
| 230 } | 231 } |
| 231 | 232 |
| 232 TEST(VariableMerge2) { | 233 TEST(VariableMerge2) { |
| 233 Isolate* isolate(CcTest::InitIsolateOnce()); | 234 Isolate* isolate(CcTest::InitIsolateOnce()); |
| 234 VoidDescriptor descriptor(isolate); | 235 CodeAssemblerTester data(isolate); |
| 235 CodeAssemblerTester m(isolate, descriptor); | 236 CodeAssembler m(data.state()); |
| 236 CodeStubAssembler::Variable var1(&m, MachineRepresentation::kTagged); | 237 CodeStubAssembler::Variable var1(&m, MachineRepresentation::kTagged); |
| 237 CodeStubAssembler::Label l1(&m), l2(&m), merge(&m); | 238 CodeStubAssembler::Label l1(&m), l2(&m), merge(&m); |
| 238 Node* temp = m.Int32Constant(0); | 239 Node* temp = m.Int32Constant(0); |
| 239 var1.Bind(temp); | 240 var1.Bind(temp); |
| 240 m.Branch(m.Int32Constant(1), &l1, &l2); | 241 m.Branch(m.Int32Constant(1), &l1, &l2); |
| 241 m.Bind(&l1); | 242 m.Bind(&l1); |
| 242 CHECK_EQ(var1.value(), temp); | 243 CHECK_EQ(var1.value(), temp); |
| 243 m.Goto(&merge); | 244 m.Goto(&merge); |
| 244 m.Bind(&l2); | 245 m.Bind(&l2); |
| 245 Node* temp2 = m.Int32Constant(2); | 246 Node* temp2 = m.Int32Constant(2); |
| 246 var1.Bind(temp2); | 247 var1.Bind(temp2); |
| 247 CHECK_EQ(var1.value(), temp2); | 248 CHECK_EQ(var1.value(), temp2); |
| 248 m.Goto(&merge); | 249 m.Goto(&merge); |
| 249 m.Bind(&merge); | 250 m.Bind(&merge); |
| 250 CHECK_NE(var1.value(), temp); | 251 CHECK_NE(var1.value(), temp); |
| 251 } | 252 } |
| 252 | 253 |
| 253 TEST(VariableMerge3) { | 254 TEST(VariableMerge3) { |
| 254 Isolate* isolate(CcTest::InitIsolateOnce()); | 255 Isolate* isolate(CcTest::InitIsolateOnce()); |
| 255 VoidDescriptor descriptor(isolate); | 256 CodeAssemblerTester data(isolate); |
| 256 CodeAssemblerTester m(isolate, descriptor); | 257 CodeAssembler m(data.state()); |
| 257 CodeStubAssembler::Variable var1(&m, MachineRepresentation::kTagged); | 258 CodeStubAssembler::Variable var1(&m, MachineRepresentation::kTagged); |
| 258 CodeStubAssembler::Variable var2(&m, MachineRepresentation::kTagged); | 259 CodeStubAssembler::Variable var2(&m, MachineRepresentation::kTagged); |
| 259 CodeStubAssembler::Label l1(&m), l2(&m), merge(&m); | 260 CodeStubAssembler::Label l1(&m), l2(&m), merge(&m); |
| 260 Node* temp = m.Int32Constant(0); | 261 Node* temp = m.Int32Constant(0); |
| 261 var1.Bind(temp); | 262 var1.Bind(temp); |
| 262 var2.Bind(temp); | 263 var2.Bind(temp); |
| 263 m.Branch(m.Int32Constant(1), &l1, &l2); | 264 m.Branch(m.Int32Constant(1), &l1, &l2); |
| 264 m.Bind(&l1); | 265 m.Bind(&l1); |
| 265 CHECK_EQ(var1.value(), temp); | 266 CHECK_EQ(var1.value(), temp); |
| 266 m.Goto(&merge); | 267 m.Goto(&merge); |
| 267 m.Bind(&l2); | 268 m.Bind(&l2); |
| 268 Node* temp2 = m.Int32Constant(2); | 269 Node* temp2 = m.Int32Constant(2); |
| 269 var1.Bind(temp2); | 270 var1.Bind(temp2); |
| 270 CHECK_EQ(var1.value(), temp2); | 271 CHECK_EQ(var1.value(), temp2); |
| 271 m.Goto(&merge); | 272 m.Goto(&merge); |
| 272 m.Bind(&merge); | 273 m.Bind(&merge); |
| 273 CHECK_NE(var1.value(), temp); | 274 CHECK_NE(var1.value(), temp); |
| 274 CHECK_NE(var1.value(), temp2); | 275 CHECK_NE(var1.value(), temp2); |
| 275 CHECK_EQ(var2.value(), temp); | 276 CHECK_EQ(var2.value(), temp); |
| 276 } | 277 } |
| 277 | 278 |
| 278 TEST(VariableMergeBindFirst) { | 279 TEST(VariableMergeBindFirst) { |
| 279 Isolate* isolate(CcTest::InitIsolateOnce()); | 280 Isolate* isolate(CcTest::InitIsolateOnce()); |
| 280 VoidDescriptor descriptor(isolate); | 281 CodeAssemblerTester data(isolate); |
| 281 CodeAssemblerTester m(isolate, descriptor); | 282 CodeAssembler m(data.state()); |
| 282 CodeStubAssembler::Variable var1(&m, MachineRepresentation::kTagged); | 283 CodeStubAssembler::Variable var1(&m, MachineRepresentation::kTagged); |
| 283 CodeStubAssembler::Label l1(&m), l2(&m), merge(&m, &var1), end(&m); | 284 CodeStubAssembler::Label l1(&m), l2(&m), merge(&m, &var1), end(&m); |
| 284 Node* temp = m.Int32Constant(0); | 285 Node* temp = m.Int32Constant(0); |
| 285 var1.Bind(temp); | 286 var1.Bind(temp); |
| 286 m.Branch(m.Int32Constant(1), &l1, &l2); | 287 m.Branch(m.Int32Constant(1), &l1, &l2); |
| 287 m.Bind(&l1); | 288 m.Bind(&l1); |
| 288 CHECK_EQ(var1.value(), temp); | 289 CHECK_EQ(var1.value(), temp); |
| 289 m.Goto(&merge); | 290 m.Goto(&merge); |
| 290 m.Bind(&merge); | 291 m.Bind(&merge); |
| 291 CHECK(var1.value() != temp); | 292 CHECK(var1.value() != temp); |
| 292 CHECK(var1.value() != nullptr); | 293 CHECK(var1.value() != nullptr); |
| 293 m.Goto(&end); | 294 m.Goto(&end); |
| 294 m.Bind(&l2); | 295 m.Bind(&l2); |
| 295 Node* temp2 = m.Int32Constant(2); | 296 Node* temp2 = m.Int32Constant(2); |
| 296 var1.Bind(temp2); | 297 var1.Bind(temp2); |
| 297 CHECK_EQ(var1.value(), temp2); | 298 CHECK_EQ(var1.value(), temp2); |
| 298 m.Goto(&merge); | 299 m.Goto(&merge); |
| 299 m.Bind(&end); | 300 m.Bind(&end); |
| 300 CHECK(var1.value() != temp); | 301 CHECK(var1.value() != temp); |
| 301 CHECK(var1.value() != nullptr); | 302 CHECK(var1.value() != nullptr); |
| 302 } | 303 } |
| 303 | 304 |
| 304 TEST(VariableMergeSwitch) { | 305 TEST(VariableMergeSwitch) { |
| 305 Isolate* isolate(CcTest::InitIsolateOnce()); | 306 Isolate* isolate(CcTest::InitIsolateOnce()); |
| 306 VoidDescriptor descriptor(isolate); | 307 CodeAssemblerTester data(isolate); |
| 307 CodeAssemblerTester m(isolate, descriptor); | 308 CodeAssembler m(data.state()); |
| 308 CodeStubAssembler::Variable var1(&m, MachineRepresentation::kTagged); | 309 CodeStubAssembler::Variable var1(&m, MachineRepresentation::kTagged); |
| 309 CodeStubAssembler::Label l1(&m), l2(&m), default_label(&m); | 310 CodeStubAssembler::Label l1(&m), l2(&m), default_label(&m); |
| 310 CodeStubAssembler::Label* labels[] = {&l1, &l2}; | 311 CodeStubAssembler::Label* labels[] = {&l1, &l2}; |
| 311 int32_t values[] = {1, 2}; | 312 int32_t values[] = {1, 2}; |
| 312 Node* temp = m.Int32Constant(0); | 313 Node* temp = m.Int32Constant(0); |
| 313 var1.Bind(temp); | 314 var1.Bind(temp); |
| 314 m.Switch(m.Int32Constant(2), &default_label, values, labels, 2); | 315 m.Switch(m.Int32Constant(2), &default_label, values, labels, 2); |
| 315 m.Bind(&l1); | 316 m.Bind(&l1); |
| 316 DCHECK_EQ(temp, var1.value()); | 317 DCHECK_EQ(temp, var1.value()); |
| 317 m.Return(temp); | 318 m.Return(temp); |
| 318 m.Bind(&l2); | 319 m.Bind(&l2); |
| 319 DCHECK_EQ(temp, var1.value()); | 320 DCHECK_EQ(temp, var1.value()); |
| 320 m.Return(temp); | 321 m.Return(temp); |
| 321 m.Bind(&default_label); | 322 m.Bind(&default_label); |
| 322 DCHECK_EQ(temp, var1.value()); | 323 DCHECK_EQ(temp, var1.value()); |
| 323 m.Return(temp); | 324 m.Return(temp); |
| 324 } | 325 } |
| 325 | 326 |
| 326 TEST(SplitEdgeBranchMerge) { | 327 TEST(SplitEdgeBranchMerge) { |
| 327 Isolate* isolate(CcTest::InitIsolateOnce()); | 328 Isolate* isolate(CcTest::InitIsolateOnce()); |
| 328 VoidDescriptor descriptor(isolate); | 329 CodeAssemblerTester data(isolate); |
| 329 CodeAssemblerTester m(isolate, descriptor); | 330 CodeAssembler m(data.state()); |
| 330 CodeStubAssembler::Label l1(&m), merge(&m); | 331 CodeStubAssembler::Label l1(&m), merge(&m); |
| 331 m.Branch(m.Int32Constant(1), &l1, &merge); | 332 m.Branch(m.Int32Constant(1), &l1, &merge); |
| 332 m.Bind(&l1); | 333 m.Bind(&l1); |
| 333 m.Goto(&merge); | 334 m.Goto(&merge); |
| 334 m.Bind(&merge); | 335 m.Bind(&merge); |
| 335 USE(m.GenerateCode()); | 336 USE(data.GenerateCode()); |
| 336 } | 337 } |
| 337 | 338 |
| 338 TEST(SplitEdgeSwitchMerge) { | 339 TEST(SplitEdgeSwitchMerge) { |
| 339 Isolate* isolate(CcTest::InitIsolateOnce()); | 340 Isolate* isolate(CcTest::InitIsolateOnce()); |
| 340 VoidDescriptor descriptor(isolate); | 341 CodeAssemblerTester data(isolate); |
| 341 CodeAssemblerTester m(isolate, descriptor); | 342 CodeAssembler m(data.state()); |
| 342 CodeStubAssembler::Label l1(&m), l2(&m), l3(&m), default_label(&m); | 343 CodeStubAssembler::Label l1(&m), l2(&m), l3(&m), default_label(&m); |
| 343 CodeStubAssembler::Label* labels[] = {&l1, &l2}; | 344 CodeStubAssembler::Label* labels[] = {&l1, &l2}; |
| 344 int32_t values[] = {1, 2}; | 345 int32_t values[] = {1, 2}; |
| 345 m.Branch(m.Int32Constant(1), &l3, &l1); | 346 m.Branch(m.Int32Constant(1), &l3, &l1); |
| 346 m.Bind(&l3); | 347 m.Bind(&l3); |
| 347 m.Switch(m.Int32Constant(2), &default_label, values, labels, 2); | 348 m.Switch(m.Int32Constant(2), &default_label, values, labels, 2); |
| 348 m.Bind(&l1); | 349 m.Bind(&l1); |
| 349 m.Goto(&l2); | 350 m.Goto(&l2); |
| 350 m.Bind(&l2); | 351 m.Bind(&l2); |
| 351 m.Goto(&default_label); | 352 m.Goto(&default_label); |
| 352 m.Bind(&default_label); | 353 m.Bind(&default_label); |
| 353 USE(m.GenerateCode()); | 354 USE(data.GenerateCode()); |
| 354 } | 355 } |
| 355 | 356 |
| 356 TEST(TestToConstant) { | 357 TEST(TestToConstant) { |
| 357 Isolate* isolate(CcTest::InitIsolateOnce()); | 358 Isolate* isolate(CcTest::InitIsolateOnce()); |
| 358 VoidDescriptor descriptor(isolate); | 359 CodeAssemblerTester data(isolate); |
| 359 CodeAssemblerTester m(isolate, descriptor); | 360 CodeAssembler m(data.state()); |
| 360 int32_t value32; | 361 int32_t value32; |
| 361 int64_t value64; | 362 int64_t value64; |
| 362 Node* a = m.Int32Constant(5); | 363 Node* a = m.Int32Constant(5); |
| 363 CHECK(m.ToInt32Constant(a, value32)); | 364 CHECK(m.ToInt32Constant(a, value32)); |
| 364 CHECK(m.ToInt64Constant(a, value64)); | 365 CHECK(m.ToInt64Constant(a, value64)); |
| 365 | 366 |
| 366 a = m.Int64Constant(static_cast<int64_t>(1) << 32); | 367 a = m.Int64Constant(static_cast<int64_t>(1) << 32); |
| 367 CHECK(!m.ToInt32Constant(a, value32)); | 368 CHECK(!m.ToInt32Constant(a, value32)); |
| 368 CHECK(m.ToInt64Constant(a, value64)); | 369 CHECK(m.ToInt64Constant(a, value64)); |
| 369 | 370 |
| 370 a = m.Int64Constant(13); | 371 a = m.Int64Constant(13); |
| 371 CHECK(m.ToInt32Constant(a, value32)); | 372 CHECK(m.ToInt32Constant(a, value32)); |
| 372 CHECK(m.ToInt64Constant(a, value64)); | 373 CHECK(m.ToInt64Constant(a, value64)); |
| 373 | 374 |
| 374 a = UndefinedConstant(m); | 375 a = UndefinedConstant(m); |
| 375 CHECK(!m.ToInt32Constant(a, value32)); | 376 CHECK(!m.ToInt32Constant(a, value32)); |
| 376 CHECK(!m.ToInt64Constant(a, value64)); | 377 CHECK(!m.ToInt64Constant(a, value64)); |
| 377 | 378 |
| 378 a = UndefinedConstant(m); | 379 a = UndefinedConstant(m); |
| 379 CHECK(!m.ToInt32Constant(a, value32)); | 380 CHECK(!m.ToInt32Constant(a, value32)); |
| 380 CHECK(!m.ToInt64Constant(a, value64)); | 381 CHECK(!m.ToInt64Constant(a, value64)); |
| 381 } | 382 } |
| 382 | 383 |
| 383 TEST(DeferredCodePhiHints) { | 384 TEST(DeferredCodePhiHints) { |
| 384 typedef compiler::Node Node; | 385 typedef compiler::Node Node; |
| 385 typedef CodeStubAssembler::Label Label; | 386 typedef CodeStubAssembler::Label Label; |
| 386 typedef CodeStubAssembler::Variable Variable; | 387 typedef CodeStubAssembler::Variable Variable; |
| 387 Isolate* isolate(CcTest::InitIsolateOnce()); | 388 Isolate* isolate(CcTest::InitIsolateOnce()); |
| 388 VoidDescriptor descriptor(isolate); | 389 CodeAssemblerTester data(isolate); |
| 389 CodeAssemblerTester m(isolate, descriptor); | 390 CodeAssembler m(data.state()); |
| 390 Label block1(&m, Label::kDeferred); | 391 Label block1(&m, Label::kDeferred); |
| 391 m.Goto(&block1); | 392 m.Goto(&block1); |
| 392 m.Bind(&block1); | 393 m.Bind(&block1); |
| 393 { | 394 { |
| 394 Variable var_object(&m, MachineRepresentation::kTagged); | 395 Variable var_object(&m, MachineRepresentation::kTagged); |
| 395 Label loop(&m, &var_object); | 396 Label loop(&m, &var_object); |
| 396 var_object.Bind(m.IntPtrConstant(0)); | 397 var_object.Bind(m.IntPtrConstant(0)); |
| 397 m.Goto(&loop); | 398 m.Goto(&loop); |
| 398 m.Bind(&loop); | 399 m.Bind(&loop); |
| 399 { | 400 { |
| 400 Node* map = LoadObjectField(m, var_object.value(), JSObject::kMapOffset); | 401 Node* map = LoadObjectField(m, var_object.value(), JSObject::kMapOffset); |
| 401 var_object.Bind(map); | 402 var_object.Bind(map); |
| 402 m.Goto(&loop); | 403 m.Goto(&loop); |
| 403 } | 404 } |
| 404 } | 405 } |
| 405 CHECK(!m.GenerateCode().is_null()); | 406 CHECK(!data.GenerateCode().is_null()); |
| 406 } | 407 } |
| 407 | 408 |
| 408 TEST(TestOutOfScopeVariable) { | 409 TEST(TestOutOfScopeVariable) { |
| 409 typedef CodeStubAssembler::Label Label; | 410 typedef CodeStubAssembler::Label Label; |
| 410 typedef CodeStubAssembler::Variable Variable; | 411 typedef CodeStubAssembler::Variable Variable; |
| 411 Isolate* isolate(CcTest::InitIsolateOnce()); | 412 Isolate* isolate(CcTest::InitIsolateOnce()); |
| 412 VoidDescriptor descriptor(isolate); | 413 CodeAssemblerTester data(isolate); |
| 413 CodeAssemblerTester m(isolate, descriptor); | 414 CodeAssembler m(data.state()); |
| 414 Label block1(&m); | 415 Label block1(&m); |
| 415 Label block2(&m); | 416 Label block2(&m); |
| 416 Label block3(&m); | 417 Label block3(&m); |
| 417 Label block4(&m); | 418 Label block4(&m); |
| 418 m.Branch(m.WordEqual(m.Parameter(0), m.IntPtrConstant(0)), &block1, &block4); | 419 m.Branch(m.WordEqual(m.Parameter(0), m.IntPtrConstant(0)), &block1, &block4); |
| 419 m.Bind(&block4); | 420 m.Bind(&block4); |
| 420 { | 421 { |
| 421 Variable var_object(&m, MachineRepresentation::kTagged); | 422 Variable var_object(&m, MachineRepresentation::kTagged); |
| 422 m.Branch(m.WordEqual(m.Parameter(0), m.IntPtrConstant(0)), &block2, | 423 m.Branch(m.WordEqual(m.Parameter(0), m.IntPtrConstant(0)), &block2, |
| 423 &block3); | 424 &block3); |
| 424 | 425 |
| 425 m.Bind(&block2); | 426 m.Bind(&block2); |
| 426 var_object.Bind(m.IntPtrConstant(55)); | 427 var_object.Bind(m.IntPtrConstant(55)); |
| 427 m.Goto(&block1); | 428 m.Goto(&block1); |
| 428 | 429 |
| 429 m.Bind(&block3); | 430 m.Bind(&block3); |
| 430 var_object.Bind(m.IntPtrConstant(66)); | 431 var_object.Bind(m.IntPtrConstant(66)); |
| 431 m.Goto(&block1); | 432 m.Goto(&block1); |
| 432 } | 433 } |
| 433 m.Bind(&block1); | 434 m.Bind(&block1); |
| 434 CHECK(!m.GenerateCode().is_null()); | 435 CHECK(!data.GenerateCode().is_null()); |
| 435 } | 436 } |
| 436 | 437 |
| 437 } // namespace compiler | 438 } // namespace compiler |
| 438 } // namespace internal | 439 } // namespace internal |
| 439 } // namespace v8 | 440 } // namespace v8 |
| OLD | NEW |