| OLD | NEW |
| 1 // Copyright 2014 the V8 project authors. All rights reserved. | 1 // Copyright 2014 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/interpreter/bytecode-array-builder.h" | 7 #include "src/interpreter/bytecode-array-builder.h" |
| 8 #include "src/interpreter/bytecode-array-iterator.h" | 8 #include "src/interpreter/bytecode-array-iterator.h" |
| 9 #include "src/interpreter/bytecode-label.h" | 9 #include "src/interpreter/bytecode-label.h" |
| 10 #include "src/interpreter/bytecode-register-allocator.h" | 10 #include "src/interpreter/bytecode-register-allocator.h" |
| (...skipping 15 matching lines...) Expand all Loading... |
| 26 BytecodeArrayBuilder builder(isolate(), zone(), 0, 1, 131); | 26 BytecodeArrayBuilder builder(isolate(), zone(), 0, 1, 131); |
| 27 Factory* factory = isolate()->factory(); | 27 Factory* factory = isolate()->factory(); |
| 28 | 28 |
| 29 CHECK_EQ(builder.locals_count(), 131); | 29 CHECK_EQ(builder.locals_count(), 131); |
| 30 CHECK_EQ(builder.context_count(), 1); | 30 CHECK_EQ(builder.context_count(), 1); |
| 31 CHECK_EQ(builder.fixed_register_count(), 132); | 31 CHECK_EQ(builder.fixed_register_count(), 132); |
| 32 | 32 |
| 33 Register reg(0); | 33 Register reg(0); |
| 34 Register other(reg.index() + 1); | 34 Register other(reg.index() + 1); |
| 35 Register wide(128); | 35 Register wide(128); |
| 36 RegisterList reg_list; |
| 36 | 37 |
| 37 // Emit argument creation operations. | 38 // Emit argument creation operations. |
| 38 builder.CreateArguments(CreateArgumentsType::kMappedArguments) | 39 builder.CreateArguments(CreateArgumentsType::kMappedArguments) |
| 39 .CreateArguments(CreateArgumentsType::kUnmappedArguments) | 40 .CreateArguments(CreateArgumentsType::kUnmappedArguments) |
| 40 .CreateArguments(CreateArgumentsType::kRestParameter); | 41 .CreateArguments(CreateArgumentsType::kRestParameter); |
| 41 | 42 |
| 42 // Emit constant loads. | 43 // Emit constant loads. |
| 43 builder.LoadLiteral(Smi::FromInt(0)) | 44 builder.LoadLiteral(Smi::FromInt(0)) |
| 44 .StoreAccumulatorInRegister(reg) | 45 .StoreAccumulatorInRegister(reg) |
| 45 .LoadLiteral(Smi::FromInt(8)) | 46 .LoadLiteral(Smi::FromInt(8)) |
| (...skipping 70 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 116 builder.CreateCatchContext(reg, name, factory->NewScopeInfo(1)); | 117 builder.CreateCatchContext(reg, name, factory->NewScopeInfo(1)); |
| 117 builder.CreateFunctionContext(1); | 118 builder.CreateFunctionContext(1); |
| 118 builder.CreateWithContext(reg, factory->NewScopeInfo(1)); | 119 builder.CreateWithContext(reg, factory->NewScopeInfo(1)); |
| 119 | 120 |
| 120 // Emit literal creation operations. | 121 // Emit literal creation operations. |
| 121 builder.CreateRegExpLiteral(factory->NewStringFromStaticChars("a"), 0, 0) | 122 builder.CreateRegExpLiteral(factory->NewStringFromStaticChars("a"), 0, 0) |
| 122 .CreateArrayLiteral(factory->NewFixedArray(1), 0, 0) | 123 .CreateArrayLiteral(factory->NewFixedArray(1), 0, 0) |
| 123 .CreateObjectLiteral(factory->NewFixedArray(1), 0, 0, reg); | 124 .CreateObjectLiteral(factory->NewFixedArray(1), 0, 0, reg); |
| 124 | 125 |
| 125 // Call operations. | 126 // Call operations. |
| 126 builder.Call(reg, other, 0, 1) | 127 builder.Call(reg, reg_list, 1) |
| 127 .Call(reg, wide, 0, 1) | 128 .Call(reg, reg_list, 1, TailCallMode::kAllow) |
| 128 .TailCall(reg, other, 0, 1) | 129 .CallRuntime(Runtime::kIsArray, reg) |
| 129 .TailCall(reg, wide, 0, 1) | 130 .CallRuntimeForPair(Runtime::kLoadLookupSlotForCall, reg_list, other) |
| 130 .CallRuntime(Runtime::kIsArray, reg, 1) | 131 .CallJSRuntime(Context::SPREAD_ITERABLE_INDEX, reg_list); |
| 131 .CallRuntime(Runtime::kIsArray, wide, 1) | |
| 132 .CallRuntimeForPair(Runtime::kLoadLookupSlotForCall, reg, 1, other) | |
| 133 .CallRuntimeForPair(Runtime::kLoadLookupSlotForCall, wide, 1, other) | |
| 134 .CallJSRuntime(Context::SPREAD_ITERABLE_INDEX, reg, 1) | |
| 135 .CallJSRuntime(Context::SPREAD_ITERABLE_INDEX, wide, 1); | |
| 136 | 132 |
| 137 // Emit binary operator invocations. | 133 // Emit binary operator invocations. |
| 138 builder.BinaryOperation(Token::Value::ADD, reg, 1) | 134 builder.BinaryOperation(Token::Value::ADD, reg, 1) |
| 139 .BinaryOperation(Token::Value::SUB, reg, 2) | 135 .BinaryOperation(Token::Value::SUB, reg, 2) |
| 140 .BinaryOperation(Token::Value::MUL, reg, 3) | 136 .BinaryOperation(Token::Value::MUL, reg, 3) |
| 141 .BinaryOperation(Token::Value::DIV, reg, 4) | 137 .BinaryOperation(Token::Value::DIV, reg, 4) |
| 142 .BinaryOperation(Token::Value::MOD, reg, 5); | 138 .BinaryOperation(Token::Value::MOD, reg, 5); |
| 143 | 139 |
| 144 // Emit bitwise operator invocations | 140 // Emit bitwise operator invocations |
| 145 builder.BinaryOperation(Token::Value::BIT_OR, reg, 6) | 141 builder.BinaryOperation(Token::Value::BIT_OR, reg, 6) |
| (...skipping 26 matching lines...) Expand all Loading... |
| 172 // Emit unary operator invocations. | 168 // Emit unary operator invocations. |
| 173 builder | 169 builder |
| 174 .LogicalNot() // ToBooleanLogicalNot | 170 .LogicalNot() // ToBooleanLogicalNot |
| 175 .LogicalNot() // non-ToBoolean LogicalNot | 171 .LogicalNot() // non-ToBoolean LogicalNot |
| 176 .TypeOf(); | 172 .TypeOf(); |
| 177 | 173 |
| 178 // Emit delete | 174 // Emit delete |
| 179 builder.Delete(reg, LanguageMode::SLOPPY).Delete(reg, LanguageMode::STRICT); | 175 builder.Delete(reg, LanguageMode::SLOPPY).Delete(reg, LanguageMode::STRICT); |
| 180 | 176 |
| 181 // Emit new. | 177 // Emit new. |
| 182 builder.New(reg, reg, 0, 1); | 178 builder.New(reg, reg_list, 1); |
| 183 builder.New(wide, wide, 0, 1); | |
| 184 | 179 |
| 185 // Emit test operator invocations. | 180 // Emit test operator invocations. |
| 186 builder.CompareOperation(Token::Value::EQ, reg, 1) | 181 builder.CompareOperation(Token::Value::EQ, reg, 1) |
| 187 .CompareOperation(Token::Value::NE, reg, 2) | 182 .CompareOperation(Token::Value::NE, reg, 2) |
| 188 .CompareOperation(Token::Value::EQ_STRICT, reg, 3) | 183 .CompareOperation(Token::Value::EQ_STRICT, reg, 3) |
| 189 .CompareOperation(Token::Value::LT, reg, 4) | 184 .CompareOperation(Token::Value::LT, reg, 4) |
| 190 .CompareOperation(Token::Value::GT, reg, 5) | 185 .CompareOperation(Token::Value::GT, reg, 5) |
| 191 .CompareOperation(Token::Value::LTE, reg, 6) | 186 .CompareOperation(Token::Value::LTE, reg, 6) |
| 192 .CompareOperation(Token::Value::GTE, reg, 7) | 187 .CompareOperation(Token::Value::GTE, reg, 7) |
| 193 .CompareOperation(Token::Value::INSTANCEOF, reg, 8) | 188 .CompareOperation(Token::Value::INSTANCEOF, reg, 8) |
| (...skipping 136 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 330 builder.CreateRegExpLiteral(factory->NewStringFromStaticChars("wide_literal"), | 325 builder.CreateRegExpLiteral(factory->NewStringFromStaticChars("wide_literal"), |
| 331 0, 0) | 326 0, 0) |
| 332 .CreateArrayLiteral(factory->NewFixedArray(2), 0, 0) | 327 .CreateArrayLiteral(factory->NewFixedArray(2), 0, 0) |
| 333 .CreateObjectLiteral(factory->NewFixedArray(2), 0, 0, reg); | 328 .CreateObjectLiteral(factory->NewFixedArray(2), 0, 0, reg); |
| 334 | 329 |
| 335 // Emit generator operations | 330 // Emit generator operations |
| 336 builder.SuspendGenerator(reg) | 331 builder.SuspendGenerator(reg) |
| 337 .ResumeGenerator(reg); | 332 .ResumeGenerator(reg); |
| 338 | 333 |
| 339 // Intrinsics handled by the interpreter. | 334 // Intrinsics handled by the interpreter. |
| 340 builder.CallRuntime(Runtime::kInlineIsArray, reg, 1) | 335 builder.CallRuntime(Runtime::kInlineIsArray, reg_list); |
| 341 .CallRuntime(Runtime::kInlineIsArray, wide, 1); | |
| 342 | 336 |
| 343 // Emit debugger bytecode. | 337 // Emit debugger bytecode. |
| 344 builder.Debugger(); | 338 builder.Debugger(); |
| 345 | 339 |
| 346 // Insert dummy ops to force longer jumps. | 340 // Insert dummy ops to force longer jumps. |
| 347 for (int i = 0; i < 128; i++) { | 341 for (int i = 0; i < 128; i++) { |
| 348 builder.LoadTrue(); | 342 builder.LoadTrue(); |
| 349 } | 343 } |
| 350 | 344 |
| 351 // Bind labels for long jumps at the very end. | 345 // Bind labels for long jumps at the very end. |
| 352 for (size_t i = 0; i < arraysize(end); i++) { | 346 for (size_t i = 0; i < arraysize(end); i++) { |
| 353 builder.Bind(&end[i]); | 347 builder.Bind(&end[i]); |
| 354 } | 348 } |
| 355 | 349 |
| 356 // Return must be the last instruction. | 350 // Return must be the last instruction. |
| 357 builder.Return(); | 351 builder.Return(); |
| 358 | 352 |
| 359 // Generate BytecodeArray. | 353 // Generate BytecodeArray. |
| 360 Handle<BytecodeArray> the_array = builder.ToBytecodeArray(isolate()); | 354 Handle<BytecodeArray> the_array = builder.ToBytecodeArray(isolate()); |
| 361 CHECK_EQ(the_array->frame_size(), | 355 CHECK_EQ(the_array->frame_size(), |
| 362 builder.fixed_and_temporary_register_count() * kPointerSize); | 356 builder.total_register_count() * kPointerSize); |
| 363 | 357 |
| 364 // Build scorecard of bytecodes encountered in the BytecodeArray. | 358 // Build scorecard of bytecodes encountered in the BytecodeArray. |
| 365 std::vector<int> scorecard(Bytecodes::ToByte(Bytecode::kLast) + 1); | 359 std::vector<int> scorecard(Bytecodes::ToByte(Bytecode::kLast) + 1); |
| 366 | 360 |
| 367 Bytecode final_bytecode = Bytecode::kLdaZero; | 361 Bytecode final_bytecode = Bytecode::kLdaZero; |
| 368 int i = 0; | 362 int i = 0; |
| 369 while (i < the_array->length()) { | 363 while (i < the_array->length()) { |
| 370 uint8_t code = the_array->get(i); | 364 uint8_t code = the_array->get(i); |
| 371 scorecard[code] += 1; | 365 scorecard[code] += 1; |
| 372 final_bytecode = Bytecodes::FromByte(code); | 366 final_bytecode = Bytecodes::FromByte(code); |
| (...skipping 48 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 421 #undef CHECK_BYTECODE_PRESENT | 415 #undef CHECK_BYTECODE_PRESENT |
| 422 } | 416 } |
| 423 | 417 |
| 424 | 418 |
| 425 TEST_F(BytecodeArrayBuilderTest, FrameSizesLookGood) { | 419 TEST_F(BytecodeArrayBuilderTest, FrameSizesLookGood) { |
| 426 CanonicalHandleScope canonical(isolate()); | 420 CanonicalHandleScope canonical(isolate()); |
| 427 for (int locals = 0; locals < 5; locals++) { | 421 for (int locals = 0; locals < 5; locals++) { |
| 428 for (int contexts = 0; contexts < 4; contexts++) { | 422 for (int contexts = 0; contexts < 4; contexts++) { |
| 429 for (int temps = 0; temps < 3; temps++) { | 423 for (int temps = 0; temps < 3; temps++) { |
| 430 BytecodeArrayBuilder builder(isolate(), zone(), 0, contexts, locals); | 424 BytecodeArrayBuilder builder(isolate(), zone(), 0, contexts, locals); |
| 431 BytecodeRegisterAllocator temporaries( | 425 BytecodeRegisterAllocator* allocator(builder.register_allocator()); |
| 432 zone(), builder.temporary_register_allocator()); | |
| 433 for (int i = 0; i < locals + contexts; i++) { | 426 for (int i = 0; i < locals + contexts; i++) { |
| 434 builder.LoadLiteral(Smi::FromInt(0)); | 427 builder.LoadLiteral(Smi::FromInt(0)); |
| 435 builder.StoreAccumulatorInRegister(Register(i)); | 428 builder.StoreAccumulatorInRegister(Register(i)); |
| 436 } | 429 } |
| 437 for (int i = 0; i < temps; i++) { | 430 for (int i = 0; i < temps; i++) { |
| 431 Register temp = allocator->NewRegister(); |
| 438 builder.LoadLiteral(Smi::FromInt(0)); | 432 builder.LoadLiteral(Smi::FromInt(0)); |
| 439 builder.StoreAccumulatorInRegister(temporaries.NewRegister()); | 433 builder.StoreAccumulatorInRegister(temp); |
| 440 } | |
| 441 if (temps > 0) { | |
| 442 // Ensure temporaries are used so not optimized away by the | 434 // Ensure temporaries are used so not optimized away by the |
| 443 // register optimizer. | 435 // register optimizer. |
| 444 builder.New(Register(locals + contexts), Register(locals + contexts), | 436 builder.ConvertAccumulatorToName(temp); |
| 445 static_cast<size_t>(temps), 0); | |
| 446 } | 437 } |
| 447 builder.Return(); | 438 builder.Return(); |
| 448 | 439 |
| 449 Handle<BytecodeArray> the_array = builder.ToBytecodeArray(isolate()); | 440 Handle<BytecodeArray> the_array = builder.ToBytecodeArray(isolate()); |
| 450 int total_registers = locals + contexts + temps; | 441 int total_registers = locals + contexts + temps; |
| 451 CHECK_EQ(the_array->frame_size(), total_registers * kPointerSize); | 442 CHECK_EQ(the_array->frame_size(), total_registers * kPointerSize); |
| 452 } | 443 } |
| 453 } | 444 } |
| 454 } | 445 } |
| 455 } | 446 } |
| (...skipping 15 matching lines...) Expand all Loading... |
| 471 TEST_F(BytecodeArrayBuilderTest, Parameters) { | 462 TEST_F(BytecodeArrayBuilderTest, Parameters) { |
| 472 CanonicalHandleScope canonical(isolate()); | 463 CanonicalHandleScope canonical(isolate()); |
| 473 BytecodeArrayBuilder builder(isolate(), zone(), 10, 0, 0); | 464 BytecodeArrayBuilder builder(isolate(), zone(), 10, 0, 0); |
| 474 | 465 |
| 475 Register param0(builder.Parameter(0)); | 466 Register param0(builder.Parameter(0)); |
| 476 Register param9(builder.Parameter(9)); | 467 Register param9(builder.Parameter(9)); |
| 477 CHECK_EQ(param9.index() - param0.index(), 9); | 468 CHECK_EQ(param9.index() - param0.index(), 9); |
| 478 } | 469 } |
| 479 | 470 |
| 480 | 471 |
| 481 TEST_F(BytecodeArrayBuilderTest, RegisterType) { | |
| 482 CanonicalHandleScope canonical(isolate()); | |
| 483 BytecodeArrayBuilder builder(isolate(), zone(), 10, 0, 3); | |
| 484 BytecodeRegisterAllocator register_allocator( | |
| 485 zone(), builder.temporary_register_allocator()); | |
| 486 Register temp0 = register_allocator.NewRegister(); | |
| 487 Register param0(builder.Parameter(0)); | |
| 488 Register param9(builder.Parameter(9)); | |
| 489 Register temp1 = register_allocator.NewRegister(); | |
| 490 Register reg0(0); | |
| 491 Register reg1(1); | |
| 492 Register reg2(2); | |
| 493 Register temp2 = register_allocator.NewRegister(); | |
| 494 CHECK_EQ(builder.RegisterIsParameterOrLocal(temp0), false); | |
| 495 CHECK_EQ(builder.RegisterIsParameterOrLocal(temp1), false); | |
| 496 CHECK_EQ(builder.RegisterIsParameterOrLocal(temp2), false); | |
| 497 CHECK_EQ(builder.RegisterIsParameterOrLocal(param0), true); | |
| 498 CHECK_EQ(builder.RegisterIsParameterOrLocal(param9), true); | |
| 499 CHECK_EQ(builder.RegisterIsParameterOrLocal(reg0), true); | |
| 500 CHECK_EQ(builder.RegisterIsParameterOrLocal(reg1), true); | |
| 501 CHECK_EQ(builder.RegisterIsParameterOrLocal(reg2), true); | |
| 502 } | |
| 503 | |
| 504 | |
| 505 TEST_F(BytecodeArrayBuilderTest, Constants) { | 472 TEST_F(BytecodeArrayBuilderTest, Constants) { |
| 506 CanonicalHandleScope canonical(isolate()); | 473 CanonicalHandleScope canonical(isolate()); |
| 507 BytecodeArrayBuilder builder(isolate(), zone(), 0, 0, 0); | 474 BytecodeArrayBuilder builder(isolate(), zone(), 0, 0, 0); |
| 508 | 475 |
| 509 Factory* factory = isolate()->factory(); | 476 Factory* factory = isolate()->factory(); |
| 510 Handle<HeapObject> heap_num_1 = factory->NewHeapNumber(3.14); | 477 Handle<HeapObject> heap_num_1 = factory->NewHeapNumber(3.14); |
| 511 Handle<HeapObject> heap_num_2 = factory->NewHeapNumber(5.2); | 478 Handle<HeapObject> heap_num_2 = factory->NewHeapNumber(5.2); |
| 512 Handle<Object> large_smi(Smi::FromInt(0x12345678), isolate()); | 479 Handle<Object> large_smi(Smi::FromInt(0x12345678), isolate()); |
| 513 Handle<HeapObject> heap_num_2_copy(*heap_num_2); | 480 Handle<HeapObject> heap_num_2_copy(*heap_num_2); |
| 514 builder.LoadLiteral(heap_num_1) | 481 builder.LoadLiteral(heap_num_1) |
| (...skipping 250 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 765 iterator.Advance(); | 732 iterator.Advance(); |
| 766 } | 733 } |
| 767 CHECK_EQ(iterator.current_bytecode(), Bytecode::kReturn); | 734 CHECK_EQ(iterator.current_bytecode(), Bytecode::kReturn); |
| 768 iterator.Advance(); | 735 iterator.Advance(); |
| 769 CHECK(iterator.done()); | 736 CHECK(iterator.done()); |
| 770 } | 737 } |
| 771 | 738 |
| 772 } // namespace interpreter | 739 } // namespace interpreter |
| 773 } // namespace internal | 740 } // namespace internal |
| 774 } // namespace v8 | 741 } // namespace v8 |
| OLD | NEW |