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/v8.h" | 5 #include "src/v8.h" |
6 | 6 |
7 #include "src/compiler.h" | 7 #include "src/compiler.h" |
8 #include "src/interpreter/bytecode-array-iterator.h" | 8 #include "src/interpreter/bytecode-array-iterator.h" |
9 #include "src/interpreter/bytecode-generator.h" | 9 #include "src/interpreter/bytecode-generator.h" |
10 #include "src/interpreter/interpreter.h" | 10 #include "src/interpreter/interpreter.h" |
(...skipping 143 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
154 // Structure for containing expected bytecode snippets. | 154 // Structure for containing expected bytecode snippets. |
155 template<typename T, int C = 6> | 155 template<typename T, int C = 6> |
156 struct ExpectedSnippet { | 156 struct ExpectedSnippet { |
157 const char* code_snippet; | 157 const char* code_snippet; |
158 int frame_size; | 158 int frame_size; |
159 int parameter_count; | 159 int parameter_count; |
160 int bytecode_length; | 160 int bytecode_length; |
161 const uint8_t bytecode[2048]; | 161 const uint8_t bytecode[2048]; |
162 int constant_count; | 162 int constant_count; |
163 T constants[C]; | 163 T constants[C]; |
164 int handler_count; | |
165 struct { | |
166 int start; | |
167 int end; | |
168 int handler; | |
169 } handlers[C]; | |
164 }; | 170 }; |
165 | 171 |
166 | 172 |
167 static void CheckConstant(int expected, Object* actual) { | 173 static void CheckConstant(int expected, Object* actual) { |
168 CHECK_EQ(expected, Smi::cast(actual)->value()); | 174 CHECK_EQ(expected, Smi::cast(actual)->value()); |
169 } | 175 } |
170 | 176 |
171 | 177 |
172 static void CheckConstant(double expected, Object* actual) { | 178 static void CheckConstant(double expected, Object* actual) { |
173 CHECK_EQ(expected, HeapNumber::cast(actual)->value()); | 179 CHECK_EQ(expected, HeapNumber::cast(actual)->value()); |
(...skipping 24 matching lines...) Expand all Loading... | |
198 CHECK_EQ(expected.parameter_count, actual->parameter_count()); | 204 CHECK_EQ(expected.parameter_count, actual->parameter_count()); |
199 CHECK_EQ(expected.bytecode_length, actual->length()); | 205 CHECK_EQ(expected.bytecode_length, actual->length()); |
200 if (expected.constant_count == 0) { | 206 if (expected.constant_count == 0) { |
201 CHECK_EQ(CcTest::heap()->empty_fixed_array(), actual->constant_pool()); | 207 CHECK_EQ(CcTest::heap()->empty_fixed_array(), actual->constant_pool()); |
202 } else { | 208 } else { |
203 CHECK_EQ(expected.constant_count, actual->constant_pool()->length()); | 209 CHECK_EQ(expected.constant_count, actual->constant_pool()->length()); |
204 for (int i = 0; i < expected.constant_count; i++) { | 210 for (int i = 0; i < expected.constant_count; i++) { |
205 CheckConstant(expected.constants[i], actual->constant_pool()->get(i)); | 211 CheckConstant(expected.constants[i], actual->constant_pool()->get(i)); |
206 } | 212 } |
207 } | 213 } |
214 if (expected.handler_count == 0) { | |
215 CHECK_EQ(CcTest::heap()->empty_fixed_array(), actual->handler_table()); | |
216 } else { | |
217 static const int kHTSize = 4; // see HandlerTable::kRangeEntrySize | |
218 static const int kHTStart = 0; // see HandlerTable::kRangeStartIndex | |
219 static const int kHTEnd = 1; // see HandlerTable::kRangeEndIndex | |
220 static const int kHTHandler = 2; // see HandlerTable::kRangeHandlerIndex | |
221 HandlerTable* table = HandlerTable::cast(actual->handler_table()); | |
222 CHECK_EQ(expected.handler_count * kHTSize, table->length()); | |
223 for (int i = 0; i < expected.handler_count; i++) { | |
224 int start = Smi::cast(table->get(i * kHTSize + kHTStart))->value(); | |
225 int end = Smi::cast(table->get(i * kHTSize + kHTEnd))->value(); | |
226 int handler = Smi::cast(table->get(i * kHTSize + kHTHandler))->value(); | |
227 CHECK_EQ(expected.handlers[i].start, start); | |
228 CHECK_EQ(expected.handlers[i].end, end); | |
229 CHECK_EQ(expected.handlers[i].handler, handler >> 1); | |
230 } | |
231 } | |
208 | 232 |
209 BytecodeArrayIterator iterator(actual); | 233 BytecodeArrayIterator iterator(actual); |
210 int i = 0; | 234 int i = 0; |
211 while (!iterator.done()) { | 235 while (!iterator.done()) { |
212 int bytecode_index = i++; | 236 int bytecode_index = i++; |
213 Bytecode bytecode = iterator.current_bytecode(); | 237 Bytecode bytecode = iterator.current_bytecode(); |
214 if (Bytecodes::ToByte(bytecode) != expected.bytecode[bytecode_index]) { | 238 if (Bytecodes::ToByte(bytecode) != expected.bytecode[bytecode_index]) { |
215 std::ostringstream stream; | 239 std::ostringstream stream; |
216 stream << "Check failed: expected bytecode [" << bytecode_index | 240 stream << "Check failed: expected bytecode [" << bytecode_index |
217 << "] to be " << Bytecodes::ToString(static_cast<Bytecode>( | 241 << "] to be " << Bytecodes::ToString(static_cast<Bytecode>( |
(...skipping 3918 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
4136 helper.MakeTopLevelBytecode(snippets[i].code_snippet); | 4160 helper.MakeTopLevelBytecode(snippets[i].code_snippet); |
4137 CheckBytecodeArrayEqual(snippets[i], bytecode_array); | 4161 CheckBytecodeArrayEqual(snippets[i], bytecode_array); |
4138 } | 4162 } |
4139 } | 4163 } |
4140 | 4164 |
4141 | 4165 |
4142 TEST(TryCatch) { | 4166 TEST(TryCatch) { |
4143 InitializedHandleScope handle_scope; | 4167 InitializedHandleScope handle_scope; |
4144 BytecodeGeneratorHelper helper; | 4168 BytecodeGeneratorHelper helper; |
4145 | 4169 |
4146 // TODO(rmcilroy): modify tests when we have real try catch support. | 4170 int closure = Register::function_closure().index(); |
4147 ExpectedSnippet<int> snippets[] = { | 4171 |
4172 ExpectedSnippet<const char*> snippets[] = { | |
4148 {"try { return 1; } catch(e) { return 2; }", | 4173 {"try { return 1; } catch(e) { return 2; }", |
4149 kPointerSize, | 4174 5 * kPointerSize, |
4150 1, | 4175 1, |
4151 3, | 4176 23, |
4152 { | 4177 { |
4153 B(LdaSmi8), U8(1), // | 4178 B(LdaSmi8), U8(1), // |
4154 B(Return), // | 4179 B(Return), // |
4180 B(Star), R(3), // | |
4181 B(LdaConstant), U8(0), // | |
4182 B(Star), R(2), // | |
4183 B(Ldar), R(closure), // | |
4184 B(Star), R(4), // | |
4185 B(CallRuntime), U16(Runtime::kPushCatchContext), R(2), U8(3), // | |
4186 B(LdaSmi8), U8(2), // | |
4187 B(Return), // | |
4188 // TODO(mstarzinger): Potential optimization, elide next bytes. | |
4189 B(LdaUndefined), // | |
4190 B(Return), // | |
4155 }, | 4191 }, |
4156 0}, | 4192 1, |
4193 {"e"}, | |
4194 1, | |
4195 {{0, 3, 3}}}, | |
4157 }; | 4196 }; |
4158 | 4197 |
4159 for (size_t i = 0; i < arraysize(snippets); i++) { | 4198 for (size_t i = 0; i < arraysize(snippets); i++) { |
4160 Handle<BytecodeArray> bytecode_array = | 4199 Handle<BytecodeArray> bytecode_array = |
4161 helper.MakeBytecodeForFunctionBody(snippets[i].code_snippet); | 4200 helper.MakeBytecodeForFunctionBody(snippets[i].code_snippet); |
4162 CheckBytecodeArrayEqual(snippets[i], bytecode_array); | 4201 CheckBytecodeArrayEqual(snippets[i], bytecode_array); |
4163 } | 4202 } |
4164 } | 4203 } |
4165 | 4204 |
4166 | 4205 |
4167 TEST(TryFinally) { | 4206 TEST(TryFinally) { |
4168 InitializedHandleScope handle_scope; | 4207 InitializedHandleScope handle_scope; |
4169 BytecodeGeneratorHelper helper; | 4208 BytecodeGeneratorHelper helper; |
4170 | 4209 |
4171 // TODO(rmcilroy): modify tests when we have real try finally support. | 4210 int closure = Register::function_closure().index(); |
4172 ExpectedSnippet<int> snippets[] = { | 4211 |
4212 ExpectedSnippet<const char*> snippets[] = { | |
4173 {"var a = 1; try { a = 2; } finally { a = 3; }", | 4213 {"var a = 1; try { a = 2; } finally { a = 3; }", |
4174 kPointerSize, | 4214 2 * kPointerSize, |
4175 1, | 4215 1, |
4176 14, | 4216 14, |
4177 { | 4217 { |
4178 B(LdaSmi8), U8(1), // | 4218 B(LdaSmi8), U8(1), // |
4179 B(Star), R(0), // | 4219 B(Star), R(0), // |
4180 B(LdaSmi8), U8(2), // | 4220 B(LdaSmi8), U8(2), // |
4181 B(Star), R(0), // | 4221 B(Star), R(0), // |
4182 B(LdaSmi8), U8(3), // | 4222 B(LdaSmi8), U8(3), // |
4183 B(Star), R(0), // | 4223 B(Star), R(0), // |
4184 B(LdaUndefined), // | 4224 B(LdaUndefined), // |
4185 B(Return), // | 4225 B(Return), // |
4186 }, | 4226 }, |
4187 0}, | 4227 0, |
4228 {}, | |
4229 1, | |
4230 {{4, 8, 8}}}, | |
4188 {"var a = 1; try { a = 2; } catch(e) { a = 20 } finally { a = 3; }", | 4231 {"var a = 1; try { a = 2; } catch(e) { a = 20 } finally { a = 3; }", |
4189 2 * kPointerSize, | 4232 7 * kPointerSize, |
4190 1, | 4233 1, |
4191 14, | 4234 35, |
4192 { | 4235 { |
4193 B(LdaSmi8), U8(1), // | 4236 B(LdaSmi8), U8(1), // |
oth
2016/01/20 08:01:33
Tests are a bit brief. Could we add a couple of mo
Michael Starzinger
2016/01/20 10:19:54
Done, (1) in the test above and (2) here.
| |
4194 B(Star), R(0), // | 4237 B(Star), R(0), // |
4195 B(LdaSmi8), U8(2), // | 4238 B(LdaSmi8), U8(2), // |
4196 B(Star), R(0), // | 4239 B(Star), R(0), // |
4197 B(LdaSmi8), U8(3), // | 4240 B(Jump), U8(21), // |
4198 B(Star), R(0), // | 4241 B(Star), R(5), // |
4199 B(LdaUndefined), // | 4242 B(LdaConstant), U8(0), // |
4200 B(Return), // | 4243 B(Star), R(4), // |
4244 B(Ldar), R(closure), // | |
4245 B(Star), R(6), // | |
4246 B(CallRuntime), U16(Runtime::kPushCatchContext), R(4), U8(3), // | |
4247 B(LdaSmi8), U8(20), // | |
4248 B(Star), R(0), // | |
4249 B(LdaSmi8), U8(3), // | |
4250 B(Star), R(0), // | |
4251 B(LdaUndefined), // | |
4252 B(Return), // | |
4201 }, | 4253 }, |
4202 0}, | 4254 1, |
4255 {"e"}, | |
4256 2, | |
4257 {{4, 29, 29}, {4, 8, 10}}}, | |
4203 }; | 4258 }; |
4204 | 4259 |
4205 for (size_t i = 0; i < arraysize(snippets); i++) { | 4260 for (size_t i = 0; i < arraysize(snippets); i++) { |
4206 Handle<BytecodeArray> bytecode_array = | 4261 Handle<BytecodeArray> bytecode_array = |
4207 helper.MakeBytecodeForFunctionBody(snippets[i].code_snippet); | 4262 helper.MakeBytecodeForFunctionBody(snippets[i].code_snippet); |
4208 CheckBytecodeArrayEqual(snippets[i], bytecode_array); | 4263 CheckBytecodeArrayEqual(snippets[i], bytecode_array); |
4209 } | 4264 } |
4210 } | 4265 } |
4211 | 4266 |
4212 | 4267 |
4213 TEST(Throw) { | 4268 TEST(Throw) { |
4214 InitializedHandleScope handle_scope; | 4269 InitializedHandleScope handle_scope; |
4215 BytecodeGeneratorHelper helper; | 4270 BytecodeGeneratorHelper helper; |
4216 | 4271 |
4217 // TODO(rmcilroy): modify tests when we have real try catch support. | |
4218 ExpectedSnippet<const char*> snippets[] = { | 4272 ExpectedSnippet<const char*> snippets[] = { |
4219 {"throw 1;", | 4273 {"throw 1;", |
4220 0, | 4274 0, |
4221 1, | 4275 1, |
4222 3, | 4276 3, |
4223 { | 4277 { |
4224 B(LdaSmi8), U8(1), // | 4278 B(LdaSmi8), U8(1), // |
4225 B(Throw), // | 4279 B(Throw), // |
4226 }, | 4280 }, |
4227 0}, | 4281 0}, |
(...skipping 2534 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
6762 std::string(function_epilogue); | 6816 std::string(function_epilogue); |
6763 Handle<BytecodeArray> bytecode_array = | 6817 Handle<BytecodeArray> bytecode_array = |
6764 helper.MakeBytecode(script.c_str(), "*", "f"); | 6818 helper.MakeBytecode(script.c_str(), "*", "f"); |
6765 CheckBytecodeArrayEqual(snippets[i], bytecode_array); | 6819 CheckBytecodeArrayEqual(snippets[i], bytecode_array); |
6766 } | 6820 } |
6767 } | 6821 } |
6768 | 6822 |
6769 } // namespace interpreter | 6823 } // namespace interpreter |
6770 } // namespace internal | 6824 } // namespace internal |
6771 } // namespace v8 | 6825 } // namespace v8 |
OLD | NEW |