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}}}, |
| 4196 {"var a; try { a = 1 } catch(e1) {}; try { a = 2 } catch(e2) { a = 3 }", |
| 4197 6 * kPointerSize, |
| 4198 1, |
| 4199 48, |
| 4200 { |
| 4201 B(LdaSmi8), U8(1), // |
| 4202 B(Star), R(0), // |
| 4203 B(Jump), U8(17), // |
| 4204 B(Star), R(4), // |
| 4205 B(LdaConstant), U8(0), // |
| 4206 B(Star), R(3), // |
| 4207 B(Ldar), R(closure), // |
| 4208 B(Star), R(5), // |
| 4209 B(CallRuntime), U16(Runtime::kPushCatchContext), R(3), U8(3), // |
| 4210 B(LdaSmi8), U8(2), // |
| 4211 B(Star), R(0), // |
| 4212 B(Jump), U8(21), // |
| 4213 B(Star), R(4), // |
| 4214 B(LdaConstant), U8(1), // |
| 4215 B(Star), R(3), // |
| 4216 B(Ldar), R(closure), // |
| 4217 B(Star), R(5), // |
| 4218 B(CallRuntime), U16(Runtime::kPushCatchContext), R(3), U8(3), // |
| 4219 B(LdaSmi8), U8(3), // |
| 4220 B(Star), R(0), // |
| 4221 B(LdaUndefined), // |
| 4222 B(Return), // |
| 4223 }, |
| 4224 2, |
| 4225 {"e1", "e2"}, |
| 4226 2, |
| 4227 {{0, 4, 6}, {21, 25, 27}}}, |
4157 }; | 4228 }; |
4158 | 4229 |
4159 for (size_t i = 0; i < arraysize(snippets); i++) { | 4230 for (size_t i = 0; i < arraysize(snippets); i++) { |
4160 Handle<BytecodeArray> bytecode_array = | 4231 Handle<BytecodeArray> bytecode_array = |
4161 helper.MakeBytecodeForFunctionBody(snippets[i].code_snippet); | 4232 helper.MakeBytecodeForFunctionBody(snippets[i].code_snippet); |
4162 CheckBytecodeArrayEqual(snippets[i], bytecode_array); | 4233 CheckBytecodeArrayEqual(snippets[i], bytecode_array); |
4163 } | 4234 } |
4164 } | 4235 } |
4165 | 4236 |
4166 | 4237 |
4167 TEST(TryFinally) { | 4238 TEST(TryFinally) { |
4168 InitializedHandleScope handle_scope; | 4239 InitializedHandleScope handle_scope; |
4169 BytecodeGeneratorHelper helper; | 4240 BytecodeGeneratorHelper helper; |
4170 | 4241 |
4171 // TODO(rmcilroy): modify tests when we have real try finally support. | 4242 int closure = Register::function_closure().index(); |
4172 ExpectedSnippet<int> snippets[] = { | 4243 |
| 4244 ExpectedSnippet<const char*> snippets[] = { |
4173 {"var a = 1; try { a = 2; } finally { a = 3; }", | 4245 {"var a = 1; try { a = 2; } finally { a = 3; }", |
4174 kPointerSize, | 4246 2 * kPointerSize, |
4175 1, | 4247 1, |
4176 14, | 4248 14, |
4177 { | 4249 { |
4178 B(LdaSmi8), U8(1), // | 4250 B(LdaSmi8), U8(1), // |
4179 B(Star), R(0), // | 4251 B(Star), R(0), // |
4180 B(LdaSmi8), U8(2), // | 4252 B(LdaSmi8), U8(2), // |
4181 B(Star), R(0), // | 4253 B(Star), R(0), // |
4182 B(LdaSmi8), U8(3), // | 4254 B(LdaSmi8), U8(3), // |
4183 B(Star), R(0), // | 4255 B(Star), R(0), // |
4184 B(LdaUndefined), // | 4256 B(LdaUndefined), // |
4185 B(Return), // | 4257 B(Return), // |
4186 }, | 4258 }, |
4187 0}, | 4259 0, |
| 4260 {}, |
| 4261 1, |
| 4262 {{4, 8, 8}}}, |
4188 {"var a = 1; try { a = 2; } catch(e) { a = 20 } finally { a = 3; }", | 4263 {"var a = 1; try { a = 2; } catch(e) { a = 20 } finally { a = 3; }", |
4189 2 * kPointerSize, | 4264 7 * kPointerSize, |
4190 1, | 4265 1, |
4191 14, | 4266 35, |
4192 { | 4267 { |
4193 B(LdaSmi8), U8(1), // | 4268 B(LdaSmi8), U8(1), // |
4194 B(Star), R(0), // | 4269 B(Star), R(0), // |
4195 B(LdaSmi8), U8(2), // | 4270 B(LdaSmi8), U8(2), // |
4196 B(Star), R(0), // | 4271 B(Star), R(0), // |
4197 B(LdaSmi8), U8(3), // | 4272 B(Jump), U8(21), // |
4198 B(Star), R(0), // | 4273 B(Star), R(5), // |
4199 B(LdaUndefined), // | 4274 B(LdaConstant), U8(0), // |
4200 B(Return), // | 4275 B(Star), R(4), // |
| 4276 B(Ldar), R(closure), // |
| 4277 B(Star), R(6), // |
| 4278 B(CallRuntime), U16(Runtime::kPushCatchContext), R(4), U8(3), // |
| 4279 B(LdaSmi8), U8(20), // |
| 4280 B(Star), R(0), // |
| 4281 B(LdaSmi8), U8(3), // |
| 4282 B(Star), R(0), // |
| 4283 B(LdaUndefined), // |
| 4284 B(Return), // |
4201 }, | 4285 }, |
4202 0}, | 4286 1, |
| 4287 {"e"}, |
| 4288 2, |
| 4289 {{4, 29, 29}, {4, 8, 10}}}, |
| 4290 {"var a; try {" |
| 4291 " try { a = 1 } catch(e) { a = 2 }" |
| 4292 "} catch(e) { a = 20 } finally { a = 3; }", |
| 4293 8 * kPointerSize, |
| 4294 1, |
| 4295 52, |
| 4296 { |
| 4297 B(LdaSmi8), U8(1), // |
| 4298 B(Star), R(0), // |
| 4299 B(Jump), U8(21), // |
| 4300 B(Star), R(6), // |
| 4301 B(LdaConstant), U8(0), // |
| 4302 B(Star), R(5), // |
| 4303 B(Ldar), R(closure), // |
| 4304 B(Star), R(7), // |
| 4305 B(CallRuntime), U16(Runtime::kPushCatchContext), R(5), U8(3), // |
| 4306 B(LdaSmi8), U8(2), // |
| 4307 B(Star), R(0), // |
| 4308 B(Jump), U8(21), // |
| 4309 B(Star), R(5), // |
| 4310 B(LdaConstant), U8(0), // |
| 4311 B(Star), R(4), // |
| 4312 B(Ldar), R(closure), // |
| 4313 B(Star), R(6), // |
| 4314 B(CallRuntime), U16(Runtime::kPushCatchContext), R(4), U8(3), // |
| 4315 B(LdaSmi8), U8(20), // |
| 4316 B(Star), R(0), // |
| 4317 B(LdaSmi8), U8(3), // |
| 4318 B(Star), R(0), // |
| 4319 B(LdaUndefined), // |
| 4320 B(Return), // |
| 4321 }, |
| 4322 1, |
| 4323 {"e"}, |
| 4324 3, |
| 4325 {{0, 46, 46}, {0, 25, 27}, {0, 4, 6}}}, |
4203 }; | 4326 }; |
4204 | 4327 |
4205 for (size_t i = 0; i < arraysize(snippets); i++) { | 4328 for (size_t i = 0; i < arraysize(snippets); i++) { |
4206 Handle<BytecodeArray> bytecode_array = | 4329 Handle<BytecodeArray> bytecode_array = |
4207 helper.MakeBytecodeForFunctionBody(snippets[i].code_snippet); | 4330 helper.MakeBytecodeForFunctionBody(snippets[i].code_snippet); |
4208 CheckBytecodeArrayEqual(snippets[i], bytecode_array); | 4331 CheckBytecodeArrayEqual(snippets[i], bytecode_array); |
4209 } | 4332 } |
4210 } | 4333 } |
4211 | 4334 |
4212 | 4335 |
4213 TEST(Throw) { | 4336 TEST(Throw) { |
4214 InitializedHandleScope handle_scope; | 4337 InitializedHandleScope handle_scope; |
4215 BytecodeGeneratorHelper helper; | 4338 BytecodeGeneratorHelper helper; |
4216 | 4339 |
4217 // TODO(rmcilroy): modify tests when we have real try catch support. | |
4218 ExpectedSnippet<const char*> snippets[] = { | 4340 ExpectedSnippet<const char*> snippets[] = { |
4219 {"throw 1;", | 4341 {"throw 1;", |
4220 0, | 4342 0, |
4221 1, | 4343 1, |
4222 3, | 4344 3, |
4223 { | 4345 { |
4224 B(LdaSmi8), U8(1), // | 4346 B(LdaSmi8), U8(1), // |
4225 B(Throw), // | 4347 B(Throw), // |
4226 }, | 4348 }, |
4227 0}, | 4349 0}, |
(...skipping 2534 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
6762 std::string(function_epilogue); | 6884 std::string(function_epilogue); |
6763 Handle<BytecodeArray> bytecode_array = | 6885 Handle<BytecodeArray> bytecode_array = |
6764 helper.MakeBytecode(script.c_str(), "*", "f"); | 6886 helper.MakeBytecode(script.c_str(), "*", "f"); |
6765 CheckBytecodeArrayEqual(snippets[i], bytecode_array); | 6887 CheckBytecodeArrayEqual(snippets[i], bytecode_array); |
6766 } | 6888 } |
6767 } | 6889 } |
6768 | 6890 |
6769 } // namespace interpreter | 6891 } // namespace interpreter |
6770 } // namespace internal | 6892 } // namespace internal |
6771 } // namespace v8 | 6893 } // namespace v8 |
OLD | NEW |