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