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-generator.h" | 9 #include "src/interpreter/bytecode-generator.h" |
9 #include "src/interpreter/interpreter.h" | 10 #include "src/interpreter/interpreter.h" |
10 #include "test/cctest/cctest.h" | 11 #include "test/cctest/cctest.h" |
11 | 12 |
12 namespace v8 { | 13 namespace v8 { |
13 namespace internal { | 14 namespace internal { |
14 namespace interpreter { | 15 namespace interpreter { |
15 | 16 |
16 class BytecodeGeneratorHelper { | 17 class BytecodeGeneratorHelper { |
17 public: | 18 public: |
(...skipping 32 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
50 } | 51 } |
51 | 52 |
52 Handle<BytecodeArray> MakeBytecodeForFunction(const char* function) { | 53 Handle<BytecodeArray> MakeBytecodeForFunction(const char* function) { |
53 ScopedVector<char> program(1024); | 54 ScopedVector<char> program(1024); |
54 SNPrintF(program, "%s\n%s();", function, kFunctionName); | 55 SNPrintF(program, "%s\n%s();", function, kFunctionName); |
55 return MakeBytecode(program.start(), kFunctionName); | 56 return MakeBytecode(program.start(), kFunctionName); |
56 } | 57 } |
57 }; | 58 }; |
58 | 59 |
59 | 60 |
| 61 // Helper macros for handcrafting bytecode sequences. |
| 62 #define B(x) static_cast<uint8_t>(Bytecode::k##x) |
| 63 #define U8(x) static_cast<uint8_t>((x) & 0xff) |
| 64 #define R(x) static_cast<uint8_t>(-(x) & 0xff) |
| 65 #define _ static_cast<uint8_t>(0x5a) |
| 66 |
| 67 |
60 // Structure for containing expected bytecode snippets. | 68 // Structure for containing expected bytecode snippets. |
61 template<typename T> | 69 template<typename T> |
62 struct ExpectedSnippet { | 70 struct ExpectedSnippet { |
63 const char* code_snippet; | 71 const char* code_snippet; |
64 int frame_size; | 72 int frame_size; |
65 int parameter_count; | 73 int parameter_count; |
66 int bytecode_length; | 74 int bytecode_length; |
67 const uint8_t bytecode[32]; | 75 const uint8_t bytecode[32]; |
68 int constant_count; | 76 int constant_count; |
69 T constants[16]; | 77 T constants[16]; |
70 }; | 78 }; |
71 | 79 |
72 | 80 |
73 // Helper macros for handcrafting bytecode sequences. | 81 static void CheckConstant(int expected, Object* actual) { |
74 #define B(x) static_cast<uint8_t>(Bytecode::k##x) | 82 CHECK_EQ(expected, Smi::cast(actual)->value()); |
75 #define U8(x) static_cast<uint8_t>((x) & 0xff) | 83 } |
76 #define R(x) static_cast<uint8_t>(-(x) & 0xff) | 84 |
| 85 |
| 86 static void CheckConstant(double expected, Object* actual) { |
| 87 CHECK_EQ(expected, HeapNumber::cast(actual)->value()); |
| 88 } |
| 89 |
| 90 |
| 91 static void CheckConstant(const char* expected, Object* actual) { |
| 92 Handle<String> expected_string = |
| 93 CcTest::i_isolate()->factory()->NewStringFromAsciiChecked(expected); |
| 94 CHECK(String::cast(actual)->Equals(*expected_string)); |
| 95 } |
| 96 |
| 97 |
| 98 template <typename T> |
| 99 static void CheckBytecodeArrayEqual(struct ExpectedSnippet<T> expected, |
| 100 Handle<BytecodeArray> actual, |
| 101 bool has_unknown = false) { |
| 102 CHECK_EQ(actual->frame_size(), expected.frame_size); |
| 103 CHECK_EQ(actual->parameter_count(), expected.parameter_count); |
| 104 CHECK_EQ(actual->length(), expected.bytecode_length); |
| 105 if (expected.constant_count == 0) { |
| 106 CHECK_EQ(actual->constant_pool(), CcTest::heap()->empty_fixed_array()); |
| 107 } else { |
| 108 CHECK_EQ(actual->constant_pool()->length(), expected.constant_count); |
| 109 for (int i = 0; i < expected.constant_count; i++) { |
| 110 CheckConstant(expected.constants[i], actual->constant_pool()->get(i)); |
| 111 } |
| 112 } |
| 113 |
| 114 BytecodeArrayIterator iterator(actual); |
| 115 int i = 0; |
| 116 while (!iterator.done()) { |
| 117 int bytecode_index = i++; |
| 118 Bytecode bytecode = iterator.current_bytecode(); |
| 119 if (Bytecodes::ToByte(bytecode) != expected.bytecode[bytecode_index]) { |
| 120 std::ostringstream stream; |
| 121 stream << "Check failed: expected bytecode [" << bytecode_index |
| 122 << "] to be " << Bytecodes::ToString(static_cast<Bytecode>( |
| 123 expected.bytecode[bytecode_index])) |
| 124 << " but got " << Bytecodes::ToString(bytecode); |
| 125 FATAL(stream.str().c_str()); |
| 126 } |
| 127 for (int j = 0; j < Bytecodes::NumberOfOperands(bytecode); ++j, ++i) { |
| 128 uint8_t raw_operand = |
| 129 iterator.GetRawOperand(j, Bytecodes::GetOperandType(bytecode, j)); |
| 130 if (has_unknown) { |
| 131 // Check actual bytecode array doesn't have the same byte as the |
| 132 // one we use to specify an unknown byte. |
| 133 CHECK_NE(raw_operand, _); |
| 134 if (expected.bytecode[i] == _) { |
| 135 continue; |
| 136 } |
| 137 } |
| 138 if (raw_operand != expected.bytecode[i]) { |
| 139 std::ostringstream stream; |
| 140 stream << "Check failed: expected operand [" << j << "] for bytecode [" |
| 141 << bytecode_index << "] to be " |
| 142 << static_cast<unsigned int>(expected.bytecode[i]) << " but got " |
| 143 << static_cast<unsigned int>(raw_operand); |
| 144 FATAL(stream.str().c_str()); |
| 145 } |
| 146 } |
| 147 iterator.Advance(); |
| 148 } |
| 149 } |
77 | 150 |
78 | 151 |
79 TEST(PrimitiveReturnStatements) { | 152 TEST(PrimitiveReturnStatements) { |
80 InitializedHandleScope handle_scope; | 153 InitializedHandleScope handle_scope; |
81 BytecodeGeneratorHelper helper; | 154 BytecodeGeneratorHelper helper; |
82 | 155 |
83 ExpectedSnippet<void*> snippets[] = { | 156 ExpectedSnippet<int> snippets[] = { |
84 {"", 0, 1, 2, {B(LdaUndefined), B(Return)}, 0}, | 157 {"", 0, 1, 2, {B(LdaUndefined), B(Return)}, 0}, |
85 {"return;", 0, 1, 2, {B(LdaUndefined), B(Return)}, 0}, | 158 {"return;", 0, 1, 2, {B(LdaUndefined), B(Return)}, 0}, |
86 {"return null;", 0, 1, 2, {B(LdaNull), B(Return)}, 0}, | 159 {"return null;", 0, 1, 2, {B(LdaNull), B(Return)}, 0}, |
87 {"return true;", 0, 1, 2, {B(LdaTrue), B(Return)}, 0}, | 160 {"return true;", 0, 1, 2, {B(LdaTrue), B(Return)}, 0}, |
88 {"return false;", 0, 1, 2, {B(LdaFalse), B(Return)}, 0}, | 161 {"return false;", 0, 1, 2, {B(LdaFalse), B(Return)}, 0}, |
89 {"return 0;", 0, 1, 2, {B(LdaZero), B(Return)}, 0}, | 162 {"return 0;", 0, 1, 2, {B(LdaZero), B(Return)}, 0}, |
90 {"return +1;", 0, 1, 3, {B(LdaSmi8), U8(1), B(Return)}, 0}, | 163 {"return +1;", 0, 1, 3, {B(LdaSmi8), U8(1), B(Return)}, 0}, |
91 {"return -1;", 0, 1, 3, {B(LdaSmi8), U8(-1), B(Return)}, 0}, | 164 {"return -1;", 0, 1, 3, {B(LdaSmi8), U8(-1), B(Return)}, 0}, |
92 {"return +127;", 0, 1, 3, {B(LdaSmi8), U8(127), B(Return)}, 0}, | 165 {"return +127;", 0, 1, 3, {B(LdaSmi8), U8(127), B(Return)}, 0}, |
93 {"return -128;", 0, 1, 3, {B(LdaSmi8), U8(-128), B(Return)}, 0}, | 166 {"return -128;", 0, 1, 3, {B(LdaSmi8), U8(-128), B(Return)}, 0}, |
94 }; | 167 }; |
95 | 168 |
96 size_t num_snippets = sizeof(snippets) / sizeof(snippets[0]); | 169 size_t num_snippets = sizeof(snippets) / sizeof(snippets[0]); |
97 for (size_t i = 0; i < num_snippets; i++) { | 170 for (size_t i = 0; i < num_snippets; i++) { |
98 Handle<BytecodeArray> ba = | 171 Handle<BytecodeArray> bytecode_array = |
99 helper.MakeBytecodeForFunctionBody(snippets[i].code_snippet); | 172 helper.MakeBytecodeForFunctionBody(snippets[i].code_snippet); |
100 CHECK_EQ(ba->frame_size(), snippets[i].frame_size); | 173 CheckBytecodeArrayEqual(snippets[i], bytecode_array); |
101 CHECK_EQ(ba->parameter_count(), snippets[i].parameter_count); | |
102 CHECK_EQ(ba->length(), snippets[i].bytecode_length); | |
103 CHECK(!memcmp(ba->GetFirstBytecodeAddress(), snippets[i].bytecode, | |
104 ba->length())); | |
105 CHECK_EQ(ba->constant_pool(), CcTest::heap()->empty_fixed_array()); | |
106 } | 174 } |
107 } | 175 } |
108 | 176 |
109 | 177 |
110 TEST(PrimitiveExpressions) { | 178 TEST(PrimitiveExpressions) { |
111 InitializedHandleScope handle_scope; | 179 InitializedHandleScope handle_scope; |
112 BytecodeGeneratorHelper helper; | 180 BytecodeGeneratorHelper helper; |
113 | 181 |
114 ExpectedSnippet<void*> snippets[] = { | 182 ExpectedSnippet<int> snippets[] = { |
115 {"var x = 0; return x;", | 183 {"var x = 0; return x;", |
116 kPointerSize, | 184 kPointerSize, |
117 1, | 185 1, |
118 6, | 186 6, |
119 { | 187 { |
120 B(LdaZero), // | 188 B(LdaZero), // |
121 B(Star), R(0), // | 189 B(Star), R(0), // |
122 B(Ldar), R(0), // | 190 B(Ldar), R(0), // |
123 B(Return) // | 191 B(Return) // |
124 }, | 192 }, |
(...skipping 10 matching lines...) Expand all Loading... |
135 B(Star), R(1), // Dead store. | 203 B(Star), R(1), // Dead store. |
136 B(LdaSmi8), U8(3), // | 204 B(LdaSmi8), U8(3), // |
137 B(Add), R(1), // | 205 B(Add), R(1), // |
138 B(Return) // | 206 B(Return) // |
139 }, | 207 }, |
140 0 | 208 0 |
141 }}; | 209 }}; |
142 | 210 |
143 size_t num_snippets = sizeof(snippets) / sizeof(snippets[0]); | 211 size_t num_snippets = sizeof(snippets) / sizeof(snippets[0]); |
144 for (size_t i = 0; i < num_snippets; i++) { | 212 for (size_t i = 0; i < num_snippets; i++) { |
145 Handle<BytecodeArray> ba = | 213 Handle<BytecodeArray> bytecode_array = |
146 helper.MakeBytecodeForFunctionBody(snippets[i].code_snippet); | 214 helper.MakeBytecodeForFunctionBody(snippets[i].code_snippet); |
147 CHECK_EQ(ba->frame_size(), snippets[i].frame_size); | 215 CheckBytecodeArrayEqual(snippets[i], bytecode_array); |
148 CHECK_EQ(ba->parameter_count(), snippets[i].parameter_count); | |
149 CHECK_EQ(ba->length(), snippets[i].bytecode_length); | |
150 CHECK(!memcmp(ba->GetFirstBytecodeAddress(), snippets[i].bytecode, | |
151 ba->length())); | |
152 CHECK_EQ(ba->constant_pool(), CcTest::heap()->empty_fixed_array()); | |
153 } | 216 } |
154 } | 217 } |
155 | 218 |
156 | 219 |
157 TEST(Parameters) { | 220 TEST(Parameters) { |
158 InitializedHandleScope handle_scope; | 221 InitializedHandleScope handle_scope; |
159 BytecodeGeneratorHelper helper; | 222 BytecodeGeneratorHelper helper; |
160 | 223 |
161 ExpectedSnippet<void*> snippets[] = { | 224 ExpectedSnippet<int> snippets[] = { |
162 {"function f() { return this; }", | 225 {"function f() { return this; }", |
163 0, 1, 3, {B(Ldar), R(helper.kLastParamIndex), B(Return)}, 0}, | 226 0, 1, 3, {B(Ldar), R(helper.kLastParamIndex), B(Return)}, 0}, |
164 {"function f(arg1) { return arg1; }", | 227 {"function f(arg1) { return arg1; }", |
165 0, 2, 3, {B(Ldar), R(helper.kLastParamIndex), B(Return)}, 0}, | 228 0, 2, 3, {B(Ldar), R(helper.kLastParamIndex), B(Return)}, 0}, |
166 {"function f(arg1) { return this; }", | 229 {"function f(arg1) { return this; }", |
167 0, 2, 3, {B(Ldar), R(helper.kLastParamIndex - 1), B(Return)}, 0}, | 230 0, 2, 3, {B(Ldar), R(helper.kLastParamIndex - 1), B(Return)}, 0}, |
168 {"function f(arg1, arg2, arg3, arg4, arg5, arg6, arg7) { return arg4; }", | 231 {"function f(arg1, arg2, arg3, arg4, arg5, arg6, arg7) { return arg4; }", |
169 0, 8, 3, {B(Ldar), R(helper.kLastParamIndex - 3), B(Return)}, 0}, | 232 0, 8, 3, {B(Ldar), R(helper.kLastParamIndex - 3), B(Return)}, 0}, |
170 {"function f(arg1, arg2, arg3, arg4, arg5, arg6, arg7) { return this; }", | 233 {"function f(arg1, arg2, arg3, arg4, arg5, arg6, arg7) { return this; }", |
171 0, 8, 3, {B(Ldar), R(helper.kLastParamIndex - 7), B(Return)}, 0} | 234 0, 8, 3, {B(Ldar), R(helper.kLastParamIndex - 7), B(Return)}, 0} |
172 }; | 235 }; |
173 | 236 |
174 size_t num_snippets = sizeof(snippets) / sizeof(snippets[0]); | 237 size_t num_snippets = sizeof(snippets) / sizeof(snippets[0]); |
175 for (size_t i = 0; i < num_snippets; i++) { | 238 for (size_t i = 0; i < num_snippets; i++) { |
176 Handle<BytecodeArray> ba = | 239 Handle<BytecodeArray> bytecode_array = |
177 helper.MakeBytecodeForFunction(snippets[i].code_snippet); | 240 helper.MakeBytecodeForFunction(snippets[i].code_snippet); |
178 CHECK_EQ(ba->frame_size(), snippets[i].frame_size); | 241 CheckBytecodeArrayEqual(snippets[i], bytecode_array); |
179 CHECK_EQ(ba->parameter_count(), snippets[i].parameter_count); | |
180 CHECK_EQ(ba->length(), snippets[i].bytecode_length); | |
181 CHECK(!memcmp(ba->GetFirstBytecodeAddress(), snippets[i].bytecode, | |
182 ba->length())); | |
183 CHECK_EQ(ba->constant_pool(), CcTest::heap()->empty_fixed_array()); | |
184 } | 242 } |
185 } | 243 } |
186 | 244 |
187 | 245 |
188 TEST(Constants) { | 246 TEST(Constants) { |
189 InitializedHandleScope handle_scope; | 247 InitializedHandleScope handle_scope; |
190 BytecodeGeneratorHelper helper; | 248 BytecodeGeneratorHelper helper; |
191 | 249 |
192 // Check large SMIs. | 250 // Check large SMIs. |
193 { | 251 { |
(...skipping 18 matching lines...) Expand all Loading... |
212 B(LdaConstant), U8(0), | 270 B(LdaConstant), U8(0), |
213 B(Star), R(0), | 271 B(Star), R(0), |
214 B(LdaConstant), U8(0), | 272 B(LdaConstant), U8(0), |
215 B(Return) | 273 B(Return) |
216 }, 1, { 1234 } | 274 }, 1, { 1234 } |
217 } | 275 } |
218 }; | 276 }; |
219 | 277 |
220 size_t num_snippets = sizeof(snippets) / sizeof(snippets[0]); | 278 size_t num_snippets = sizeof(snippets) / sizeof(snippets[0]); |
221 for (size_t i = 0; i < num_snippets; i++) { | 279 for (size_t i = 0; i < num_snippets; i++) { |
222 Handle<BytecodeArray> ba = | 280 Handle<BytecodeArray> bytecode_array = |
223 helper.MakeBytecodeForFunctionBody(snippets[i].code_snippet); | 281 helper.MakeBytecodeForFunctionBody(snippets[i].code_snippet); |
224 CHECK_EQ(ba->frame_size(), snippets[i].frame_size); | 282 CheckBytecodeArrayEqual(snippets[i], bytecode_array); |
225 CHECK_EQ(ba->parameter_count(), snippets[i].parameter_count); | |
226 CHECK_EQ(ba->length(), snippets[i].bytecode_length); | |
227 CHECK(!memcmp(ba->GetFirstBytecodeAddress(), snippets[i].bytecode, | |
228 ba->length())); | |
229 CHECK_EQ(ba->constant_pool()->length(), snippets[i].constant_count); | |
230 for (int j = 0; j < snippets[i].constant_count; j++) { | |
231 CHECK_EQ(Smi::cast(ba->constant_pool()->get(j))->value(), | |
232 snippets[i].constants[j]); | |
233 } | |
234 } | 283 } |
235 } | 284 } |
236 | 285 |
237 // Check heap number double constants | 286 // Check heap number double constants |
238 { | 287 { |
239 ExpectedSnippet<double> snippets[] = { | 288 ExpectedSnippet<double> snippets[] = { |
240 {"return 1.2;", | 289 {"return 1.2;", |
241 0, 1, 3, | 290 0, 1, 3, |
242 { | 291 { |
243 B(LdaConstant), U8(0), | 292 B(LdaConstant), U8(0), |
(...skipping 17 matching lines...) Expand all Loading... |
261 }, 2, | 310 }, 2, |
262 // TODO(rmcilroy): Currently multiple identical double literals end up | 311 // TODO(rmcilroy): Currently multiple identical double literals end up |
263 // being allocated as new HeapNumbers and so require multiple constant | 312 // being allocated as new HeapNumbers and so require multiple constant |
264 // pool entries. De-dup identical values. | 313 // pool entries. De-dup identical values. |
265 { 3.14, 3.14 } | 314 { 3.14, 3.14 } |
266 } | 315 } |
267 }; | 316 }; |
268 | 317 |
269 size_t num_snippets = sizeof(snippets) / sizeof(snippets[0]); | 318 size_t num_snippets = sizeof(snippets) / sizeof(snippets[0]); |
270 for (size_t i = 0; i < num_snippets; i++) { | 319 for (size_t i = 0; i < num_snippets; i++) { |
271 Handle<BytecodeArray> ba = | 320 Handle<BytecodeArray> bytecode_array = |
272 helper.MakeBytecodeForFunctionBody(snippets[i].code_snippet); | 321 helper.MakeBytecodeForFunctionBody(snippets[i].code_snippet); |
273 CHECK_EQ(ba->frame_size(), snippets[i].frame_size); | 322 CheckBytecodeArrayEqual(snippets[i], bytecode_array); |
274 CHECK_EQ(ba->parameter_count(), snippets[i].parameter_count); | |
275 CHECK_EQ(ba->length(), snippets[i].bytecode_length); | |
276 CHECK(!memcmp(ba->GetFirstBytecodeAddress(), snippets[i].bytecode, | |
277 ba->length())); | |
278 CHECK_EQ(ba->constant_pool()->length(), snippets[i].constant_count); | |
279 for (int j = 0; j < snippets[i].constant_count; j++) { | |
280 CHECK_EQ(HeapNumber::cast(ba->constant_pool()->get(j))->value(), | |
281 snippets[i].constants[j]); | |
282 } | |
283 } | 323 } |
284 } | 324 } |
285 | 325 |
286 // Check string literals | 326 // Check string literals |
287 { | 327 { |
288 ExpectedSnippet<const char*> snippets[] = { | 328 ExpectedSnippet<const char*> snippets[] = { |
289 {"return \"This is a string\";", 0, 1, 3, | 329 {"return \"This is a string\";", 0, 1, 3, |
290 { | 330 { |
291 B(LdaConstant), U8(0), | 331 B(LdaConstant), U8(0), |
292 B(Return) | 332 B(Return) |
(...skipping 15 matching lines...) Expand all Loading... |
308 B(LdaConstant), U8(0), | 348 B(LdaConstant), U8(0), |
309 B(Star), R(0), | 349 B(Star), R(0), |
310 B(LdaConstant), U8(0), | 350 B(LdaConstant), U8(0), |
311 B(Return) | 351 B(Return) |
312 }, 1, { "Same string" } | 352 }, 1, { "Same string" } |
313 } | 353 } |
314 }; | 354 }; |
315 | 355 |
316 size_t num_snippets = sizeof(snippets) / sizeof(snippets[0]); | 356 size_t num_snippets = sizeof(snippets) / sizeof(snippets[0]); |
317 for (size_t i = 0; i < num_snippets; i++) { | 357 for (size_t i = 0; i < num_snippets; i++) { |
318 Handle<BytecodeArray> ba = | 358 Handle<BytecodeArray> bytecode_array = |
319 helper.MakeBytecodeForFunctionBody(snippets[i].code_snippet); | 359 helper.MakeBytecodeForFunctionBody(snippets[i].code_snippet); |
320 CHECK_EQ(ba->frame_size(), snippets[i].frame_size); | 360 CheckBytecodeArrayEqual(snippets[i], bytecode_array); |
321 CHECK_EQ(ba->parameter_count(), snippets[i].parameter_count); | |
322 CHECK_EQ(ba->length(), snippets[i].bytecode_length); | |
323 CHECK(!memcmp(ba->GetFirstBytecodeAddress(), snippets[i].bytecode, | |
324 ba->length())); | |
325 CHECK_EQ(ba->constant_pool()->length(), snippets[i].constant_count); | |
326 for (int j = 0; j < snippets[i].constant_count; j++) { | |
327 Handle<String> expected = helper.factory()->NewStringFromAsciiChecked( | |
328 snippets[i].constants[j]); | |
329 CHECK(String::cast(ba->constant_pool()->get(j))->Equals(*expected)); | |
330 } | |
331 } | 361 } |
332 } | 362 } |
333 } | 363 } |
334 | 364 |
335 | 365 |
336 TEST(PropertyLoads) { | 366 TEST(PropertyLoads) { |
337 InitializedHandleScope handle_scope; | 367 InitializedHandleScope handle_scope; |
338 BytecodeGeneratorHelper helper; | 368 BytecodeGeneratorHelper helper; |
339 | 369 |
340 Code::Kind ic_kinds[] = { i::Code::LOAD_IC, i::Code::LOAD_IC }; | 370 Code::Kind ic_kinds[] = { i::Code::LOAD_IC, i::Code::LOAD_IC }; |
(...skipping 57 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
398 B(Star), R(1), | 428 B(Star), R(1), |
399 B(LdaSmi8), U8(-124), | 429 B(LdaSmi8), U8(-124), |
400 B(KeyedLoadIC), R(1), U8(vector->first_ic_slot_index() + 2), | 430 B(KeyedLoadIC), R(1), U8(vector->first_ic_slot_index() + 2), |
401 B(Return) | 431 B(Return) |
402 }, | 432 }, |
403 1, { "name" } | 433 1, { "name" } |
404 } | 434 } |
405 }; | 435 }; |
406 size_t num_snippets = sizeof(snippets) / sizeof(snippets[0]); | 436 size_t num_snippets = sizeof(snippets) / sizeof(snippets[0]); |
407 for (size_t i = 0; i < num_snippets; i++) { | 437 for (size_t i = 0; i < num_snippets; i++) { |
408 Handle<BytecodeArray> ba = | 438 Handle<BytecodeArray> bytecode_array = |
409 helper.MakeBytecode(snippets[i].code_snippet, "f"); | 439 helper.MakeBytecode(snippets[i].code_snippet, "f"); |
410 CHECK_EQ(ba->frame_size(), snippets[i].frame_size); | 440 CheckBytecodeArrayEqual(snippets[i], bytecode_array); |
411 CHECK_EQ(ba->parameter_count(), snippets[i].parameter_count); | |
412 CHECK_EQ(ba->length(), snippets[i].bytecode_length); | |
413 CHECK(!memcmp(ba->GetFirstBytecodeAddress(), snippets[i].bytecode, | |
414 ba->length())); | |
415 CHECK_EQ(ba->constant_pool()->length(), snippets[i].constant_count); | |
416 for (int j = 0; j < snippets[i].constant_count; j++) { | |
417 Handle<String> expected = helper.factory()->NewStringFromAsciiChecked( | |
418 snippets[i].constants[j]); | |
419 CHECK(String::cast(ba->constant_pool()->get(j))->Equals(*expected)); | |
420 } | |
421 } | 441 } |
422 } | 442 } |
423 | 443 |
424 | 444 |
425 TEST(PropertyStores) { | 445 TEST(PropertyStores) { |
426 InitializedHandleScope handle_scope; | 446 InitializedHandleScope handle_scope; |
427 BytecodeGeneratorHelper helper; | 447 BytecodeGeneratorHelper helper; |
428 | 448 |
429 Code::Kind ic_kinds[] = { i::Code::STORE_IC, i::Code::STORE_IC }; | 449 Code::Kind ic_kinds[] = { i::Code::STORE_IC, i::Code::STORE_IC }; |
430 FeedbackVectorSpec feedback_spec(0, 2, ic_kinds); | 450 FeedbackVectorSpec feedback_spec(0, 2, ic_kinds); |
(...skipping 71 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
502 B(KeyedLoadIC), R(2), U8(vector->first_ic_slot_index()), | 522 B(KeyedLoadIC), R(2), U8(vector->first_ic_slot_index()), |
503 B(StoreIC), R(0), R(1), U8(vector->first_ic_slot_index() + 2), | 523 B(StoreIC), R(0), R(1), U8(vector->first_ic_slot_index() + 2), |
504 B(LdaUndefined), | 524 B(LdaUndefined), |
505 B(Return) | 525 B(Return) |
506 }, | 526 }, |
507 1, { "name" } | 527 1, { "name" } |
508 } | 528 } |
509 }; | 529 }; |
510 size_t num_snippets = sizeof(snippets) / sizeof(snippets[0]); | 530 size_t num_snippets = sizeof(snippets) / sizeof(snippets[0]); |
511 for (size_t i = 0; i < num_snippets; i++) { | 531 for (size_t i = 0; i < num_snippets; i++) { |
512 Handle<BytecodeArray> ba = | 532 Handle<BytecodeArray> bytecode_array = |
513 helper.MakeBytecode(snippets[i].code_snippet, "f"); | 533 helper.MakeBytecode(snippets[i].code_snippet, "f"); |
514 CHECK_EQ(ba->frame_size(), snippets[i].frame_size); | 534 CheckBytecodeArrayEqual(snippets[i], bytecode_array); |
515 CHECK_EQ(ba->parameter_count(), snippets[i].parameter_count); | |
516 CHECK_EQ(ba->length(), snippets[i].bytecode_length); | |
517 CHECK(!memcmp(ba->GetFirstBytecodeAddress(), snippets[i].bytecode, | |
518 ba->length())); | |
519 CHECK_EQ(ba->constant_pool()->length(), snippets[i].constant_count); | |
520 for (int j = 0; j < snippets[i].constant_count; j++) { | |
521 Handle<String> expected = | |
522 helper.factory()->NewStringFromAsciiChecked(snippets[i].constants[j]); | |
523 CHECK(String::cast(ba->constant_pool()->get(j))->Equals(*expected)); | |
524 } | |
525 } | 535 } |
526 } | 536 } |
527 | 537 |
528 | 538 |
529 #define FUNC_ARG "new (function Obj() { this.func = function() { return; }})()" | 539 #define FUNC_ARG "new (function Obj() { this.func = function() { return; }})()" |
530 | 540 |
531 | 541 |
532 TEST(PropertyCall) { | 542 TEST(PropertyCall) { |
533 InitializedHandleScope handle_scope; | 543 InitializedHandleScope handle_scope; |
534 BytecodeGeneratorHelper helper; | 544 BytecodeGeneratorHelper helper; |
(...skipping 50 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
585 B(Ldar), R(helper.kLastParamIndex), | 595 B(Ldar), R(helper.kLastParamIndex), |
586 B(Star), R(3), | 596 B(Star), R(3), |
587 B(Call), R(0), R(1), U8(2), | 597 B(Call), R(0), R(1), U8(2), |
588 B(Return) | 598 B(Return) |
589 }, | 599 }, |
590 1, { "func" } | 600 1, { "func" } |
591 } | 601 } |
592 }; | 602 }; |
593 size_t num_snippets = sizeof(snippets) / sizeof(snippets[0]); | 603 size_t num_snippets = sizeof(snippets) / sizeof(snippets[0]); |
594 for (size_t i = 0; i < num_snippets; i++) { | 604 for (size_t i = 0; i < num_snippets; i++) { |
595 Handle<BytecodeArray> ba = | 605 Handle<BytecodeArray> bytecode_array = |
596 helper.MakeBytecode(snippets[i].code_snippet, "f"); | 606 helper.MakeBytecode(snippets[i].code_snippet, "f"); |
597 CHECK_EQ(ba->frame_size(), snippets[i].frame_size); | 607 CheckBytecodeArrayEqual(snippets[i], bytecode_array); |
598 CHECK_EQ(ba->parameter_count(), snippets[i].parameter_count); | |
599 CHECK_EQ(ba->length(), snippets[i].bytecode_length); | |
600 CHECK(!memcmp(ba->GetFirstBytecodeAddress(), snippets[i].bytecode, | |
601 ba->length())); | |
602 CHECK_EQ(ba->constant_pool()->length(), snippets[i].constant_count); | |
603 for (int j = 0; j < snippets[i].constant_count; j++) { | |
604 Handle<String> expected = | |
605 helper.factory()->NewStringFromAsciiChecked(snippets[i].constants[j]); | |
606 CHECK(String::cast(ba->constant_pool()->get(j))->Equals(*expected)); | |
607 } | |
608 } | 608 } |
609 } | 609 } |
610 | 610 |
| 611 |
| 612 TEST(LoadGlobal) { |
| 613 InitializedHandleScope handle_scope; |
| 614 BytecodeGeneratorHelper helper; |
| 615 |
| 616 ExpectedSnippet<const char*> snippets[] = { |
| 617 {"var a = 1;\nfunction f() { return a; }\nf()", |
| 618 0, 1, 3, |
| 619 { |
| 620 B(LdaGlobal), _, |
| 621 B(Return) |
| 622 }, |
| 623 }, |
| 624 {"function t() { }\nfunction f() { return t; }\nf()", |
| 625 0, 1, 3, |
| 626 { |
| 627 B(LdaGlobal), _, |
| 628 B(Return) |
| 629 }, |
| 630 }, |
| 631 }; |
| 632 |
| 633 size_t num_snippets = sizeof(snippets) / sizeof(snippets[0]); |
| 634 for (size_t i = 0; i < num_snippets; i++) { |
| 635 Handle<BytecodeArray> bytecode_array = |
| 636 helper.MakeBytecode(snippets[i].code_snippet, "f"); |
| 637 bytecode_array->Print(); |
| 638 CheckBytecodeArrayEqual(snippets[i], bytecode_array, true); |
| 639 } |
| 640 } |
| 641 |
| 642 |
| 643 TEST(CallGlobal) { |
| 644 InitializedHandleScope handle_scope; |
| 645 BytecodeGeneratorHelper helper; |
| 646 |
| 647 ExpectedSnippet<const char*> snippets[] = { |
| 648 {"function t() { }\nfunction f() { return t(); }\nf()", |
| 649 2 * kPointerSize, 1, 12, |
| 650 { |
| 651 B(LdaUndefined), |
| 652 B(Star), R(1), |
| 653 B(LdaGlobal), _, |
| 654 B(Star), R(0), |
| 655 B(Call), R(0), R(1), U8(0), |
| 656 B(Return) |
| 657 }, |
| 658 }, |
| 659 {"function t(a, b, c) { }\nfunction f() { return t(1, 2, 3); }\nf()", |
| 660 5 * kPointerSize, 1, 24, |
| 661 { |
| 662 B(LdaUndefined), |
| 663 B(Star), R(1), |
| 664 B(LdaGlobal), _, |
| 665 B(Star), R(0), |
| 666 B(LdaSmi8), U8(1), |
| 667 B(Star), R(2), |
| 668 B(LdaSmi8), U8(2), |
| 669 B(Star), R(3), |
| 670 B(LdaSmi8), U8(3), |
| 671 B(Star), R(4), |
| 672 B(Call), R(0), R(1), U8(3), |
| 673 B(Return) |
| 674 }, |
| 675 }, |
| 676 }; |
| 677 |
| 678 size_t num_snippets = sizeof(snippets) / sizeof(snippets[0]); |
| 679 for (size_t i = 0; i < num_snippets; i++) { |
| 680 Handle<BytecodeArray> bytecode_array = |
| 681 helper.MakeBytecode(snippets[i].code_snippet, "f"); |
| 682 CheckBytecodeArrayEqual(snippets[i], bytecode_array, true); |
| 683 } |
| 684 } |
| 685 |
611 } // namespace interpreter | 686 } // namespace interpreter |
612 } // namespace internal | 687 } // namespace internal |
613 } // namespance v8 | 688 } // namespance v8 |
OLD | NEW |