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-register-allocator.h" | 9 #include "src/interpreter/bytecode-register-allocator.h" |
10 #include "test/unittests/test-utils.h" | 10 #include "test/unittests/test-utils.h" |
11 | 11 |
12 namespace v8 { | 12 namespace v8 { |
13 namespace internal { | 13 namespace internal { |
14 namespace interpreter { | 14 namespace interpreter { |
15 | 15 |
16 class BytecodeArrayBuilderTest : public TestWithIsolateAndZone { | 16 class BytecodeArrayBuilderTest : public TestWithIsolateAndZone { |
17 public: | 17 public: |
18 BytecodeArrayBuilderTest() {} | 18 BytecodeArrayBuilderTest() {} |
19 ~BytecodeArrayBuilderTest() override {} | 19 ~BytecodeArrayBuilderTest() override {} |
20 }; | 20 }; |
21 | 21 |
22 | 22 |
23 TEST_F(BytecodeArrayBuilderTest, AllBytecodesGenerated) { | 23 TEST_F(BytecodeArrayBuilderTest, AllBytecodesGenerated) { |
24 BytecodeArrayBuilder builder(isolate(), zone()); | 24 BytecodeArrayBuilder builder(isolate(), zone()); |
25 | 25 |
26 builder.set_locals_count(200); | 26 builder.set_locals_count(131); |
27 builder.set_context_count(1); | 27 builder.set_context_count(1); |
28 builder.set_parameter_count(0); | 28 builder.set_parameter_count(0); |
29 CHECK_EQ(builder.locals_count(), 200); | 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(), 201); | 31 CHECK_EQ(builder.fixed_register_count(), 132); |
32 | 32 |
33 // Emit constant loads. | 33 // Emit constant loads. |
34 builder.LoadLiteral(Smi::FromInt(0)) | 34 builder.LoadLiteral(Smi::FromInt(0)) |
35 .LoadLiteral(Smi::FromInt(8)) | 35 .LoadLiteral(Smi::FromInt(8)) |
36 .LoadLiteral(Smi::FromInt(10000000)) | 36 .LoadLiteral(Smi::FromInt(10000000)) |
37 .LoadUndefined() | 37 .LoadUndefined() |
38 .LoadNull() | 38 .LoadNull() |
39 .LoadTheHole() | 39 .LoadTheHole() |
40 .LoadTrue() | 40 .LoadTrue() |
41 .LoadFalse(); | 41 .LoadFalse(); |
42 | 42 |
43 // Emit accumulator transfers. Stores followed by loads to the same register | |
44 // are not generated. Hence, a dummy instruction in between. | |
45 Register reg(0); | 43 Register reg(0); |
| 44 Register other(reg.index() + 1); |
| 45 Register wide(128); |
| 46 |
46 builder.LoadAccumulatorWithRegister(reg) | 47 builder.LoadAccumulatorWithRegister(reg) |
47 .LoadNull() | 48 .LoadNull() |
48 .StoreAccumulatorInRegister(reg); | 49 .StoreAccumulatorInRegister(reg); |
49 | 50 |
50 // Emit register-register transfer. | 51 // Emit register-register transfer. |
51 Register other(1); | |
52 builder.MoveRegister(reg, other); | 52 builder.MoveRegister(reg, other); |
53 | 53 builder.MoveRegister(reg, wide); |
54 // Emit register-register exchanges. | |
55 Register wide(150); | |
56 builder.ExchangeRegisters(reg, wide); | |
57 builder.ExchangeRegisters(wide, reg); | |
58 Register wider(151); | |
59 builder.ExchangeRegisters(wide, wider); | |
60 | 54 |
61 // Emit global load / store operations. | 55 // Emit global load / store operations. |
62 Factory* factory = isolate()->factory(); | 56 Factory* factory = isolate()->factory(); |
63 Handle<String> name = factory->NewStringFromStaticChars("var_name"); | 57 Handle<String> name = factory->NewStringFromStaticChars("var_name"); |
64 builder.LoadGlobal(name, 1, LanguageMode::SLOPPY, | 58 builder.LoadGlobal(name, 1, LanguageMode::SLOPPY, |
65 TypeofMode::NOT_INSIDE_TYPEOF) | 59 TypeofMode::NOT_INSIDE_TYPEOF) |
66 .LoadGlobal(name, 1, LanguageMode::STRICT, TypeofMode::NOT_INSIDE_TYPEOF) | 60 .LoadGlobal(name, 1, LanguageMode::STRICT, TypeofMode::NOT_INSIDE_TYPEOF) |
67 .LoadGlobal(name, 1, LanguageMode::SLOPPY, TypeofMode::INSIDE_TYPEOF) | 61 .LoadGlobal(name, 1, LanguageMode::SLOPPY, TypeofMode::INSIDE_TYPEOF) |
68 .LoadGlobal(name, 1, LanguageMode::STRICT, TypeofMode::INSIDE_TYPEOF) | 62 .LoadGlobal(name, 1, LanguageMode::STRICT, TypeofMode::INSIDE_TYPEOF) |
69 .StoreGlobal(name, 1, LanguageMode::SLOPPY) | 63 .StoreGlobal(name, 1, LanguageMode::SLOPPY) |
(...skipping 30 matching lines...) Expand all Loading... |
100 // Emit argument creation operations. | 94 // Emit argument creation operations. |
101 builder.CreateArguments(CreateArgumentsType::kMappedArguments) | 95 builder.CreateArguments(CreateArgumentsType::kMappedArguments) |
102 .CreateArguments(CreateArgumentsType::kUnmappedArguments); | 96 .CreateArguments(CreateArgumentsType::kUnmappedArguments); |
103 | 97 |
104 // Emit literal creation operations. | 98 // Emit literal creation operations. |
105 builder.CreateRegExpLiteral(factory->NewStringFromStaticChars("a"), 0, 0) | 99 builder.CreateRegExpLiteral(factory->NewStringFromStaticChars("a"), 0, 0) |
106 .CreateArrayLiteral(factory->NewFixedArray(1), 0, 0) | 100 .CreateArrayLiteral(factory->NewFixedArray(1), 0, 0) |
107 .CreateObjectLiteral(factory->NewFixedArray(1), 0, 0); | 101 .CreateObjectLiteral(factory->NewFixedArray(1), 0, 0); |
108 | 102 |
109 // Call operations. | 103 // Call operations. |
110 builder.Call(reg, reg, 0, 0) | 104 builder.Call(reg, other, 1, 0) |
111 .Call(reg, reg, 0, 1024) | 105 .Call(reg, wide, 1, 0) |
112 .CallRuntime(Runtime::kIsArray, reg, 1) | 106 .CallRuntime(Runtime::kIsArray, reg, 1) |
113 .CallRuntimeForPair(Runtime::kLoadLookupSlot, reg, 1, reg) | 107 .CallRuntime(Runtime::kIsArray, wide, 1) |
114 .CallJSRuntime(Context::SPREAD_ITERABLE_INDEX, reg, 1); | 108 .CallRuntimeForPair(Runtime::kLoadLookupSlot, reg, 1, other) |
| 109 .CallRuntimeForPair(Runtime::kLoadLookupSlot, wide, 1, other) |
| 110 .CallJSRuntime(Context::SPREAD_ITERABLE_INDEX, reg, 1) |
| 111 .CallJSRuntime(Context::SPREAD_ITERABLE_INDEX, wide, 1); |
115 | 112 |
116 // Emit binary operator invocations. | 113 // Emit binary operator invocations. |
117 builder.BinaryOperation(Token::Value::ADD, reg, Strength::WEAK) | 114 builder.BinaryOperation(Token::Value::ADD, reg, Strength::WEAK) |
118 .BinaryOperation(Token::Value::SUB, reg, Strength::WEAK) | 115 .BinaryOperation(Token::Value::SUB, reg, Strength::WEAK) |
119 .BinaryOperation(Token::Value::MUL, reg, Strength::WEAK) | 116 .BinaryOperation(Token::Value::MUL, reg, Strength::WEAK) |
120 .BinaryOperation(Token::Value::DIV, reg, Strength::WEAK) | 117 .BinaryOperation(Token::Value::DIV, reg, Strength::WEAK) |
121 .BinaryOperation(Token::Value::MOD, reg, Strength::WEAK); | 118 .BinaryOperation(Token::Value::MOD, reg, Strength::WEAK); |
122 | 119 |
123 // Emit bitwise operator invocations | 120 // Emit bitwise operator invocations |
124 builder.BinaryOperation(Token::Value::BIT_OR, reg, Strength::WEAK) | 121 builder.BinaryOperation(Token::Value::BIT_OR, reg, Strength::WEAK) |
(...skipping 12 matching lines...) Expand all Loading... |
137 // Emit unary operator invocations. | 134 // Emit unary operator invocations. |
138 builder.LogicalNot().TypeOf(); | 135 builder.LogicalNot().TypeOf(); |
139 | 136 |
140 // Emit delete | 137 // Emit delete |
141 builder.Delete(reg, LanguageMode::SLOPPY) | 138 builder.Delete(reg, LanguageMode::SLOPPY) |
142 .Delete(reg, LanguageMode::STRICT) | 139 .Delete(reg, LanguageMode::STRICT) |
143 .DeleteLookupSlot(); | 140 .DeleteLookupSlot(); |
144 | 141 |
145 // Emit new. | 142 // Emit new. |
146 builder.New(reg, reg, 0); | 143 builder.New(reg, reg, 0); |
| 144 builder.New(wide, wide, 0); |
147 | 145 |
148 // Emit test operator invocations. | 146 // Emit test operator invocations. |
149 builder.CompareOperation(Token::Value::EQ, reg, Strength::WEAK) | 147 builder.CompareOperation(Token::Value::EQ, reg, Strength::WEAK) |
150 .CompareOperation(Token::Value::NE, reg, Strength::WEAK) | 148 .CompareOperation(Token::Value::NE, reg, Strength::WEAK) |
151 .CompareOperation(Token::Value::EQ_STRICT, reg, Strength::WEAK) | 149 .CompareOperation(Token::Value::EQ_STRICT, reg, Strength::WEAK) |
152 .CompareOperation(Token::Value::NE_STRICT, reg, Strength::WEAK) | 150 .CompareOperation(Token::Value::NE_STRICT, reg, Strength::WEAK) |
153 .CompareOperation(Token::Value::LT, reg, Strength::WEAK) | 151 .CompareOperation(Token::Value::LT, reg, Strength::WEAK) |
154 .CompareOperation(Token::Value::GT, reg, Strength::WEAK) | 152 .CompareOperation(Token::Value::GT, reg, Strength::WEAK) |
155 .CompareOperation(Token::Value::LTE, reg, Strength::WEAK) | 153 .CompareOperation(Token::Value::LTE, reg, Strength::WEAK) |
156 .CompareOperation(Token::Value::GTE, reg, Strength::WEAK) | 154 .CompareOperation(Token::Value::GTE, reg, Strength::WEAK) |
(...skipping 41 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
198 // Perform an operation that returns a non-boolean operation to | 196 // Perform an operation that returns a non-boolean operation to |
199 // generate JumpIfToBooleanTrue/False. | 197 // generate JumpIfToBooleanTrue/False. |
200 builder.BinaryOperation(Token::Value::ADD, reg, Strength::WEAK) | 198 builder.BinaryOperation(Token::Value::ADD, reg, Strength::WEAK) |
201 .JumpIfTrue(&start) | 199 .JumpIfTrue(&start) |
202 .BinaryOperation(Token::Value::ADD, reg, Strength::WEAK) | 200 .BinaryOperation(Token::Value::ADD, reg, Strength::WEAK) |
203 .JumpIfFalse(&start); | 201 .JumpIfFalse(&start); |
204 | 202 |
205 // Emit throw in it's own basic block so that the rest of the code isn't | 203 // Emit throw in it's own basic block so that the rest of the code isn't |
206 // omitted due to being dead. | 204 // omitted due to being dead. |
207 BytecodeLabel after_throw; | 205 BytecodeLabel after_throw; |
208 builder.Jump(&after_throw) | 206 builder.Jump(&after_throw).Throw().Bind(&after_throw); |
209 .Throw() | |
210 .Bind(&after_throw); | |
211 | 207 |
212 builder.ForInPrepare(reg) | 208 builder.ForInPrepare(reg) |
213 .ForInDone(reg, reg) | 209 .ForInDone(reg, reg) |
214 .ForInNext(reg, reg, reg) | 210 .ForInNext(reg, reg, reg) |
215 .ForInStep(reg); | 211 .ForInStep(reg); |
| 212 builder.ForInPrepare(wide) |
| 213 .ForInDone(reg, other) |
| 214 .ForInNext(wide, wide, wide) |
| 215 .ForInStep(reg); |
216 | 216 |
217 // Wide constant pool loads | 217 // Wide constant pool loads |
218 for (int i = 0; i < 256; i++) { | 218 for (int i = 0; i < 256; i++) { |
219 // Emit junk in constant pool to force wide constant pool index. | 219 // Emit junk in constant pool to force wide constant pool index. |
220 builder.LoadLiteral(factory->NewNumber(2.5321 + i)); | 220 builder.LoadLiteral(factory->NewNumber(2.5321 + i)); |
221 } | 221 } |
222 builder.LoadLiteral(Smi::FromInt(20000000)); | 222 builder.LoadLiteral(Smi::FromInt(20000000)); |
223 Handle<String> wide_name = factory->NewStringFromStaticChars("var_wide_name"); | 223 Handle<String> wide_name = factory->NewStringFromStaticChars("var_wide_name"); |
224 | 224 |
225 // Emit wide global load / store operations. | 225 // Emit wide global load / store operations. |
(...skipping 10 matching lines...) Expand all Loading... |
236 builder.LoadNamedProperty(reg, wide_name, 0, LanguageMode::SLOPPY) | 236 builder.LoadNamedProperty(reg, wide_name, 0, LanguageMode::SLOPPY) |
237 .LoadKeyedProperty(reg, 2056, LanguageMode::SLOPPY) | 237 .LoadKeyedProperty(reg, 2056, LanguageMode::SLOPPY) |
238 .StoreNamedProperty(reg, wide_name, 0, LanguageMode::SLOPPY) | 238 .StoreNamedProperty(reg, wide_name, 0, LanguageMode::SLOPPY) |
239 .StoreKeyedProperty(reg, reg, 2056, LanguageMode::SLOPPY) | 239 .StoreKeyedProperty(reg, reg, 2056, LanguageMode::SLOPPY) |
240 .LoadNamedProperty(reg, wide_name, 0, LanguageMode::STRICT) | 240 .LoadNamedProperty(reg, wide_name, 0, LanguageMode::STRICT) |
241 .LoadKeyedProperty(reg, 2056, LanguageMode::STRICT) | 241 .LoadKeyedProperty(reg, 2056, LanguageMode::STRICT) |
242 .StoreNamedProperty(reg, wide_name, 0, LanguageMode::STRICT) | 242 .StoreNamedProperty(reg, wide_name, 0, LanguageMode::STRICT) |
243 .StoreKeyedProperty(reg, reg, 2056, LanguageMode::STRICT); | 243 .StoreKeyedProperty(reg, reg, 2056, LanguageMode::STRICT); |
244 | 244 |
245 // Emit wide context operations. | 245 // Emit wide context operations. |
246 builder.LoadContextSlot(reg, 1024) | 246 builder.LoadContextSlot(reg, 1024).StoreContextSlot(reg, 1024); |
247 .StoreContextSlot(reg, 1024); | |
248 | 247 |
249 // Emit wide load / store lookup slots. | 248 // Emit wide load / store lookup slots. |
250 builder.LoadLookupSlot(wide_name, TypeofMode::NOT_INSIDE_TYPEOF) | 249 builder.LoadLookupSlot(wide_name, TypeofMode::NOT_INSIDE_TYPEOF) |
251 .LoadLookupSlot(wide_name, TypeofMode::INSIDE_TYPEOF) | 250 .LoadLookupSlot(wide_name, TypeofMode::INSIDE_TYPEOF) |
252 .StoreLookupSlot(wide_name, LanguageMode::SLOPPY) | 251 .StoreLookupSlot(wide_name, LanguageMode::SLOPPY) |
253 .StoreLookupSlot(wide_name, LanguageMode::STRICT); | 252 .StoreLookupSlot(wide_name, LanguageMode::STRICT); |
254 | 253 |
255 // CreateClosureWide | 254 // CreateClosureWide |
256 Handle<SharedFunctionInfo> shared_info2 = factory->NewSharedFunctionInfo( | 255 Handle<SharedFunctionInfo> shared_info2 = factory->NewSharedFunctionInfo( |
257 factory->NewStringFromStaticChars("function_b"), MaybeHandle<Code>(), | 256 factory->NewStringFromStaticChars("function_b"), MaybeHandle<Code>(), |
(...skipping 425 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
683 } | 682 } |
684 CHECK_EQ(iterator.current_bytecode(), Bytecode::kReturn); | 683 CHECK_EQ(iterator.current_bytecode(), Bytecode::kReturn); |
685 iterator.Advance(); | 684 iterator.Advance(); |
686 CHECK(iterator.done()); | 685 CHECK(iterator.done()); |
687 } | 686 } |
688 | 687 |
689 | 688 |
690 } // namespace interpreter | 689 } // namespace interpreter |
691 } // namespace internal | 690 } // namespace internal |
692 } // namespace v8 | 691 } // namespace v8 |
OLD | NEW |