| 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 |