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/interpreter/bytecode-array-builder.h" | 5 #include "src/interpreter/bytecode-array-builder.h" |
6 #include "src/compiler.h" | 6 #include "src/compiler.h" |
7 | 7 |
8 namespace v8 { | 8 namespace v8 { |
9 namespace internal { | 9 namespace internal { |
10 namespace interpreter { | 10 namespace interpreter { |
11 | 11 |
12 class BytecodeArrayBuilder::PreviousBytecodeHelper BASE_EMBEDDED { | 12 class BytecodeArrayBuilder::PreviousBytecodeHelper BASE_EMBEDDED { |
13 public: | 13 public: |
14 explicit PreviousBytecodeHelper(const BytecodeArrayBuilder& array_builder) | 14 explicit PreviousBytecodeHelper(const BytecodeArrayBuilder& array_builder) |
15 : array_builder_(array_builder), | 15 : array_builder_(array_builder), |
16 previous_bytecode_start_(array_builder_.last_bytecode_start_) { | 16 previous_bytecode_start_(array_builder_.last_bytecode_start_) { |
17 // This helper is expected to be instantiated only when the last bytecode is | 17 // This helper is expected to be instantiated only when the last bytecode is |
18 // in the same basic block. | 18 // in the same basic block. |
19 DCHECK(array_builder_.LastBytecodeInSameBlock()); | 19 DCHECK(array_builder_.LastBytecodeInSameBlock()); |
20 bytecode_ = Bytecodes::FromByte( | |
21 array_builder_.bytecodes()->at(previous_bytecode_start_)); | |
22 operand_scale_ = Bytecodes::GetPrefixBytecodeScale(bytecode_); | |
23 if (operand_scale_ > 1) { | |
24 bytecode_ = Bytecodes::FromByte( | |
25 array_builder_.bytecodes()->at(previous_bytecode_start_ + 1)); | |
26 } | |
rmcilroy
2016/03/16 11:55:54
I would prefer this as:
operand_scale_ = 1;
if (
oth
2016/03/17 13:48:38
Done.
| |
20 } | 27 } |
21 | 28 |
22 // Returns the previous bytecode in the same basic block. | 29 // Returns the previous bytecode in the same basic block. |
23 MUST_USE_RESULT Bytecode GetBytecode() const { | 30 MUST_USE_RESULT Bytecode GetBytecode() const { |
24 DCHECK_EQ(array_builder_.last_bytecode_start_, previous_bytecode_start_); | 31 DCHECK_EQ(array_builder_.last_bytecode_start_, previous_bytecode_start_); |
25 return Bytecodes::FromByte( | 32 return bytecode_; |
26 array_builder_.bytecodes()->at(previous_bytecode_start_)); | |
27 } | 33 } |
28 | 34 |
29 // Returns the operand at operand_index for the previous bytecode in the | 35 MUST_USE_RESULT Register GetRegisterOperand(int operand_index) const { |
30 // same basic block. | 36 return Register::FromOperand(GetSignedOperand(operand_index)); |
31 MUST_USE_RESULT uint32_t GetOperand(int operand_index) const { | 37 } |
38 | |
39 MUST_USE_RESULT uint32_t GetIndexOperand(int operand_index) const { | |
40 return GetUnsignedOperand(operand_index); | |
41 } | |
42 | |
43 Handle<Object> GetConstantForIndexOperand(int operand_index) const { | |
44 return array_builder_.constant_array_builder()->At( | |
45 GetIndexOperand(operand_index)); | |
46 } | |
47 | |
48 private: | |
49 // Returns the signed operand at operand_index for the previous | |
50 // bytecode in the same basic block. | |
51 MUST_USE_RESULT int32_t GetSignedOperand(int operand_index) const { | |
32 DCHECK_EQ(array_builder_.last_bytecode_start_, previous_bytecode_start_); | 52 DCHECK_EQ(array_builder_.last_bytecode_start_, previous_bytecode_start_); |
33 Bytecode bytecode = GetBytecode(); | 53 OperandType operand_type = |
34 DCHECK_GE(operand_index, 0); | 54 Bytecodes::GetOperandType(bytecode_, operand_index); |
35 DCHECK_LT(operand_index, Bytecodes::NumberOfOperands(bytecode)); | 55 DCHECK(!Bytecodes::IsUnsignedOperandType(operand_type)); |
36 size_t operand_offset = | 56 size_t operand_offset = |
37 previous_bytecode_start_ + | 57 previous_bytecode_start_ + prefix_offset() + |
38 Bytecodes::GetOperandOffset(bytecode, operand_index); | 58 Bytecodes::GetOperandOffset(bytecode_, operand_index, operand_scale_); |
39 OperandSize size = Bytecodes::GetOperandSize(bytecode, operand_index); | 59 OperandSize operand_size = |
40 switch (size) { | 60 Bytecodes::SizeOfOperand(operand_type, operand_scale_); |
61 switch (operand_size) { | |
62 case OperandSize::kByte: | |
63 return static_cast<int8_t>(GetOperand(operand_offset, operand_size)); | |
64 case OperandSize::kShort: | |
65 return static_cast<int16_t>(GetOperand(operand_offset, operand_size)); | |
66 case OperandSize::kQuad: | |
67 return static_cast<int32_t>(GetOperand(operand_offset, operand_size)); | |
41 case OperandSize::kNone: | 68 case OperandSize::kNone: |
42 UNREACHABLE(); | 69 UNREACHABLE(); |
43 break; | 70 break; |
44 case OperandSize::kByte: | |
45 return static_cast<uint32_t>( | |
46 array_builder_.bytecodes()->at(operand_offset)); | |
47 case OperandSize::kShort: | |
48 uint16_t operand = | |
49 (array_builder_.bytecodes()->at(operand_offset) << 8) + | |
50 array_builder_.bytecodes()->at(operand_offset + 1); | |
51 return static_cast<uint32_t>(operand); | |
52 } | 71 } |
53 return 0; | 72 return 0; |
54 } | 73 } |
55 | 74 |
56 Handle<Object> GetConstantForIndexOperand(int operand_index) const { | 75 // Returns the unsigned operand at operand_index for the previous |
57 return array_builder_.constant_array_builder()->At( | 76 // bytecode in the same basic block. |
58 GetOperand(operand_index)); | 77 MUST_USE_RESULT int32_t GetUnsignedOperand(int operand_index) const { |
78 DCHECK_EQ(array_builder_.last_bytecode_start_, previous_bytecode_start_); | |
79 OperandType operand_type = | |
80 Bytecodes::GetOperandType(bytecode_, operand_index); | |
81 DCHECK(Bytecodes::IsUnsignedOperandType(operand_type)); | |
82 size_t operand_offset = | |
83 previous_bytecode_start_ + prefix_offset() + | |
84 Bytecodes::GetOperandOffset(bytecode_, operand_index, operand_scale_); | |
85 return GetOperand(operand_offset, | |
86 Bytecodes::SizeOfOperand(operand_type, operand_scale_)); | |
59 } | 87 } |
60 | 88 |
61 private: | 89 MUST_USE_RESULT uint32_t GetOperand(size_t operand_offset, |
90 OperandSize operand_size) const { | |
91 DCHECK(operand_size >= OperandSize::kByte && | |
92 operand_size <= OperandSize::kQuad); | |
93 uint32_t result = array_builder_.bytecodes()->at(operand_offset); | |
94 for (size_t i = 1; i < static_cast<size_t>(operand_size); ++i) { | |
95 result <<= 8; | |
96 result |= array_builder_.bytecodes()->at(operand_offset + 1); | |
97 } | |
98 return result; | |
99 } | |
100 | |
101 int prefix_offset() const { return operand_scale_ > 1 ? 1 : 0; } | |
102 | |
62 const BytecodeArrayBuilder& array_builder_; | 103 const BytecodeArrayBuilder& array_builder_; |
104 int operand_scale_; | |
105 Bytecode bytecode_; | |
63 size_t previous_bytecode_start_; | 106 size_t previous_bytecode_start_; |
64 | 107 |
65 DISALLOW_COPY_AND_ASSIGN(PreviousBytecodeHelper); | 108 DISALLOW_COPY_AND_ASSIGN(PreviousBytecodeHelper); |
66 }; | 109 }; |
67 | 110 |
68 BytecodeArrayBuilder::BytecodeArrayBuilder(Isolate* isolate, Zone* zone, | 111 BytecodeArrayBuilder::BytecodeArrayBuilder(Isolate* isolate, Zone* zone, |
69 int parameter_count, | 112 int parameter_count, |
70 int context_count, int locals_count, | 113 int context_count, int locals_count, |
71 FunctionLiteral* literal) | 114 FunctionLiteral* literal) |
72 : isolate_(isolate), | 115 : isolate_(isolate), |
73 zone_(zone), | 116 zone_(zone), |
74 bytecodes_(zone), | 117 bytecodes_(zone), |
75 bytecode_generated_(false), | 118 bytecode_generated_(false), |
76 constant_array_builder_(isolate, zone), | 119 constant_array_builder_(isolate, zone), |
77 handler_table_builder_(isolate, zone), | 120 handler_table_builder_(isolate, zone), |
78 source_position_table_builder_(isolate, zone), | 121 source_position_table_builder_(isolate, zone), |
79 last_block_end_(0), | 122 last_block_end_(0), |
80 last_bytecode_start_(~0), | 123 last_bytecode_start_(~0), |
81 exit_seen_in_block_(false), | 124 exit_seen_in_block_(false), |
82 unbound_jumps_(0), | 125 unbound_jumps_(0), |
83 parameter_count_(parameter_count), | 126 parameter_count_(parameter_count), |
84 local_register_count_(locals_count), | 127 local_register_count_(locals_count), |
85 context_register_count_(context_count), | 128 context_register_count_(context_count), |
86 temporary_allocator_(zone, fixed_register_count()), | 129 temporary_allocator_(zone, fixed_register_count()) { |
87 register_translator_(this) { | |
88 DCHECK_GE(parameter_count_, 0); | 130 DCHECK_GE(parameter_count_, 0); |
89 DCHECK_GE(context_register_count_, 0); | 131 DCHECK_GE(context_register_count_, 0); |
90 DCHECK_GE(local_register_count_, 0); | 132 DCHECK_GE(local_register_count_, 0); |
91 return_position_ = | 133 return_position_ = |
92 literal ? std::max(literal->start_position(), literal->end_position() - 1) | 134 literal ? std::max(literal->start_position(), literal->end_position() - 1) |
93 : RelocInfo::kNoPosition; | 135 : RelocInfo::kNoPosition; |
94 LOG_CODE_EVENT(isolate_, CodeStartLinePosInfoRecordEvent( | 136 LOG_CODE_EVENT(isolate_, CodeStartLinePosInfoRecordEvent( |
95 source_position_table_builder())); | 137 source_position_table_builder())); |
96 } | 138 } |
97 | 139 |
(...skipping 20 matching lines...) Expand all Loading... | |
118 bool BytecodeArrayBuilder::RegisterIsParameterOrLocal(Register reg) const { | 160 bool BytecodeArrayBuilder::RegisterIsParameterOrLocal(Register reg) const { |
119 return reg.is_parameter() || reg.index() < locals_count(); | 161 return reg.is_parameter() || reg.index() < locals_count(); |
120 } | 162 } |
121 | 163 |
122 | 164 |
123 Handle<BytecodeArray> BytecodeArrayBuilder::ToBytecodeArray() { | 165 Handle<BytecodeArray> BytecodeArrayBuilder::ToBytecodeArray() { |
124 DCHECK_EQ(bytecode_generated_, false); | 166 DCHECK_EQ(bytecode_generated_, false); |
125 DCHECK(exit_seen_in_block_); | 167 DCHECK(exit_seen_in_block_); |
126 | 168 |
127 int bytecode_size = static_cast<int>(bytecodes_.size()); | 169 int bytecode_size = static_cast<int>(bytecodes_.size()); |
128 int register_count = | 170 int register_count = fixed_and_temporary_register_count(); |
129 fixed_and_temporary_register_count() + translation_register_count(); | |
130 int frame_size = register_count * kPointerSize; | 171 int frame_size = register_count * kPointerSize; |
131 Handle<FixedArray> constant_pool = constant_array_builder()->ToFixedArray(); | 172 Handle<FixedArray> constant_pool = constant_array_builder()->ToFixedArray(); |
132 Handle<FixedArray> handler_table = handler_table_builder()->ToHandlerTable(); | 173 Handle<FixedArray> handler_table = handler_table_builder()->ToHandlerTable(); |
133 Handle<ByteArray> source_position_table = | 174 Handle<ByteArray> source_position_table = |
134 source_position_table_builder()->ToSourcePositionTable(); | 175 source_position_table_builder()->ToSourcePositionTable(); |
135 Handle<BytecodeArray> bytecode_array = isolate_->factory()->NewBytecodeArray( | 176 Handle<BytecodeArray> bytecode_array = isolate_->factory()->NewBytecodeArray( |
136 bytecode_size, &bytecodes_.front(), frame_size, parameter_count(), | 177 bytecode_size, &bytecodes_.front(), frame_size, parameter_count(), |
137 constant_pool); | 178 constant_pool); |
138 bytecode_array->set_handler_table(*handler_table); | 179 bytecode_array->set_handler_table(*handler_table); |
139 bytecode_array->set_source_position_table(*source_position_table); | 180 bytecode_array->set_source_position_table(*source_position_table); |
140 | 181 |
141 void* line_info = source_position_table_builder()->DetachJITHandlerData(); | 182 void* line_info = source_position_table_builder()->DetachJITHandlerData(); |
142 LOG_CODE_EVENT(isolate_, CodeEndLinePosInfoRecordEvent( | 183 LOG_CODE_EVENT(isolate_, CodeEndLinePosInfoRecordEvent( |
143 AbstractCode::cast(*bytecode_array), line_info)); | 184 AbstractCode::cast(*bytecode_array), line_info)); |
144 | 185 |
145 bytecode_generated_ = true; | 186 bytecode_generated_ = true; |
146 return bytecode_array; | 187 return bytecode_array; |
147 } | 188 } |
148 | 189 |
149 | |
150 template <size_t N> | 190 template <size_t N> |
151 void BytecodeArrayBuilder::Output(Bytecode bytecode, uint32_t(&operands)[N]) { | 191 void BytecodeArrayBuilder::Output(Bytecode bytecode, uint32_t (&operands)[N], |
192 int operand_scale) { | |
152 // Don't output dead code. | 193 // Don't output dead code. |
153 if (exit_seen_in_block_) return; | 194 if (exit_seen_in_block_) return; |
154 | 195 |
155 int operand_count = static_cast<int>(N); | 196 int operand_count = static_cast<int>(N); |
156 DCHECK_EQ(Bytecodes::NumberOfOperands(bytecode), operand_count); | 197 DCHECK_EQ(Bytecodes::NumberOfOperands(bytecode), operand_count); |
157 | 198 |
158 int register_operand_count = Bytecodes::NumberOfRegisterOperands(bytecode); | 199 last_bytecode_start_ = bytecodes()->size(); |
159 if (register_operand_count > 0) { | 200 |
160 register_translator()->TranslateInputRegisters(bytecode, operands, | 201 // Emit prefix if scaling is active. |
161 operand_count); | 202 switch (operand_scale) { |
203 case 4: | |
204 bytecodes()->push_back(Bytecodes::ToByte(Bytecode::kExtraWide)); | |
205 break; | |
206 case 2: | |
207 bytecodes()->push_back(Bytecodes::ToByte(Bytecode::kWide)); | |
208 break; | |
209 case 1: | |
210 break; | |
211 default: | |
212 UNREACHABLE(); | |
213 break; | |
162 } | 214 } |
163 | 215 |
164 last_bytecode_start_ = bytecodes()->size(); | 216 // Emit bytecode. |
165 bytecodes()->push_back(Bytecodes::ToByte(bytecode)); | 217 bytecodes()->push_back(Bytecodes::ToByte(bytecode)); |
218 | |
219 // Emit operands. | |
166 for (int i = 0; i < operand_count; i++) { | 220 for (int i = 0; i < operand_count; i++) { |
167 DCHECK(OperandIsValid(bytecode, i, operands[i])); | 221 DCHECK(OperandIsValid(bytecode, i, operand_scale, operands[i])); |
168 switch (Bytecodes::GetOperandSize(bytecode, i)) { | 222 switch (Bytecodes::GetOperandSize(bytecode, i, operand_scale)) { |
169 case OperandSize::kNone: | 223 case OperandSize::kNone: |
170 UNREACHABLE(); | 224 UNREACHABLE(); |
171 break; | 225 break; |
172 case OperandSize::kByte: | 226 case OperandSize::kByte: |
173 bytecodes()->push_back(static_cast<uint8_t>(operands[i])); | 227 bytecodes()->push_back(static_cast<uint8_t>(operands[i])); |
174 break; | 228 break; |
175 case OperandSize::kShort: { | 229 case OperandSize::kShort: { |
176 uint8_t operand_bytes[2]; | 230 uint8_t operand_bytes[2]; |
177 WriteUnalignedUInt16(operand_bytes, operands[i]); | 231 WriteUnalignedUInt16(operand_bytes, operands[i]); |
178 bytecodes()->insert(bytecodes()->end(), operand_bytes, | 232 bytecodes()->insert(bytecodes()->end(), operand_bytes, |
179 operand_bytes + 2); | 233 operand_bytes + 2); |
180 break; | 234 break; |
181 } | 235 } |
236 case OperandSize::kQuad: { | |
237 uint8_t operand_bytes[4]; | |
238 WriteUnalignedUInt32(operand_bytes, operands[i]); | |
239 bytecodes()->insert(bytecodes()->end(), operand_bytes, | |
240 operand_bytes + 4); | |
241 break; | |
242 } | |
182 } | 243 } |
183 } | 244 } |
184 | |
185 if (register_operand_count > 0) { | |
186 register_translator()->TranslateOutputRegisters(); | |
187 } | |
188 } | 245 } |
189 | 246 |
190 | |
191 void BytecodeArrayBuilder::Output(Bytecode bytecode, uint32_t operand0, | |
192 uint32_t operand1, uint32_t operand2, | |
193 uint32_t operand3) { | |
194 uint32_t operands[] = {operand0, operand1, operand2, operand3}; | |
195 Output(bytecode, operands); | |
196 } | |
197 | |
198 | |
199 void BytecodeArrayBuilder::Output(Bytecode bytecode, uint32_t operand0, | |
200 uint32_t operand1, uint32_t operand2) { | |
201 uint32_t operands[] = {operand0, operand1, operand2}; | |
202 Output(bytecode, operands); | |
203 } | |
204 | |
205 | |
206 void BytecodeArrayBuilder::Output(Bytecode bytecode, uint32_t operand0, | |
207 uint32_t operand1) { | |
208 uint32_t operands[] = {operand0, operand1}; | |
209 Output(bytecode, operands); | |
210 } | |
211 | |
212 | |
213 void BytecodeArrayBuilder::Output(Bytecode bytecode, uint32_t operand0) { | |
214 uint32_t operands[] = {operand0}; | |
215 Output(bytecode, operands); | |
216 } | |
217 | |
218 | |
219 void BytecodeArrayBuilder::Output(Bytecode bytecode) { | 247 void BytecodeArrayBuilder::Output(Bytecode bytecode) { |
220 // Don't output dead code. | 248 // Don't output dead code. |
221 if (exit_seen_in_block_) return; | 249 if (exit_seen_in_block_) return; |
222 | 250 |
223 DCHECK_EQ(Bytecodes::NumberOfOperands(bytecode), 0); | 251 DCHECK_EQ(Bytecodes::NumberOfOperands(bytecode), 0); |
224 last_bytecode_start_ = bytecodes()->size(); | 252 last_bytecode_start_ = bytecodes()->size(); |
225 bytecodes()->push_back(Bytecodes::ToByte(bytecode)); | 253 bytecodes()->push_back(Bytecodes::ToByte(bytecode)); |
226 } | 254 } |
227 | 255 |
256 void BytecodeArrayBuilder::OutputScaled(Bytecode bytecode, int operand_scale, | |
257 uint32_t operand0, uint32_t operand1, | |
258 uint32_t operand2, uint32_t operand3) { | |
259 uint32_t operands[] = {operand0, operand1, operand2, operand3}; | |
260 Output(bytecode, operands, operand_scale); | |
261 } | |
262 | |
263 void BytecodeArrayBuilder::OutputScaled(Bytecode bytecode, int operand_scale, | |
264 uint32_t operand0, uint32_t operand1, | |
265 uint32_t operand2) { | |
266 uint32_t operands[] = {operand0, operand1, operand2}; | |
267 Output(bytecode, operands, operand_scale); | |
268 } | |
269 | |
270 void BytecodeArrayBuilder::OutputScaled(Bytecode bytecode, int operand_scale, | |
271 uint32_t operand0, uint32_t operand1) { | |
272 uint32_t operands[] = {operand0, operand1}; | |
273 Output(bytecode, operands, operand_scale); | |
274 } | |
275 | |
276 void BytecodeArrayBuilder::OutputScaled(Bytecode bytecode, int operand_scale, | |
277 uint32_t operand0) { | |
278 uint32_t operands[] = {operand0}; | |
279 Output(bytecode, operands, operand_scale); | |
280 } | |
281 | |
228 BytecodeArrayBuilder& BytecodeArrayBuilder::BinaryOperation(Token::Value op, | 282 BytecodeArrayBuilder& BytecodeArrayBuilder::BinaryOperation(Token::Value op, |
229 Register reg) { | 283 Register reg) { |
230 Output(BytecodeForBinaryOperation(op), reg.ToRawOperand()); | 284 int operand_scale = OperandScale(SizeForRegisterOperand(reg)); |
285 OutputScaled(BytecodeForBinaryOperation(op), operand_scale, | |
286 RegisterOperand(reg)); | |
231 return *this; | 287 return *this; |
232 } | 288 } |
233 | 289 |
234 BytecodeArrayBuilder& BytecodeArrayBuilder::CountOperation(Token::Value op) { | 290 BytecodeArrayBuilder& BytecodeArrayBuilder::CountOperation(Token::Value op) { |
235 Output(BytecodeForCountOperation(op)); | 291 Output(BytecodeForCountOperation(op)); |
236 return *this; | 292 return *this; |
237 } | 293 } |
238 | 294 |
239 | 295 |
240 BytecodeArrayBuilder& BytecodeArrayBuilder::LogicalNot() { | 296 BytecodeArrayBuilder& BytecodeArrayBuilder::LogicalNot() { |
241 Output(Bytecode::kLogicalNot); | 297 Output(Bytecode::kLogicalNot); |
242 return *this; | 298 return *this; |
243 } | 299 } |
244 | 300 |
245 | 301 |
246 BytecodeArrayBuilder& BytecodeArrayBuilder::TypeOf() { | 302 BytecodeArrayBuilder& BytecodeArrayBuilder::TypeOf() { |
247 Output(Bytecode::kTypeOf); | 303 Output(Bytecode::kTypeOf); |
248 return *this; | 304 return *this; |
249 } | 305 } |
250 | 306 |
251 BytecodeArrayBuilder& BytecodeArrayBuilder::CompareOperation(Token::Value op, | 307 BytecodeArrayBuilder& BytecodeArrayBuilder::CompareOperation(Token::Value op, |
252 Register reg) { | 308 Register reg) { |
253 Output(BytecodeForCompareOperation(op), reg.ToRawOperand()); | 309 int operand_scale = OperandScale(SizeForRegisterOperand(reg)); |
310 OutputScaled(BytecodeForCompareOperation(op), operand_scale, | |
311 RegisterOperand(reg)); | |
254 return *this; | 312 return *this; |
255 } | 313 } |
256 | 314 |
257 | 315 |
258 BytecodeArrayBuilder& BytecodeArrayBuilder::LoadLiteral( | 316 BytecodeArrayBuilder& BytecodeArrayBuilder::LoadLiteral( |
259 v8::internal::Smi* smi) { | 317 v8::internal::Smi* smi) { |
260 int32_t raw_smi = smi->value(); | 318 int32_t raw_smi = smi->value(); |
261 if (raw_smi == 0) { | 319 if (raw_smi == 0) { |
262 Output(Bytecode::kLdaZero); | 320 Output(Bytecode::kLdaZero); |
263 } else if (raw_smi >= -128 && raw_smi <= 127) { | |
264 Output(Bytecode::kLdaSmi8, static_cast<uint8_t>(raw_smi)); | |
265 } else { | 321 } else { |
266 LoadLiteral(Handle<Object>(smi, isolate_)); | 322 OperandSize operand_size = SizeForSignedOperand(raw_smi); |
323 int operand_scale = OperandScale(operand_size); | |
324 OutputScaled(Bytecode::kLdaSmi, operand_scale, | |
325 SignedOperand(raw_smi, operand_size)); | |
267 } | 326 } |
268 return *this; | 327 return *this; |
269 } | 328 } |
270 | 329 |
271 | 330 |
272 BytecodeArrayBuilder& BytecodeArrayBuilder::LoadLiteral(Handle<Object> object) { | 331 BytecodeArrayBuilder& BytecodeArrayBuilder::LoadLiteral(Handle<Object> object) { |
273 size_t entry = GetConstantPoolEntry(object); | 332 size_t entry = GetConstantPoolEntry(object); |
274 if (FitsInIdx8Operand(entry)) { | 333 int operand_scale = OperandScale(SizeForUnsignedOperand(entry)); |
275 Output(Bytecode::kLdaConstant, static_cast<uint8_t>(entry)); | 334 OutputScaled(Bytecode::kLdaConstant, operand_scale, UnsignedOperand(entry)); |
276 } else if (FitsInIdx16Operand(entry)) { | |
277 Output(Bytecode::kLdaConstantWide, static_cast<uint16_t>(entry)); | |
278 } else { | |
279 UNIMPLEMENTED(); | |
280 } | |
281 return *this; | 335 return *this; |
282 } | 336 } |
283 | 337 |
284 | 338 |
285 BytecodeArrayBuilder& BytecodeArrayBuilder::LoadUndefined() { | 339 BytecodeArrayBuilder& BytecodeArrayBuilder::LoadUndefined() { |
286 Output(Bytecode::kLdaUndefined); | 340 Output(Bytecode::kLdaUndefined); |
287 return *this; | 341 return *this; |
288 } | 342 } |
289 | 343 |
290 | 344 |
(...skipping 26 matching lines...) Expand all Loading... | |
317 LoadTrue(); | 371 LoadTrue(); |
318 } else { | 372 } else { |
319 LoadFalse(); | 373 LoadFalse(); |
320 } | 374 } |
321 return *this; | 375 return *this; |
322 } | 376 } |
323 | 377 |
324 BytecodeArrayBuilder& BytecodeArrayBuilder::LoadAccumulatorWithRegister( | 378 BytecodeArrayBuilder& BytecodeArrayBuilder::LoadAccumulatorWithRegister( |
325 Register reg) { | 379 Register reg) { |
326 if (!IsRegisterInAccumulator(reg)) { | 380 if (!IsRegisterInAccumulator(reg)) { |
327 Output(Bytecode::kLdar, reg.ToRawOperand()); | 381 int operand_scale = OperandScale(SizeForRegisterOperand(reg)); |
382 OutputScaled(Bytecode::kLdar, operand_scale, RegisterOperand(reg)); | |
328 } | 383 } |
329 return *this; | 384 return *this; |
330 } | 385 } |
331 | 386 |
332 | 387 |
333 BytecodeArrayBuilder& BytecodeArrayBuilder::StoreAccumulatorInRegister( | 388 BytecodeArrayBuilder& BytecodeArrayBuilder::StoreAccumulatorInRegister( |
334 Register reg) { | 389 Register reg) { |
335 if (!IsRegisterInAccumulator(reg)) { | 390 if (!IsRegisterInAccumulator(reg)) { |
336 Output(Bytecode::kStar, reg.ToRawOperand()); | 391 int operand_scale = OperandScale(SizeForRegisterOperand(reg)); |
392 OutputScaled(Bytecode::kStar, operand_scale, RegisterOperand(reg)); | |
337 } | 393 } |
338 return *this; | 394 return *this; |
339 } | 395 } |
340 | 396 |
341 | 397 |
342 BytecodeArrayBuilder& BytecodeArrayBuilder::MoveRegister(Register from, | 398 BytecodeArrayBuilder& BytecodeArrayBuilder::MoveRegister(Register from, |
343 Register to) { | 399 Register to) { |
344 DCHECK(from != to); | 400 DCHECK(from != to); |
345 if (FitsInReg8Operand(from) && FitsInReg8Operand(to)) { | 401 int operand_scale = |
346 Output(Bytecode::kMov, from.ToRawOperand(), to.ToRawOperand()); | 402 OperandScale(SizeForRegisterOperand(from), SizeForRegisterOperand(to)); |
347 } else if (FitsInReg16Operand(from) && FitsInReg16Operand(to)) { | 403 OutputScaled(Bytecode::kMov, operand_scale, RegisterOperand(from), |
348 Output(Bytecode::kMovWide, from.ToRawOperand(), to.ToRawOperand()); | 404 RegisterOperand(to)); |
349 } else { | |
350 UNIMPLEMENTED(); | |
351 } | |
352 return *this; | 405 return *this; |
353 } | 406 } |
354 | 407 |
355 void BytecodeArrayBuilder::MoveRegisterUntranslated(Register from, | |
356 Register to) { | |
357 // Move bytecodes modify the stack. Checking validity is an | |
358 // essential mitigation against corrupting the stack. | |
359 if (FitsInReg8OperandUntranslated(from)) { | |
360 CHECK(RegisterIsValid(from, OperandType::kReg8) && | |
361 RegisterIsValid(to, OperandType::kReg16)); | |
362 } else if (FitsInReg8OperandUntranslated(to)) { | |
363 CHECK(RegisterIsValid(from, OperandType::kReg16) && | |
364 RegisterIsValid(to, OperandType::kReg8)); | |
365 } else { | |
366 UNIMPLEMENTED(); | |
367 } | |
368 Output(Bytecode::kMovWide, from.ToRawOperand(), to.ToRawOperand()); | |
369 } | |
370 | |
371 BytecodeArrayBuilder& BytecodeArrayBuilder::LoadGlobal( | 408 BytecodeArrayBuilder& BytecodeArrayBuilder::LoadGlobal( |
372 const Handle<String> name, int feedback_slot, TypeofMode typeof_mode) { | 409 const Handle<String> name, int feedback_slot, TypeofMode typeof_mode) { |
373 // TODO(rmcilroy): Potentially store typeof information in an | 410 // TODO(rmcilroy): Potentially store typeof information in an |
374 // operand rather than having extra bytecodes. | 411 // operand rather than having extra bytecodes. |
375 Bytecode bytecode = BytecodeForLoadGlobal(typeof_mode); | 412 Bytecode bytecode = BytecodeForLoadGlobal(typeof_mode); |
376 size_t name_index = GetConstantPoolEntry(name); | 413 size_t name_index = GetConstantPoolEntry(name); |
377 if (FitsInIdx8Operand(name_index) && FitsInIdx8Operand(feedback_slot)) { | 414 int operand_scale = OperandScale(SizeForUnsignedOperand(name_index), |
378 Output(bytecode, static_cast<uint8_t>(name_index), | 415 SizeForUnsignedOperand(feedback_slot)); |
379 static_cast<uint8_t>(feedback_slot)); | 416 OutputScaled(bytecode, operand_scale, UnsignedOperand(name_index), |
380 } else if (FitsInIdx16Operand(name_index) && | 417 UnsignedOperand(feedback_slot)); |
381 FitsInIdx16Operand(feedback_slot)) { | |
382 Output(BytecodeForWideOperands(bytecode), static_cast<uint16_t>(name_index), | |
383 static_cast<uint16_t>(feedback_slot)); | |
384 } else { | |
385 UNIMPLEMENTED(); | |
386 } | |
387 return *this; | 418 return *this; |
388 } | 419 } |
389 | 420 |
390 | |
391 BytecodeArrayBuilder& BytecodeArrayBuilder::StoreGlobal( | 421 BytecodeArrayBuilder& BytecodeArrayBuilder::StoreGlobal( |
392 const Handle<String> name, int feedback_slot, LanguageMode language_mode) { | 422 const Handle<String> name, int feedback_slot, LanguageMode language_mode) { |
393 Bytecode bytecode = BytecodeForStoreGlobal(language_mode); | 423 Bytecode bytecode = BytecodeForStoreGlobal(language_mode); |
394 size_t name_index = GetConstantPoolEntry(name); | 424 size_t name_index = GetConstantPoolEntry(name); |
395 if (FitsInIdx8Operand(name_index) && FitsInIdx8Operand(feedback_slot)) { | 425 int operand_scale = OperandScale(SizeForUnsignedOperand(name_index), |
396 Output(bytecode, static_cast<uint8_t>(name_index), | 426 SizeForUnsignedOperand(feedback_slot)); |
397 static_cast<uint8_t>(feedback_slot)); | 427 OutputScaled(bytecode, operand_scale, UnsignedOperand(name_index), |
398 } else if (FitsInIdx16Operand(name_index) && | 428 UnsignedOperand(feedback_slot)); |
399 FitsInIdx16Operand(feedback_slot)) { | |
400 Output(BytecodeForWideOperands(bytecode), static_cast<uint16_t>(name_index), | |
401 static_cast<uint16_t>(feedback_slot)); | |
402 } else { | |
403 UNIMPLEMENTED(); | |
404 } | |
405 return *this; | 429 return *this; |
406 } | 430 } |
407 | 431 |
408 | 432 |
409 BytecodeArrayBuilder& BytecodeArrayBuilder::LoadContextSlot(Register context, | 433 BytecodeArrayBuilder& BytecodeArrayBuilder::LoadContextSlot(Register context, |
410 int slot_index) { | 434 int slot_index) { |
411 DCHECK(slot_index >= 0); | 435 int operand_scale = OperandScale(SizeForRegisterOperand(context), |
412 if (FitsInIdx8Operand(slot_index)) { | 436 SizeForUnsignedOperand(slot_index)); |
413 Output(Bytecode::kLdaContextSlot, context.ToRawOperand(), | 437 OutputScaled(Bytecode::kLdaContextSlot, operand_scale, |
414 static_cast<uint8_t>(slot_index)); | 438 RegisterOperand(context), UnsignedOperand(slot_index)); |
415 } else if (FitsInIdx16Operand(slot_index)) { | |
416 Output(Bytecode::kLdaContextSlotWide, context.ToRawOperand(), | |
417 static_cast<uint16_t>(slot_index)); | |
418 } else { | |
419 UNIMPLEMENTED(); | |
420 } | |
421 return *this; | 439 return *this; |
422 } | 440 } |
423 | 441 |
424 | 442 |
425 BytecodeArrayBuilder& BytecodeArrayBuilder::StoreContextSlot(Register context, | 443 BytecodeArrayBuilder& BytecodeArrayBuilder::StoreContextSlot(Register context, |
426 int slot_index) { | 444 int slot_index) { |
427 DCHECK(slot_index >= 0); | 445 int operand_scale = OperandScale(SizeForRegisterOperand(context), |
428 if (FitsInIdx8Operand(slot_index)) { | 446 SizeForUnsignedOperand(slot_index)); |
429 Output(Bytecode::kStaContextSlot, context.ToRawOperand(), | 447 OutputScaled(Bytecode::kStaContextSlot, operand_scale, |
430 static_cast<uint8_t>(slot_index)); | 448 RegisterOperand(context), UnsignedOperand(slot_index)); |
431 } else if (FitsInIdx16Operand(slot_index)) { | |
432 Output(Bytecode::kStaContextSlotWide, context.ToRawOperand(), | |
433 static_cast<uint16_t>(slot_index)); | |
434 } else { | |
435 UNIMPLEMENTED(); | |
436 } | |
437 return *this; | 449 return *this; |
438 } | 450 } |
439 | 451 |
440 | |
441 BytecodeArrayBuilder& BytecodeArrayBuilder::LoadLookupSlot( | 452 BytecodeArrayBuilder& BytecodeArrayBuilder::LoadLookupSlot( |
442 const Handle<String> name, TypeofMode typeof_mode) { | 453 const Handle<String> name, TypeofMode typeof_mode) { |
443 Bytecode bytecode = (typeof_mode == INSIDE_TYPEOF) | 454 Bytecode bytecode = (typeof_mode == INSIDE_TYPEOF) |
444 ? Bytecode::kLdaLookupSlotInsideTypeof | 455 ? Bytecode::kLdaLookupSlotInsideTypeof |
445 : Bytecode::kLdaLookupSlot; | 456 : Bytecode::kLdaLookupSlot; |
446 size_t name_index = GetConstantPoolEntry(name); | 457 size_t name_index = GetConstantPoolEntry(name); |
447 if (FitsInIdx8Operand(name_index)) { | 458 int operand_scale = OperandScale(SizeForUnsignedOperand(name_index)); |
448 Output(bytecode, static_cast<uint8_t>(name_index)); | 459 OutputScaled(bytecode, operand_scale, UnsignedOperand(name_index)); |
449 } else if (FitsInIdx16Operand(name_index)) { | |
450 Output(BytecodeForWideOperands(bytecode), | |
451 static_cast<uint16_t>(name_index)); | |
452 } else { | |
453 UNIMPLEMENTED(); | |
454 } | |
455 return *this; | 460 return *this; |
456 } | 461 } |
457 | 462 |
458 | |
459 BytecodeArrayBuilder& BytecodeArrayBuilder::StoreLookupSlot( | 463 BytecodeArrayBuilder& BytecodeArrayBuilder::StoreLookupSlot( |
460 const Handle<String> name, LanguageMode language_mode) { | 464 const Handle<String> name, LanguageMode language_mode) { |
461 Bytecode bytecode = BytecodeForStoreLookupSlot(language_mode); | 465 Bytecode bytecode = BytecodeForStoreLookupSlot(language_mode); |
462 size_t name_index = GetConstantPoolEntry(name); | 466 size_t name_index = GetConstantPoolEntry(name); |
463 if (FitsInIdx8Operand(name_index)) { | 467 int operand_scale = OperandScale(SizeForUnsignedOperand(name_index)); |
464 Output(bytecode, static_cast<uint8_t>(name_index)); | 468 OutputScaled(bytecode, operand_scale, UnsignedOperand(name_index)); |
465 } else if (FitsInIdx16Operand(name_index)) { | |
466 Output(BytecodeForWideOperands(bytecode), | |
467 static_cast<uint16_t>(name_index)); | |
468 } else { | |
469 UNIMPLEMENTED(); | |
470 } | |
471 return *this; | 469 return *this; |
472 } | 470 } |
473 | 471 |
474 BytecodeArrayBuilder& BytecodeArrayBuilder::LoadNamedProperty( | 472 BytecodeArrayBuilder& BytecodeArrayBuilder::LoadNamedProperty( |
475 Register object, const Handle<Name> name, int feedback_slot) { | 473 Register object, const Handle<Name> name, int feedback_slot) { |
476 size_t name_index = GetConstantPoolEntry(name); | 474 size_t name_index = GetConstantPoolEntry(name); |
477 if (FitsInIdx8Operand(name_index) && FitsInIdx8Operand(feedback_slot)) { | 475 int operand_scale = OperandScale(SizeForRegisterOperand(object), |
478 Output(Bytecode::kLoadIC, object.ToRawOperand(), | 476 SizeForUnsignedOperand(name_index), |
479 static_cast<uint8_t>(name_index), | 477 SizeForUnsignedOperand(feedback_slot)); |
480 static_cast<uint8_t>(feedback_slot)); | 478 OutputScaled(Bytecode::kLoadIC, operand_scale, RegisterOperand(object), |
481 } else if (FitsInIdx16Operand(name_index) && | 479 UnsignedOperand(name_index), UnsignedOperand(feedback_slot)); |
482 FitsInIdx16Operand(feedback_slot)) { | |
483 Output(Bytecode::kLoadICWide, object.ToRawOperand(), | |
484 static_cast<uint16_t>(name_index), | |
485 static_cast<uint16_t>(feedback_slot)); | |
486 } else { | |
487 UNIMPLEMENTED(); | |
488 } | |
489 return *this; | 480 return *this; |
490 } | 481 } |
491 | 482 |
492 BytecodeArrayBuilder& BytecodeArrayBuilder::LoadKeyedProperty( | 483 BytecodeArrayBuilder& BytecodeArrayBuilder::LoadKeyedProperty( |
493 Register object, int feedback_slot) { | 484 Register object, int feedback_slot) { |
494 if (FitsInIdx8Operand(feedback_slot)) { | 485 int operand_scale = OperandScale(SizeForRegisterOperand(object), |
495 Output(Bytecode::kKeyedLoadIC, object.ToRawOperand(), | 486 SizeForUnsignedOperand(feedback_slot)); |
496 static_cast<uint8_t>(feedback_slot)); | 487 OutputScaled(Bytecode::kKeyedLoadIC, operand_scale, RegisterOperand(object), |
497 } else if (FitsInIdx16Operand(feedback_slot)) { | 488 UnsignedOperand(feedback_slot)); |
498 Output(Bytecode::kKeyedLoadICWide, object.ToRawOperand(), | |
499 static_cast<uint16_t>(feedback_slot)); | |
500 } else { | |
501 UNIMPLEMENTED(); | |
502 } | |
503 return *this; | 489 return *this; |
504 } | 490 } |
505 | 491 |
506 BytecodeArrayBuilder& BytecodeArrayBuilder::StoreNamedProperty( | 492 BytecodeArrayBuilder& BytecodeArrayBuilder::StoreNamedProperty( |
507 Register object, const Handle<Name> name, int feedback_slot, | 493 Register object, const Handle<Name> name, int feedback_slot, |
508 LanguageMode language_mode) { | 494 LanguageMode language_mode) { |
509 Bytecode bytecode = BytecodeForStoreIC(language_mode); | 495 Bytecode bytecode = BytecodeForStoreIC(language_mode); |
510 size_t name_index = GetConstantPoolEntry(name); | 496 size_t name_index = GetConstantPoolEntry(name); |
511 if (FitsInIdx8Operand(name_index) && FitsInIdx8Operand(feedback_slot)) { | 497 int operand_scale = OperandScale(SizeForRegisterOperand(object), |
512 Output(bytecode, object.ToRawOperand(), static_cast<uint8_t>(name_index), | 498 SizeForUnsignedOperand(name_index), |
513 static_cast<uint8_t>(feedback_slot)); | 499 SizeForUnsignedOperand(feedback_slot)); |
514 } else if (FitsInIdx16Operand(name_index) && | 500 OutputScaled(bytecode, operand_scale, RegisterOperand(object), |
515 FitsInIdx16Operand(feedback_slot)) { | 501 UnsignedOperand(name_index), UnsignedOperand(feedback_slot)); |
516 Output(BytecodeForWideOperands(bytecode), object.ToRawOperand(), | |
517 static_cast<uint16_t>(name_index), | |
518 static_cast<uint16_t>(feedback_slot)); | |
519 } else { | |
520 UNIMPLEMENTED(); | |
521 } | |
522 return *this; | 502 return *this; |
523 } | 503 } |
524 | 504 |
525 | 505 |
526 BytecodeArrayBuilder& BytecodeArrayBuilder::StoreKeyedProperty( | 506 BytecodeArrayBuilder& BytecodeArrayBuilder::StoreKeyedProperty( |
527 Register object, Register key, int feedback_slot, | 507 Register object, Register key, int feedback_slot, |
528 LanguageMode language_mode) { | 508 LanguageMode language_mode) { |
529 Bytecode bytecode = BytecodeForKeyedStoreIC(language_mode); | 509 Bytecode bytecode = BytecodeForKeyedStoreIC(language_mode); |
530 if (FitsInIdx8Operand(feedback_slot)) { | 510 int operand_scale = |
531 Output(bytecode, object.ToRawOperand(), key.ToRawOperand(), | 511 OperandScale(SizeForRegisterOperand(object), SizeForRegisterOperand(key), |
532 static_cast<uint8_t>(feedback_slot)); | 512 SizeForUnsignedOperand(feedback_slot)); |
533 } else if (FitsInIdx16Operand(feedback_slot)) { | 513 OutputScaled(bytecode, operand_scale, RegisterOperand(object), |
534 Output(BytecodeForWideOperands(bytecode), object.ToRawOperand(), | 514 RegisterOperand(key), UnsignedOperand(feedback_slot)); |
535 key.ToRawOperand(), static_cast<uint16_t>(feedback_slot)); | |
536 } else { | |
537 UNIMPLEMENTED(); | |
538 } | |
539 return *this; | 515 return *this; |
540 } | 516 } |
541 | 517 |
542 | 518 |
543 BytecodeArrayBuilder& BytecodeArrayBuilder::CreateClosure( | 519 BytecodeArrayBuilder& BytecodeArrayBuilder::CreateClosure( |
544 Handle<SharedFunctionInfo> shared_info, PretenureFlag tenured) { | 520 Handle<SharedFunctionInfo> shared_info, PretenureFlag tenured) { |
545 size_t entry = GetConstantPoolEntry(shared_info); | 521 size_t entry = GetConstantPoolEntry(shared_info); |
546 DCHECK(FitsInImm8Operand(tenured)); | 522 int operand_scale = OperandScale(SizeForUnsignedOperand(entry)); |
547 if (FitsInIdx8Operand(entry)) { | 523 OutputScaled(Bytecode::kCreateClosure, operand_scale, UnsignedOperand(entry), |
548 Output(Bytecode::kCreateClosure, static_cast<uint8_t>(entry), | 524 UnsignedOperand(static_cast<size_t>(tenured))); |
549 static_cast<uint8_t>(tenured)); | |
550 } else if (FitsInIdx16Operand(entry)) { | |
551 Output(Bytecode::kCreateClosureWide, static_cast<uint16_t>(entry), | |
552 static_cast<uint8_t>(tenured)); | |
553 } else { | |
554 UNIMPLEMENTED(); | |
555 } | |
556 return *this; | 525 return *this; |
557 } | 526 } |
558 | 527 |
559 | 528 |
560 BytecodeArrayBuilder& BytecodeArrayBuilder::CreateArguments( | 529 BytecodeArrayBuilder& BytecodeArrayBuilder::CreateArguments( |
561 CreateArgumentsType type) { | 530 CreateArgumentsType type) { |
562 // TODO(rmcilroy): Consider passing the type as a bytecode operand rather | 531 // TODO(rmcilroy): Consider passing the type as a bytecode operand rather |
563 // than having two different bytecodes once we have better support for | 532 // than having two different bytecodes once we have better support for |
564 // branches in the InterpreterAssembler. | 533 // branches in the InterpreterAssembler. |
565 Bytecode bytecode = BytecodeForCreateArguments(type); | 534 Bytecode bytecode = BytecodeForCreateArguments(type); |
566 Output(bytecode); | 535 Output(bytecode); |
567 return *this; | 536 return *this; |
568 } | 537 } |
569 | 538 |
570 | 539 |
571 BytecodeArrayBuilder& BytecodeArrayBuilder::CreateRegExpLiteral( | 540 BytecodeArrayBuilder& BytecodeArrayBuilder::CreateRegExpLiteral( |
572 Handle<String> pattern, int literal_index, int flags) { | 541 Handle<String> pattern, int literal_index, int flags) { |
573 DCHECK(FitsInImm8Operand(flags)); // Flags should fit in 8 bits. | |
574 size_t pattern_entry = GetConstantPoolEntry(pattern); | 542 size_t pattern_entry = GetConstantPoolEntry(pattern); |
575 if (FitsInIdx8Operand(literal_index) && FitsInIdx8Operand(pattern_entry)) { | 543 int operand_scale = OperandScale(SizeForUnsignedOperand(pattern_entry), |
576 Output(Bytecode::kCreateRegExpLiteral, static_cast<uint8_t>(pattern_entry), | 544 SizeForUnsignedOperand(literal_index), |
577 static_cast<uint8_t>(literal_index), static_cast<uint8_t>(flags)); | 545 SizeForUnsignedOperand(flags)); |
578 } else if (FitsInIdx16Operand(literal_index) && | 546 OutputScaled(Bytecode::kCreateRegExpLiteral, operand_scale, |
579 FitsInIdx16Operand(pattern_entry)) { | 547 UnsignedOperand(pattern_entry), UnsignedOperand(literal_index), |
580 Output(Bytecode::kCreateRegExpLiteralWide, | 548 UnsignedOperand(flags)); |
581 static_cast<uint16_t>(pattern_entry), | |
582 static_cast<uint16_t>(literal_index), static_cast<uint8_t>(flags)); | |
583 } else { | |
584 UNIMPLEMENTED(); | |
585 } | |
586 return *this; | 549 return *this; |
587 } | 550 } |
588 | 551 |
589 | 552 |
590 BytecodeArrayBuilder& BytecodeArrayBuilder::CreateArrayLiteral( | 553 BytecodeArrayBuilder& BytecodeArrayBuilder::CreateArrayLiteral( |
591 Handle<FixedArray> constant_elements, int literal_index, int flags) { | 554 Handle<FixedArray> constant_elements, int literal_index, int flags) { |
592 DCHECK(FitsInImm8Operand(flags)); // Flags should fit in 8 bits. | |
593 size_t constant_elements_entry = GetConstantPoolEntry(constant_elements); | 555 size_t constant_elements_entry = GetConstantPoolEntry(constant_elements); |
594 if (FitsInIdx8Operand(literal_index) && | 556 int operand_scale = OperandScale( |
595 FitsInIdx8Operand(constant_elements_entry)) { | 557 SizeForUnsignedOperand(constant_elements_entry), |
596 Output(Bytecode::kCreateArrayLiteral, | 558 SizeForUnsignedOperand(literal_index), SizeForUnsignedOperand(flags)); |
597 static_cast<uint8_t>(constant_elements_entry), | 559 OutputScaled(Bytecode::kCreateArrayLiteral, operand_scale, |
598 static_cast<uint8_t>(literal_index), static_cast<uint8_t>(flags)); | 560 UnsignedOperand(constant_elements_entry), |
599 } else if (FitsInIdx16Operand(literal_index) && | 561 UnsignedOperand(literal_index), UnsignedOperand(flags)); |
600 FitsInIdx16Operand(constant_elements_entry)) { | |
601 Output(Bytecode::kCreateArrayLiteralWide, | |
602 static_cast<uint16_t>(constant_elements_entry), | |
603 static_cast<uint16_t>(literal_index), static_cast<uint8_t>(flags)); | |
604 } else { | |
605 UNIMPLEMENTED(); | |
606 } | |
607 return *this; | 562 return *this; |
608 } | 563 } |
609 | 564 |
610 | 565 |
611 BytecodeArrayBuilder& BytecodeArrayBuilder::CreateObjectLiteral( | 566 BytecodeArrayBuilder& BytecodeArrayBuilder::CreateObjectLiteral( |
612 Handle<FixedArray> constant_properties, int literal_index, int flags) { | 567 Handle<FixedArray> constant_properties, int literal_index, int flags) { |
613 DCHECK(FitsInImm8Operand(flags)); // Flags should fit in 8 bits. | |
614 size_t constant_properties_entry = GetConstantPoolEntry(constant_properties); | 568 size_t constant_properties_entry = GetConstantPoolEntry(constant_properties); |
615 if (FitsInIdx8Operand(literal_index) && | 569 int operand_scale = OperandScale( |
616 FitsInIdx8Operand(constant_properties_entry)) { | 570 SizeForUnsignedOperand(constant_properties_entry), |
617 Output(Bytecode::kCreateObjectLiteral, | 571 SizeForUnsignedOperand(literal_index), SizeForUnsignedOperand(flags)); |
618 static_cast<uint8_t>(constant_properties_entry), | 572 OutputScaled(Bytecode::kCreateObjectLiteral, operand_scale, |
619 static_cast<uint8_t>(literal_index), static_cast<uint8_t>(flags)); | 573 UnsignedOperand(constant_properties_entry), |
620 } else if (FitsInIdx16Operand(literal_index) && | 574 UnsignedOperand(literal_index), UnsignedOperand(flags)); |
621 FitsInIdx16Operand(constant_properties_entry)) { | |
622 Output(Bytecode::kCreateObjectLiteralWide, | |
623 static_cast<uint16_t>(constant_properties_entry), | |
624 static_cast<uint16_t>(literal_index), static_cast<uint8_t>(flags)); | |
625 } else { | |
626 UNIMPLEMENTED(); | |
627 } | |
628 return *this; | 575 return *this; |
629 } | 576 } |
630 | 577 |
631 | 578 |
632 BytecodeArrayBuilder& BytecodeArrayBuilder::PushContext(Register context) { | 579 BytecodeArrayBuilder& BytecodeArrayBuilder::PushContext(Register context) { |
633 Output(Bytecode::kPushContext, context.ToRawOperand()); | 580 int operand_scale = OperandScale(SizeForRegisterOperand(context)); |
581 OutputScaled(Bytecode::kPushContext, operand_scale, RegisterOperand(context)); | |
634 return *this; | 582 return *this; |
635 } | 583 } |
636 | 584 |
637 | 585 |
638 BytecodeArrayBuilder& BytecodeArrayBuilder::PopContext(Register context) { | 586 BytecodeArrayBuilder& BytecodeArrayBuilder::PopContext(Register context) { |
639 Output(Bytecode::kPopContext, context.ToRawOperand()); | 587 int operand_scale = OperandScale(SizeForRegisterOperand(context)); |
588 OutputScaled(Bytecode::kPopContext, operand_scale, RegisterOperand(context)); | |
640 return *this; | 589 return *this; |
641 } | 590 } |
642 | 591 |
643 | 592 |
644 bool BytecodeArrayBuilder::NeedToBooleanCast() { | 593 bool BytecodeArrayBuilder::NeedToBooleanCast() { |
645 if (!LastBytecodeInSameBlock()) { | 594 if (!LastBytecodeInSameBlock()) { |
646 return true; | 595 return true; |
647 } | 596 } |
648 PreviousBytecodeHelper previous_bytecode(*this); | 597 PreviousBytecodeHelper previous_bytecode(*this); |
649 switch (previous_bytecode.GetBytecode()) { | 598 switch (previous_bytecode.GetBytecode()) { |
(...skipping 24 matching lines...) Expand all Loading... | |
674 } | 623 } |
675 | 624 |
676 | 625 |
677 BytecodeArrayBuilder& BytecodeArrayBuilder::CastAccumulatorToName() { | 626 BytecodeArrayBuilder& BytecodeArrayBuilder::CastAccumulatorToName() { |
678 if (LastBytecodeInSameBlock()) { | 627 if (LastBytecodeInSameBlock()) { |
679 PreviousBytecodeHelper previous_bytecode(*this); | 628 PreviousBytecodeHelper previous_bytecode(*this); |
680 switch (previous_bytecode.GetBytecode()) { | 629 switch (previous_bytecode.GetBytecode()) { |
681 case Bytecode::kToName: | 630 case Bytecode::kToName: |
682 case Bytecode::kTypeOf: | 631 case Bytecode::kTypeOf: |
683 return *this; | 632 return *this; |
684 case Bytecode::kLdaConstantWide: | |
685 case Bytecode::kLdaConstant: { | 633 case Bytecode::kLdaConstant: { |
686 Handle<Object> object = previous_bytecode.GetConstantForIndexOperand(0); | 634 Handle<Object> object = previous_bytecode.GetConstantForIndexOperand(0); |
687 if (object->IsName()) return *this; | 635 if (object->IsName()) return *this; |
688 break; | 636 break; |
689 } | 637 } |
690 default: | 638 default: |
691 break; | 639 break; |
692 } | 640 } |
693 } | 641 } |
694 Output(Bytecode::kToName); | 642 Output(Bytecode::kToName); |
(...skipping 52 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
747 case Bytecode::kJumpIfToBooleanFalse: | 695 case Bytecode::kJumpIfToBooleanFalse: |
748 return Bytecode::kJumpIfToBooleanFalseConstant; | 696 return Bytecode::kJumpIfToBooleanFalseConstant; |
749 case Bytecode::kJumpIfNotHole: | 697 case Bytecode::kJumpIfNotHole: |
750 return Bytecode::kJumpIfNotHoleConstant; | 698 return Bytecode::kJumpIfNotHoleConstant; |
751 case Bytecode::kJumpIfNull: | 699 case Bytecode::kJumpIfNull: |
752 return Bytecode::kJumpIfNullConstant; | 700 return Bytecode::kJumpIfNullConstant; |
753 case Bytecode::kJumpIfUndefined: | 701 case Bytecode::kJumpIfUndefined: |
754 return Bytecode::kJumpIfUndefinedConstant; | 702 return Bytecode::kJumpIfUndefinedConstant; |
755 default: | 703 default: |
756 UNREACHABLE(); | 704 UNREACHABLE(); |
757 return static_cast<Bytecode>(-1); | 705 return Bytecode::kIllegal; |
758 } | 706 } |
759 } | 707 } |
760 | 708 |
761 | |
762 // static | |
763 Bytecode BytecodeArrayBuilder::GetJumpWithConstantWideOperand( | |
764 Bytecode jump_bytecode) { | |
765 switch (jump_bytecode) { | |
766 case Bytecode::kJump: | |
767 return Bytecode::kJumpConstantWide; | |
768 case Bytecode::kJumpIfTrue: | |
769 return Bytecode::kJumpIfTrueConstantWide; | |
770 case Bytecode::kJumpIfFalse: | |
771 return Bytecode::kJumpIfFalseConstantWide; | |
772 case Bytecode::kJumpIfToBooleanTrue: | |
773 return Bytecode::kJumpIfToBooleanTrueConstantWide; | |
774 case Bytecode::kJumpIfToBooleanFalse: | |
775 return Bytecode::kJumpIfToBooleanFalseConstantWide; | |
776 case Bytecode::kJumpIfNotHole: | |
777 return Bytecode::kJumpIfNotHoleConstantWide; | |
778 case Bytecode::kJumpIfNull: | |
779 return Bytecode::kJumpIfNullConstantWide; | |
780 case Bytecode::kJumpIfUndefined: | |
781 return Bytecode::kJumpIfUndefinedConstantWide; | |
782 default: | |
783 UNREACHABLE(); | |
784 return static_cast<Bytecode>(-1); | |
785 } | |
786 } | |
787 | |
788 | |
789 // static | 709 // static |
790 Bytecode BytecodeArrayBuilder::GetJumpWithToBoolean(Bytecode jump_bytecode) { | 710 Bytecode BytecodeArrayBuilder::GetJumpWithToBoolean(Bytecode jump_bytecode) { |
791 switch (jump_bytecode) { | 711 switch (jump_bytecode) { |
792 case Bytecode::kJump: | 712 case Bytecode::kJump: |
793 case Bytecode::kJumpIfNull: | 713 case Bytecode::kJumpIfNull: |
794 case Bytecode::kJumpIfUndefined: | 714 case Bytecode::kJumpIfUndefined: |
795 case Bytecode::kJumpIfNotHole: | 715 case Bytecode::kJumpIfNotHole: |
796 return jump_bytecode; | 716 return jump_bytecode; |
797 case Bytecode::kJumpIfTrue: | 717 case Bytecode::kJumpIfTrue: |
798 return Bytecode::kJumpIfToBooleanTrue; | 718 return Bytecode::kJumpIfToBooleanTrue; |
799 case Bytecode::kJumpIfFalse: | 719 case Bytecode::kJumpIfFalse: |
800 return Bytecode::kJumpIfToBooleanFalse; | 720 return Bytecode::kJumpIfToBooleanFalse; |
801 default: | 721 default: |
802 UNREACHABLE(); | 722 UNREACHABLE(); |
803 } | 723 } |
804 return static_cast<Bytecode>(-1); | 724 return Bytecode::kIllegal; |
805 } | 725 } |
806 | 726 |
807 | 727 |
808 void BytecodeArrayBuilder::PatchIndirectJumpWith8BitOperand( | 728 void BytecodeArrayBuilder::PatchIndirectJumpWith8BitOperand( |
809 const ZoneVector<uint8_t>::iterator& jump_location, int delta) { | 729 const ZoneVector<uint8_t>::iterator& jump_location, int delta) { |
810 Bytecode jump_bytecode = Bytecodes::FromByte(*jump_location); | 730 Bytecode jump_bytecode = Bytecodes::FromByte(*jump_location); |
811 DCHECK(Bytecodes::IsJumpImmediate(jump_bytecode)); | 731 DCHECK(Bytecodes::IsJumpImmediate(jump_bytecode)); |
812 ZoneVector<uint8_t>::iterator operand_location = jump_location + 1; | 732 ZoneVector<uint8_t>::iterator operand_location = jump_location + 1; |
813 DCHECK_EQ(*operand_location, 0); | 733 DCHECK_EQ(*operand_location, 0); |
814 if (FitsInImm8Operand(delta)) { | 734 if (SizeForSignedOperand(delta) == OperandSize::kByte) { |
815 // The jump fits within the range of an Imm8 operand, so cancel | 735 // The jump fits within the range of an Imm operand, so cancel |
816 // the reservation and jump directly. | 736 // the reservation and jump directly. |
817 constant_array_builder()->DiscardReservedEntry(OperandSize::kByte); | 737 constant_array_builder()->DiscardReservedEntry(OperandSize::kByte); |
818 *operand_location = static_cast<uint8_t>(delta); | 738 *operand_location = static_cast<uint8_t>(delta); |
819 } else { | 739 } else { |
820 // The jump does not fit within the range of an Imm8 operand, so | 740 // The jump does not fit within the range of an Imm operand, so |
821 // commit reservation putting the offset into the constant pool, | 741 // commit reservation putting the offset into the constant pool, |
822 // and update the jump instruction and operand. | 742 // and update the jump instruction and operand. |
823 size_t entry = constant_array_builder()->CommitReservedEntry( | 743 size_t entry = constant_array_builder()->CommitReservedEntry( |
824 OperandSize::kByte, handle(Smi::FromInt(delta), isolate())); | 744 OperandSize::kByte, handle(Smi::FromInt(delta), isolate())); |
825 DCHECK(FitsInIdx8Operand(entry)); | 745 DCHECK(SizeForUnsignedOperand(entry) == OperandSize::kByte); |
826 jump_bytecode = GetJumpWithConstantOperand(jump_bytecode); | 746 jump_bytecode = GetJumpWithConstantOperand(jump_bytecode); |
827 *jump_location = Bytecodes::ToByte(jump_bytecode); | 747 *jump_location = Bytecodes::ToByte(jump_bytecode); |
828 *operand_location = static_cast<uint8_t>(entry); | 748 *operand_location = static_cast<uint8_t>(entry); |
829 } | 749 } |
830 } | 750 } |
831 | 751 |
832 | |
833 void BytecodeArrayBuilder::PatchIndirectJumpWith16BitOperand( | 752 void BytecodeArrayBuilder::PatchIndirectJumpWith16BitOperand( |
834 const ZoneVector<uint8_t>::iterator& jump_location, int delta) { | 753 const ZoneVector<uint8_t>::iterator& jump_location, int delta) { |
835 DCHECK(Bytecodes::IsJumpConstantWide(Bytecodes::FromByte(*jump_location))); | 754 Bytecode jump_bytecode = Bytecodes::FromByte(*jump_location); |
755 DCHECK(Bytecodes::IsJumpImmediate(jump_bytecode)); | |
836 ZoneVector<uint8_t>::iterator operand_location = jump_location + 1; | 756 ZoneVector<uint8_t>::iterator operand_location = jump_location + 1; |
837 size_t entry = constant_array_builder()->CommitReservedEntry( | |
838 OperandSize::kShort, handle(Smi::FromInt(delta), isolate())); | |
839 DCHECK(FitsInIdx16Operand(entry)); | |
840 uint8_t operand_bytes[2]; | 757 uint8_t operand_bytes[2]; |
841 WriteUnalignedUInt16(operand_bytes, static_cast<uint16_t>(entry)); | 758 if (SizeForSignedOperand(delta) <= OperandSize::kShort) { |
759 constant_array_builder()->DiscardReservedEntry(OperandSize::kShort); | |
760 WriteUnalignedUInt16(operand_bytes, static_cast<uint16_t>(delta)); | |
761 } else { | |
762 jump_bytecode = GetJumpWithConstantOperand(jump_bytecode); | |
763 *jump_location = Bytecodes::ToByte(jump_bytecode); | |
764 size_t entry = constant_array_builder()->CommitReservedEntry( | |
765 OperandSize::kShort, handle(Smi::FromInt(delta), isolate())); | |
766 WriteUnalignedUInt16(operand_bytes, static_cast<uint16_t>(entry)); | |
767 } | |
842 DCHECK(*operand_location == 0 && *(operand_location + 1) == 0); | 768 DCHECK(*operand_location == 0 && *(operand_location + 1) == 0); |
843 *operand_location++ = operand_bytes[0]; | 769 *operand_location++ = operand_bytes[0]; |
844 *operand_location = operand_bytes[1]; | 770 *operand_location = operand_bytes[1]; |
845 } | 771 } |
846 | 772 |
773 void BytecodeArrayBuilder::PatchIndirectJumpWith32BitOperand( | |
774 const ZoneVector<uint8_t>::iterator& jump_location, int delta) { | |
775 DCHECK(Bytecodes::IsJumpImmediate(Bytecodes::FromByte(*jump_location))); | |
776 constant_array_builder()->DiscardReservedEntry(OperandSize::kQuad); | |
777 ZoneVector<uint8_t>::iterator operand_location = jump_location + 1; | |
778 uint8_t operand_bytes[4]; | |
779 WriteUnalignedUInt32(operand_bytes, static_cast<uint32_t>(delta)); | |
780 DCHECK(*operand_location == 0 && *(operand_location + 1) == 0 && | |
781 *(operand_location + 2) == 0 && *(operand_location + 3) == 0); | |
782 *operand_location++ = operand_bytes[0]; | |
783 *operand_location++ = operand_bytes[1]; | |
784 *operand_location++ = operand_bytes[2]; | |
785 *operand_location = operand_bytes[3]; | |
786 } | |
847 | 787 |
848 void BytecodeArrayBuilder::PatchJump( | 788 void BytecodeArrayBuilder::PatchJump( |
849 const ZoneVector<uint8_t>::iterator& jump_target, | 789 const ZoneVector<uint8_t>::iterator& jump_target, |
850 const ZoneVector<uint8_t>::iterator& jump_location) { | 790 const ZoneVector<uint8_t>::iterator& jump_location) { |
791 int delta = static_cast<int>(jump_target - jump_location); | |
851 Bytecode jump_bytecode = Bytecodes::FromByte(*jump_location); | 792 Bytecode jump_bytecode = Bytecodes::FromByte(*jump_location); |
852 int delta = static_cast<int>(jump_target - jump_location); | 793 int operand_scale = Bytecodes::GetPrefixBytecodeScale(jump_bytecode); |
794 int prefix_offset = 0; | |
795 if (operand_scale > 1) { | |
796 delta -= 1; | |
797 prefix_offset = 1; | |
798 jump_bytecode = Bytecodes::FromByte(*(jump_location + prefix_offset)); | |
799 } | |
800 | |
853 DCHECK(Bytecodes::IsJump(jump_bytecode)); | 801 DCHECK(Bytecodes::IsJump(jump_bytecode)); |
854 switch (Bytecodes::GetOperandSize(jump_bytecode, 0)) { | 802 switch (operand_scale) { |
855 case OperandSize::kByte: | 803 case 1: |
856 PatchIndirectJumpWith8BitOperand(jump_location, delta); | 804 PatchIndirectJumpWith8BitOperand(jump_location, delta); |
857 break; | 805 break; |
858 case OperandSize::kShort: | 806 case 2: |
859 PatchIndirectJumpWith16BitOperand(jump_location, delta); | 807 PatchIndirectJumpWith16BitOperand(jump_location + prefix_offset, delta); |
860 break; | 808 break; |
861 case OperandSize::kNone: | 809 case 4: |
810 PatchIndirectJumpWith32BitOperand(jump_location + prefix_offset, delta); | |
811 break; | |
812 default: | |
862 UNREACHABLE(); | 813 UNREACHABLE(); |
863 } | 814 } |
864 unbound_jumps_--; | 815 unbound_jumps_--; |
865 } | 816 } |
866 | 817 |
867 | 818 |
868 BytecodeArrayBuilder& BytecodeArrayBuilder::OutputJump(Bytecode jump_bytecode, | 819 BytecodeArrayBuilder& BytecodeArrayBuilder::OutputJump(Bytecode jump_bytecode, |
869 BytecodeLabel* label) { | 820 BytecodeLabel* label) { |
870 // Don't emit dead code. | 821 // Don't emit dead code. |
871 if (exit_seen_in_block_) return *this; | 822 if (exit_seen_in_block_) return *this; |
872 | 823 |
873 // Check if the value in accumulator is boolean, if not choose an | 824 // Check if the value in accumulator is boolean, if not choose an |
874 // appropriate JumpIfToBoolean bytecode. | 825 // appropriate JumpIfToBoolean bytecode. |
875 if (NeedToBooleanCast()) { | 826 if (NeedToBooleanCast()) { |
876 jump_bytecode = GetJumpWithToBoolean(jump_bytecode); | 827 jump_bytecode = GetJumpWithToBoolean(jump_bytecode); |
877 } | 828 } |
878 | 829 |
879 if (label->is_bound()) { | 830 if (label->is_bound()) { |
880 // Label has been bound already so this is a backwards jump. | 831 // Label has been bound already so this is a backwards jump. |
881 CHECK_GE(bytecodes()->size(), label->offset()); | 832 CHECK_GE(bytecodes()->size(), label->offset()); |
882 CHECK_LE(bytecodes()->size(), static_cast<size_t>(kMaxInt)); | 833 CHECK_LE(bytecodes()->size(), static_cast<size_t>(kMaxInt)); |
883 size_t abs_delta = bytecodes()->size() - label->offset(); | 834 size_t abs_delta = bytecodes()->size() - label->offset(); |
884 int delta = -static_cast<int>(abs_delta); | 835 int delta = -static_cast<int>(abs_delta); |
885 | 836 OperandSize operand_size = SizeForSignedOperand(delta); |
886 if (FitsInImm8Operand(delta)) { | 837 if (operand_size > OperandSize::kByte) { |
887 Output(jump_bytecode, static_cast<uint8_t>(delta)); | 838 // Adjust for scaling byte prefix for wide jump offset. |
888 } else { | 839 DCHECK_LE(delta, 0); |
889 size_t entry = | 840 delta -= 1; |
890 GetConstantPoolEntry(handle(Smi::FromInt(delta), isolate())); | |
891 if (FitsInIdx8Operand(entry)) { | |
892 Output(GetJumpWithConstantOperand(jump_bytecode), | |
893 static_cast<uint8_t>(entry)); | |
894 } else if (FitsInIdx16Operand(entry)) { | |
895 Output(GetJumpWithConstantWideOperand(jump_bytecode), | |
896 static_cast<uint16_t>(entry)); | |
897 } else { | |
898 UNREACHABLE(); | |
899 } | |
900 } | 841 } |
842 OutputScaled(jump_bytecode, static_cast<int>(operand_size), | |
843 SignedOperand(delta, operand_size)); | |
901 } else { | 844 } else { |
902 // The label has not yet been bound so this is a forward reference | 845 // The label has not yet been bound so this is a forward reference |
903 // that will be patched when the label is bound. We create a | 846 // that will be patched when the label is bound. We create a |
904 // reservation in the constant pool so the jump can be patched | 847 // reservation in the constant pool so the jump can be patched |
905 // when the label is bound. The reservation means the maximum size | 848 // when the label is bound. The reservation means the maximum size |
906 // of the operand for the constant is known and the jump can | 849 // of the operand for the constant is known and the jump can |
907 // be emitted into the bytecode stream with space for the operand. | 850 // be emitted into the bytecode stream with space for the operand. |
908 label->set_referrer(bytecodes()->size()); | 851 label->set_referrer(bytecodes()->size()); |
909 unbound_jumps_++; | 852 unbound_jumps_++; |
910 OperandSize reserved_operand_size = | 853 OperandSize reserved_operand_size = |
911 constant_array_builder()->CreateReservedEntry(); | 854 constant_array_builder()->CreateReservedEntry(); |
912 switch (reserved_operand_size) { | 855 OutputScaled(jump_bytecode, static_cast<int>(reserved_operand_size), 0); |
913 case OperandSize::kByte: | |
914 Output(jump_bytecode, 0); | |
915 break; | |
916 case OperandSize::kShort: | |
917 Output(GetJumpWithConstantWideOperand(jump_bytecode), 0); | |
918 break; | |
919 case OperandSize::kNone: | |
920 UNREACHABLE(); | |
921 } | |
922 } | 856 } |
923 LeaveBasicBlock(); | 857 LeaveBasicBlock(); |
924 return *this; | 858 return *this; |
925 } | 859 } |
926 | 860 |
927 | 861 |
928 BytecodeArrayBuilder& BytecodeArrayBuilder::Jump(BytecodeLabel* label) { | 862 BytecodeArrayBuilder& BytecodeArrayBuilder::Jump(BytecodeLabel* label) { |
929 return OutputJump(Bytecode::kJump, label); | 863 return OutputJump(Bytecode::kJump, label); |
930 } | 864 } |
931 | 865 |
(...skipping 49 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
981 return *this; | 915 return *this; |
982 } | 916 } |
983 | 917 |
984 BytecodeArrayBuilder& BytecodeArrayBuilder::Debugger() { | 918 BytecodeArrayBuilder& BytecodeArrayBuilder::Debugger() { |
985 Output(Bytecode::kDebugger); | 919 Output(Bytecode::kDebugger); |
986 return *this; | 920 return *this; |
987 } | 921 } |
988 | 922 |
989 BytecodeArrayBuilder& BytecodeArrayBuilder::ForInPrepare( | 923 BytecodeArrayBuilder& BytecodeArrayBuilder::ForInPrepare( |
990 Register cache_info_triple) { | 924 Register cache_info_triple) { |
991 if (FitsInReg8Operand(cache_info_triple)) { | 925 int operand_scale = OperandScale(SizeForRegisterOperand(cache_info_triple)); |
992 Output(Bytecode::kForInPrepare, cache_info_triple.ToRawOperand()); | 926 OutputScaled(Bytecode::kForInPrepare, operand_scale, |
993 } else if (FitsInReg16Operand(cache_info_triple)) { | 927 RegisterOperand(cache_info_triple)); |
994 Output(Bytecode::kForInPrepareWide, cache_info_triple.ToRawOperand()); | |
995 } else { | |
996 UNIMPLEMENTED(); | |
997 } | |
998 return *this; | 928 return *this; |
999 } | 929 } |
1000 | 930 |
1001 | |
1002 BytecodeArrayBuilder& BytecodeArrayBuilder::ForInDone(Register index, | 931 BytecodeArrayBuilder& BytecodeArrayBuilder::ForInDone(Register index, |
1003 Register cache_length) { | 932 Register cache_length) { |
1004 Output(Bytecode::kForInDone, index.ToRawOperand(), | 933 int operand_scale = OperandScale(SizeForRegisterOperand(index), |
1005 cache_length.ToRawOperand()); | 934 SizeForRegisterOperand(cache_length)); |
935 OutputScaled(Bytecode::kForInDone, operand_scale, RegisterOperand(index), | |
936 RegisterOperand(cache_length)); | |
1006 return *this; | 937 return *this; |
1007 } | 938 } |
1008 | 939 |
1009 BytecodeArrayBuilder& BytecodeArrayBuilder::ForInNext( | 940 BytecodeArrayBuilder& BytecodeArrayBuilder::ForInNext( |
1010 Register receiver, Register index, Register cache_type_array_pair, | 941 Register receiver, Register index, Register cache_type_array_pair, |
1011 int feedback_slot) { | 942 int feedback_slot) { |
1012 if (FitsInReg8Operand(receiver) && FitsInReg8Operand(index) && | 943 int operand_scale = OperandScale( |
1013 FitsInReg8Operand(cache_type_array_pair) && | 944 SizeForRegisterOperand(receiver), SizeForRegisterOperand(index), |
1014 FitsInIdx8Operand(feedback_slot)) { | 945 SizeForRegisterOperand(cache_type_array_pair), |
1015 Output(Bytecode::kForInNext, receiver.ToRawOperand(), index.ToRawOperand(), | 946 SizeForUnsignedOperand(feedback_slot)); |
1016 cache_type_array_pair.ToRawOperand(), | 947 OutputScaled(Bytecode::kForInNext, operand_scale, RegisterOperand(receiver), |
1017 static_cast<uint8_t>(feedback_slot)); | 948 RegisterOperand(index), RegisterOperand(cache_type_array_pair), |
1018 } else if (FitsInReg16Operand(receiver) && FitsInReg16Operand(index) && | 949 UnsignedOperand(feedback_slot)); |
1019 FitsInReg16Operand(cache_type_array_pair) && | |
1020 FitsInIdx16Operand(feedback_slot)) { | |
1021 Output(Bytecode::kForInNextWide, receiver.ToRawOperand(), | |
1022 index.ToRawOperand(), cache_type_array_pair.ToRawOperand(), | |
1023 static_cast<uint16_t>(feedback_slot)); | |
1024 } else { | |
1025 UNIMPLEMENTED(); | |
1026 } | |
1027 return *this; | 950 return *this; |
1028 } | 951 } |
1029 | 952 |
1030 | 953 |
1031 BytecodeArrayBuilder& BytecodeArrayBuilder::ForInStep(Register index) { | 954 BytecodeArrayBuilder& BytecodeArrayBuilder::ForInStep(Register index) { |
1032 Output(Bytecode::kForInStep, index.ToRawOperand()); | 955 int operand_scale = OperandScale(SizeForRegisterOperand(index)); |
956 OutputScaled(Bytecode::kForInStep, operand_scale, RegisterOperand(index)); | |
1033 return *this; | 957 return *this; |
1034 } | 958 } |
1035 | 959 |
1036 | 960 |
1037 BytecodeArrayBuilder& BytecodeArrayBuilder::MarkHandler(int handler_id, | 961 BytecodeArrayBuilder& BytecodeArrayBuilder::MarkHandler(int handler_id, |
1038 bool will_catch) { | 962 bool will_catch) { |
1039 handler_table_builder()->SetHandlerTarget(handler_id, bytecodes()->size()); | 963 handler_table_builder()->SetHandlerTarget(handler_id, bytecodes()->size()); |
1040 handler_table_builder()->SetPrediction(handler_id, will_catch); | 964 handler_table_builder()->SetPrediction(handler_id, will_catch); |
1041 return *this; | 965 return *this; |
1042 } | 966 } |
(...skipping 25 matching lines...) Expand all Loading... | |
1068 } | 992 } |
1069 DCHECK(exit_seen_in_block_); | 993 DCHECK(exit_seen_in_block_); |
1070 } | 994 } |
1071 | 995 |
1072 BytecodeArrayBuilder& BytecodeArrayBuilder::Call(Register callable, | 996 BytecodeArrayBuilder& BytecodeArrayBuilder::Call(Register callable, |
1073 Register receiver_args, | 997 Register receiver_args, |
1074 size_t receiver_args_count, | 998 size_t receiver_args_count, |
1075 int feedback_slot, | 999 int feedback_slot, |
1076 TailCallMode tail_call_mode) { | 1000 TailCallMode tail_call_mode) { |
1077 Bytecode bytecode = BytecodeForCall(tail_call_mode); | 1001 Bytecode bytecode = BytecodeForCall(tail_call_mode); |
1078 if (FitsInReg8Operand(callable) && FitsInReg8Operand(receiver_args) && | 1002 int operand_scale = OperandScale(SizeForRegisterOperand(callable), |
1079 FitsInIdx8Operand(receiver_args_count) && | 1003 SizeForRegisterOperand(receiver_args), |
1080 FitsInIdx8Operand(feedback_slot)) { | 1004 SizeForUnsignedOperand(receiver_args_count), |
1081 Output(bytecode, callable.ToRawOperand(), receiver_args.ToRawOperand(), | 1005 SizeForUnsignedOperand(feedback_slot)); |
1082 static_cast<uint8_t>(receiver_args_count), | 1006 OutputScaled(bytecode, operand_scale, RegisterOperand(callable), |
1083 static_cast<uint8_t>(feedback_slot)); | 1007 RegisterOperand(receiver_args), |
1084 } else if (FitsInReg16Operand(callable) && | 1008 UnsignedOperand(receiver_args_count), |
1085 FitsInReg16Operand(receiver_args) && | 1009 UnsignedOperand(feedback_slot)); |
1086 FitsInIdx16Operand(receiver_args_count) && | |
1087 FitsInIdx16Operand(feedback_slot)) { | |
1088 bytecode = BytecodeForWideOperands(bytecode); | |
1089 Output(bytecode, callable.ToRawOperand(), receiver_args.ToRawOperand(), | |
1090 static_cast<uint16_t>(receiver_args_count), | |
1091 static_cast<uint16_t>(feedback_slot)); | |
1092 } else { | |
1093 UNIMPLEMENTED(); | |
1094 } | |
1095 return *this; | 1010 return *this; |
1096 } | 1011 } |
1097 | 1012 |
1098 BytecodeArrayBuilder& BytecodeArrayBuilder::New(Register constructor, | 1013 BytecodeArrayBuilder& BytecodeArrayBuilder::New(Register constructor, |
1099 Register first_arg, | 1014 Register first_arg, |
1100 size_t arg_count) { | 1015 size_t arg_count) { |
1101 if (!first_arg.is_valid()) { | 1016 if (!first_arg.is_valid()) { |
1102 DCHECK_EQ(0u, arg_count); | 1017 DCHECK_EQ(0u, arg_count); |
1103 first_arg = Register(0); | 1018 first_arg = Register(0); |
1104 } | 1019 } |
1105 if (FitsInReg8Operand(constructor) && FitsInReg8Operand(first_arg) && | 1020 int operand_scale = OperandScale(SizeForRegisterOperand(constructor), |
1106 FitsInIdx8Operand(arg_count)) { | 1021 SizeForRegisterOperand(first_arg), |
1107 Output(Bytecode::kNew, constructor.ToRawOperand(), first_arg.ToRawOperand(), | 1022 SizeForUnsignedOperand(arg_count)); |
1108 static_cast<uint8_t>(arg_count)); | 1023 OutputScaled(Bytecode::kNew, operand_scale, RegisterOperand(constructor), |
1109 } else if (FitsInReg16Operand(constructor) && FitsInReg16Operand(first_arg) && | 1024 RegisterOperand(first_arg), UnsignedOperand(arg_count)); |
1110 FitsInIdx16Operand(arg_count)) { | |
1111 Output(Bytecode::kNewWide, constructor.ToRawOperand(), | |
1112 first_arg.ToRawOperand(), static_cast<uint16_t>(arg_count)); | |
1113 } else { | |
1114 UNIMPLEMENTED(); | |
1115 } | |
1116 return *this; | 1025 return *this; |
1117 } | 1026 } |
1118 | 1027 |
1119 | 1028 |
1120 BytecodeArrayBuilder& BytecodeArrayBuilder::CallRuntime( | 1029 BytecodeArrayBuilder& BytecodeArrayBuilder::CallRuntime( |
1121 Runtime::FunctionId function_id, Register first_arg, size_t arg_count) { | 1030 Runtime::FunctionId function_id, Register first_arg, size_t arg_count) { |
1122 DCHECK_EQ(1, Runtime::FunctionForId(function_id)->result_size); | 1031 DCHECK_EQ(1, Runtime::FunctionForId(function_id)->result_size); |
1123 DCHECK(FitsInIdx16Operand(function_id)); | 1032 DCHECK(SizeForUnsignedOperand(function_id) <= OperandSize::kShort); |
1124 if (!first_arg.is_valid()) { | 1033 if (!first_arg.is_valid()) { |
1125 DCHECK_EQ(0u, arg_count); | 1034 DCHECK_EQ(0u, arg_count); |
1126 first_arg = Register(0); | 1035 first_arg = Register(0); |
1127 } | 1036 } |
1128 if (FitsInReg8Operand(first_arg) && FitsInIdx8Operand(arg_count)) { | 1037 int operand_scale = OperandScale(SizeForRegisterOperand(first_arg), |
1129 Output(Bytecode::kCallRuntime, static_cast<uint16_t>(function_id), | 1038 SizeForUnsignedOperand(arg_count)); |
1130 first_arg.ToRawOperand(), static_cast<uint8_t>(arg_count)); | 1039 OutputScaled(Bytecode::kCallRuntime, operand_scale, |
1131 } else if (FitsInReg16Operand(first_arg) && FitsInIdx16Operand(arg_count)) { | 1040 static_cast<uint16_t>(function_id), RegisterOperand(first_arg), |
1132 Output(Bytecode::kCallRuntimeWide, static_cast<uint16_t>(function_id), | 1041 UnsignedOperand(arg_count)); |
1133 first_arg.ToRawOperand(), static_cast<uint16_t>(arg_count)); | |
1134 } else { | |
1135 UNIMPLEMENTED(); | |
1136 } | |
1137 return *this; | 1042 return *this; |
1138 } | 1043 } |
1139 | 1044 |
1140 | 1045 |
1141 BytecodeArrayBuilder& BytecodeArrayBuilder::CallRuntimeForPair( | 1046 BytecodeArrayBuilder& BytecodeArrayBuilder::CallRuntimeForPair( |
1142 Runtime::FunctionId function_id, Register first_arg, size_t arg_count, | 1047 Runtime::FunctionId function_id, Register first_arg, size_t arg_count, |
1143 Register first_return) { | 1048 Register first_return) { |
1144 DCHECK_EQ(2, Runtime::FunctionForId(function_id)->result_size); | 1049 DCHECK_EQ(2, Runtime::FunctionForId(function_id)->result_size); |
1145 DCHECK(FitsInIdx16Operand(function_id)); | 1050 DCHECK(SizeForUnsignedOperand(function_id) <= OperandSize::kShort); |
1146 if (!first_arg.is_valid()) { | 1051 if (!first_arg.is_valid()) { |
1147 DCHECK_EQ(0u, arg_count); | 1052 DCHECK_EQ(0u, arg_count); |
1148 first_arg = Register(0); | 1053 first_arg = Register(0); |
1149 } | 1054 } |
1150 if (FitsInReg8Operand(first_arg) && FitsInIdx8Operand(arg_count) && | 1055 int operand_scale = OperandScale(SizeForRegisterOperand(first_arg), |
1151 FitsInReg8Operand(first_return)) { | 1056 SizeForUnsignedOperand(arg_count), |
1152 Output(Bytecode::kCallRuntimeForPair, static_cast<uint16_t>(function_id), | 1057 SizeForRegisterOperand(first_return)); |
1153 first_arg.ToRawOperand(), static_cast<uint8_t>(arg_count), | 1058 OutputScaled(Bytecode::kCallRuntimeForPair, operand_scale, |
1154 first_return.ToRawOperand()); | 1059 static_cast<uint16_t>(function_id), RegisterOperand(first_arg), |
1155 } else if (FitsInReg16Operand(first_arg) && FitsInIdx16Operand(arg_count) && | 1060 UnsignedOperand(arg_count), RegisterOperand(first_return)); |
1156 FitsInReg16Operand(first_return)) { | |
1157 Output(Bytecode::kCallRuntimeForPairWide, | |
1158 static_cast<uint16_t>(function_id), first_arg.ToRawOperand(), | |
1159 static_cast<uint16_t>(arg_count), first_return.ToRawOperand()); | |
1160 } else { | |
1161 UNIMPLEMENTED(); | |
1162 } | |
1163 return *this; | 1061 return *this; |
1164 } | 1062 } |
1165 | 1063 |
1166 BytecodeArrayBuilder& BytecodeArrayBuilder::CallJSRuntime( | 1064 BytecodeArrayBuilder& BytecodeArrayBuilder::CallJSRuntime( |
1167 int context_index, Register receiver_args, size_t receiver_args_count) { | 1065 int context_index, Register receiver_args, size_t receiver_args_count) { |
1168 DCHECK(FitsInIdx16Operand(context_index)); | 1066 int operand_scale = OperandScale(SizeForUnsignedOperand(context_index), |
1169 if (FitsInReg8Operand(receiver_args) && | 1067 SizeForRegisterOperand(receiver_args), |
1170 FitsInIdx8Operand(receiver_args_count)) { | 1068 SizeForUnsignedOperand(receiver_args_count)); |
1171 Output(Bytecode::kCallJSRuntime, static_cast<uint16_t>(context_index), | 1069 OutputScaled(Bytecode::kCallJSRuntime, operand_scale, |
1172 receiver_args.ToRawOperand(), | 1070 UnsignedOperand(context_index), RegisterOperand(receiver_args), |
1173 static_cast<uint8_t>(receiver_args_count)); | 1071 UnsignedOperand(receiver_args_count)); |
1174 } else if (FitsInReg16Operand(receiver_args) && | |
1175 FitsInIdx16Operand(receiver_args_count)) { | |
1176 Output(Bytecode::kCallJSRuntimeWide, static_cast<uint16_t>(context_index), | |
1177 receiver_args.ToRawOperand(), | |
1178 static_cast<uint16_t>(receiver_args_count)); | |
1179 } else { | |
1180 UNIMPLEMENTED(); | |
1181 } | |
1182 return *this; | 1072 return *this; |
1183 } | 1073 } |
1184 | 1074 |
1185 | 1075 |
1186 BytecodeArrayBuilder& BytecodeArrayBuilder::Delete(Register object, | 1076 BytecodeArrayBuilder& BytecodeArrayBuilder::Delete(Register object, |
1187 LanguageMode language_mode) { | 1077 LanguageMode language_mode) { |
1188 Output(BytecodeForDelete(language_mode), object.ToRawOperand()); | 1078 int operand_scale = OperandScale(SizeForRegisterOperand(object)); |
1079 OutputScaled(BytecodeForDelete(language_mode), operand_scale, | |
1080 RegisterOperand(object)); | |
1189 return *this; | 1081 return *this; |
1190 } | 1082 } |
1191 | 1083 |
1192 | |
1193 size_t BytecodeArrayBuilder::GetConstantPoolEntry(Handle<Object> object) { | 1084 size_t BytecodeArrayBuilder::GetConstantPoolEntry(Handle<Object> object) { |
1194 return constant_array_builder()->Insert(object); | 1085 return constant_array_builder()->Insert(object); |
1195 } | 1086 } |
1196 | 1087 |
1197 void BytecodeArrayBuilder::SetReturnPosition() { | 1088 void BytecodeArrayBuilder::SetReturnPosition() { |
1198 if (return_position_ == RelocInfo::kNoPosition) return; | 1089 if (return_position_ == RelocInfo::kNoPosition) return; |
1199 if (exit_seen_in_block_) return; | 1090 if (exit_seen_in_block_) return; |
1200 source_position_table_builder_.AddStatementPosition( | 1091 source_position_table_builder_.AddStatementPosition( |
1201 bytecodes_.size(), return_position_, | 1092 bytecodes_.size(), return_position_, |
1202 SourcePositionTableBuilder::OVERWRITE_DUPLICATE); | 1093 SourcePositionTableBuilder::OVERWRITE_DUPLICATE); |
(...skipping 18 matching lines...) Expand all Loading... | |
1221 if (exit_seen_in_block_) return; | 1112 if (exit_seen_in_block_) return; |
1222 source_position_table_builder_.AddStatementPosition(bytecodes_.size(), | 1113 source_position_table_builder_.AddStatementPosition(bytecodes_.size(), |
1223 expr->position()); | 1114 expr->position()); |
1224 } | 1115 } |
1225 | 1116 |
1226 bool BytecodeArrayBuilder::TemporaryRegisterIsLive(Register reg) const { | 1117 bool BytecodeArrayBuilder::TemporaryRegisterIsLive(Register reg) const { |
1227 return temporary_register_allocator()->RegisterIsLive(reg); | 1118 return temporary_register_allocator()->RegisterIsLive(reg); |
1228 } | 1119 } |
1229 | 1120 |
1230 bool BytecodeArrayBuilder::OperandIsValid(Bytecode bytecode, int operand_index, | 1121 bool BytecodeArrayBuilder::OperandIsValid(Bytecode bytecode, int operand_index, |
1122 int operand_scale, | |
1231 uint32_t operand_value) const { | 1123 uint32_t operand_value) const { |
1124 OperandSize operand_size = | |
1125 Bytecodes::GetOperandSize(bytecode, operand_index, operand_scale); | |
1232 OperandType operand_type = Bytecodes::GetOperandType(bytecode, operand_index); | 1126 OperandType operand_type = Bytecodes::GetOperandType(bytecode, operand_index); |
1233 switch (operand_type) { | 1127 switch (operand_type) { |
1234 case OperandType::kNone: | 1128 case OperandType::kNone: |
1235 return false; | 1129 return false; |
1236 case OperandType::kRegCount16: { | 1130 case OperandType::kRegCount: { |
1237 // Expect kRegCount16 is part of a range previous operand is a | |
1238 // valid operand to start a range. | |
1239 if (operand_index > 0) { | 1131 if (operand_index > 0) { |
1240 OperandType previous_operand_type = | 1132 OperandType previous_operand_type = |
1241 Bytecodes::GetOperandType(bytecode, operand_index - 1); | 1133 Bytecodes::GetOperandType(bytecode, operand_index - 1); |
1242 return ((previous_operand_type == OperandType::kMaybeReg16 || | 1134 if (previous_operand_type != OperandType::kMaybeReg && |
1243 previous_operand_type == OperandType::kReg16) && | 1135 previous_operand_type != OperandType::kReg) { |
1244 static_cast<uint16_t>(operand_value) == operand_value); | 1136 return false; |
1245 } else { | 1137 } |
1246 return false; | |
1247 } | 1138 } |
1139 } // Fall-through | |
1140 case OperandType::kFlag8: | |
1141 case OperandType::kIdx: | |
1142 case OperandType::kRuntimeId: | |
1143 case OperandType::kImm: { | |
1144 size_t unsigned_value = static_cast<size_t>(operand_value); | |
1145 return SizeForUnsignedOperand(unsigned_value) <= operand_size; | |
1248 } | 1146 } |
1249 case OperandType::kRegCount8: { | 1147 case OperandType::kMaybeReg: |
1250 // Expect kRegCount8 is part of a range previous operand is a | |
1251 // valid operand to start a range. | |
1252 if (operand_index > 0) { | |
1253 OperandType previous_operand_type = | |
1254 Bytecodes::GetOperandType(bytecode, operand_index - 1); | |
1255 return ((previous_operand_type == OperandType::kMaybeReg8 || | |
1256 previous_operand_type == OperandType::kReg8 || | |
1257 previous_operand_type == OperandType::kMaybeReg16) && | |
1258 static_cast<uint8_t>(operand_value) == operand_value); | |
1259 } else { | |
1260 return false; | |
1261 } | |
1262 } | |
1263 case OperandType::kIdx16: | |
1264 return static_cast<uint16_t>(operand_value) == operand_value; | |
1265 case OperandType::kImm8: | |
1266 case OperandType::kIdx8: | |
1267 return static_cast<uint8_t>(operand_value) == operand_value; | |
1268 case OperandType::kMaybeReg8: | |
1269 if (operand_value == 0) { | 1148 if (operand_value == 0) { |
1270 return true; | 1149 return true; |
1271 } | 1150 } |
1272 // Fall-through to kReg8 case. | 1151 // Fall-through to kReg case. |
1273 case OperandType::kReg8: | 1152 case OperandType::kReg: |
1274 case OperandType::kRegOut8: | 1153 case OperandType::kRegOut: { |
1275 return RegisterIsValid(Register::FromRawOperand(operand_value), | 1154 Register reg = RegisterFromOperand(operand_value); |
1276 operand_type); | 1155 return RegisterIsValid(reg, operand_size); |
1277 case OperandType::kRegOutPair8: | 1156 } |
1278 case OperandType::kRegOutPair16: | 1157 case OperandType::kRegOutPair: |
1279 case OperandType::kRegPair8: | 1158 case OperandType::kRegPair: { |
1280 case OperandType::kRegPair16: { | 1159 Register reg0 = RegisterFromOperand(operand_value); |
1281 Register reg0 = Register::FromRawOperand(operand_value); | |
1282 Register reg1 = Register(reg0.index() + 1); | 1160 Register reg1 = Register(reg0.index() + 1); |
1283 return RegisterIsValid(reg0, operand_type) && | 1161 // The size of reg1 is immaterial. |
rmcilroy
2016/03/16 11:55:54
Good catch! :)
| |
1284 RegisterIsValid(reg1, operand_type); | 1162 return RegisterIsValid(reg0, operand_size) && |
1163 RegisterIsValid(reg1, OperandSize::kQuad); | |
1285 } | 1164 } |
1286 case OperandType::kRegOutTriple8: | 1165 case OperandType::kRegOutTriple: { |
1287 case OperandType::kRegOutTriple16: { | 1166 Register reg0 = RegisterFromOperand(operand_value); |
1288 Register reg0 = Register::FromRawOperand(operand_value); | |
1289 Register reg1 = Register(reg0.index() + 1); | 1167 Register reg1 = Register(reg0.index() + 1); |
1290 Register reg2 = Register(reg0.index() + 2); | 1168 Register reg2 = Register(reg0.index() + 2); |
1291 return RegisterIsValid(reg0, operand_type) && | 1169 // The size of reg1 and reg2 is immaterial. |
1292 RegisterIsValid(reg1, operand_type) && | 1170 return RegisterIsValid(reg0, operand_size) && |
1293 RegisterIsValid(reg2, operand_type); | 1171 RegisterIsValid(reg1, OperandSize::kQuad) && |
1294 } | 1172 RegisterIsValid(reg2, OperandSize::kQuad); |
1295 case OperandType::kMaybeReg16: | |
1296 if (operand_value == 0) { | |
1297 return true; | |
1298 } | |
1299 // Fall-through to kReg16 case. | |
1300 case OperandType::kReg16: | |
1301 case OperandType::kRegOut16: { | |
1302 Register reg = Register::FromRawOperand(operand_value); | |
1303 return RegisterIsValid(reg, operand_type); | |
1304 } | 1173 } |
1305 } | 1174 } |
1306 UNREACHABLE(); | 1175 UNREACHABLE(); |
1307 return false; | 1176 return false; |
1308 } | 1177 } |
1309 | 1178 |
1310 | |
1311 bool BytecodeArrayBuilder::RegisterIsValid(Register reg, | 1179 bool BytecodeArrayBuilder::RegisterIsValid(Register reg, |
1312 OperandType reg_type) const { | 1180 OperandSize reg_size) const { |
1313 if (!reg.is_valid()) { | 1181 if (!reg.is_valid()) { |
1314 return false; | 1182 return false; |
1315 } | 1183 } |
1316 | 1184 |
1317 switch (Bytecodes::SizeOfOperand(reg_type)) { | 1185 if (SizeForRegisterOperand(reg) > reg_size) { |
1318 case OperandSize::kByte: | 1186 return false; |
1319 if (!FitsInReg8OperandUntranslated(reg)) { | |
1320 return false; | |
1321 } | |
1322 break; | |
1323 case OperandSize::kShort: | |
1324 if (!FitsInReg16OperandUntranslated(reg)) { | |
1325 return false; | |
1326 } | |
1327 break; | |
1328 case OperandSize::kNone: | |
1329 UNREACHABLE(); | |
1330 return false; | |
1331 } | 1187 } |
1332 | 1188 |
1333 if (reg.is_current_context() || reg.is_function_closure() || | 1189 if (reg.is_current_context() || reg.is_function_closure() || |
1334 reg.is_new_target()) { | 1190 reg.is_new_target()) { |
1335 return true; | 1191 return true; |
1336 } else if (reg.is_parameter()) { | 1192 } else if (reg.is_parameter()) { |
1337 int parameter_index = reg.ToParameterIndex(parameter_count()); | 1193 int parameter_index = reg.ToParameterIndex(parameter_count()); |
1338 return parameter_index >= 0 && parameter_index < parameter_count(); | 1194 return parameter_index >= 0 && parameter_index < parameter_count(); |
1339 } else if (RegisterTranslator::InTranslationWindow(reg)) { | 1195 } else if (reg.index() < fixed_register_count()) { |
1340 return translation_register_count() > 0; | 1196 return true; |
1341 } else { | 1197 } else { |
1342 reg = RegisterTranslator::UntranslateRegister(reg); | 1198 return TemporaryRegisterIsLive(reg); |
1343 if (reg.index() < fixed_register_count()) { | |
1344 return true; | |
1345 } else { | |
1346 return TemporaryRegisterIsLive(reg); | |
1347 } | |
1348 } | 1199 } |
1349 } | 1200 } |
1350 | 1201 |
1351 | 1202 |
1352 bool BytecodeArrayBuilder::LastBytecodeInSameBlock() const { | 1203 bool BytecodeArrayBuilder::LastBytecodeInSameBlock() const { |
1353 return last_bytecode_start_ < bytecodes()->size() && | 1204 return last_bytecode_start_ < bytecodes()->size() && |
1354 last_bytecode_start_ >= last_block_end_; | 1205 last_bytecode_start_ >= last_block_end_; |
1355 } | 1206 } |
1356 | 1207 |
1357 | 1208 |
1358 bool BytecodeArrayBuilder::IsRegisterInAccumulator(Register reg) { | 1209 bool BytecodeArrayBuilder::IsRegisterInAccumulator(Register reg) { |
1359 if (LastBytecodeInSameBlock()) { | 1210 if (LastBytecodeInSameBlock()) { |
1360 PreviousBytecodeHelper previous_bytecode(*this); | 1211 PreviousBytecodeHelper previous_bytecode(*this); |
1361 Bytecode bytecode = previous_bytecode.GetBytecode(); | 1212 Bytecode bytecode = previous_bytecode.GetBytecode(); |
1362 if (bytecode == Bytecode::kLdar || bytecode == Bytecode::kStar) { | 1213 if (bytecode == Bytecode::kLdar || bytecode == Bytecode::kStar) { |
1363 Register previous_reg = | 1214 return previous_bytecode.GetRegisterOperand(0) == reg; |
1364 Register::FromOperand(previous_bytecode.GetOperand(0)); | |
1365 return previous_reg == reg; | |
1366 } | 1215 } |
1367 } | 1216 } |
1368 return false; | 1217 return false; |
1369 } | 1218 } |
1370 | 1219 |
1371 | 1220 |
1372 // static | 1221 // static |
1373 Bytecode BytecodeArrayBuilder::BytecodeForBinaryOperation(Token::Value op) { | 1222 Bytecode BytecodeArrayBuilder::BytecodeForBinaryOperation(Token::Value op) { |
1374 switch (op) { | 1223 switch (op) { |
1375 case Token::Value::ADD: | 1224 case Token::Value::ADD: |
(...skipping 13 matching lines...) Expand all Loading... | |
1389 case Token::Value::BIT_AND: | 1238 case Token::Value::BIT_AND: |
1390 return Bytecode::kBitwiseAnd; | 1239 return Bytecode::kBitwiseAnd; |
1391 case Token::Value::SHL: | 1240 case Token::Value::SHL: |
1392 return Bytecode::kShiftLeft; | 1241 return Bytecode::kShiftLeft; |
1393 case Token::Value::SAR: | 1242 case Token::Value::SAR: |
1394 return Bytecode::kShiftRight; | 1243 return Bytecode::kShiftRight; |
1395 case Token::Value::SHR: | 1244 case Token::Value::SHR: |
1396 return Bytecode::kShiftRightLogical; | 1245 return Bytecode::kShiftRightLogical; |
1397 default: | 1246 default: |
1398 UNREACHABLE(); | 1247 UNREACHABLE(); |
1399 return static_cast<Bytecode>(-1); | 1248 return Bytecode::kIllegal; |
1400 } | 1249 } |
1401 } | 1250 } |
1402 | 1251 |
1403 | 1252 |
1404 // static | 1253 // static |
1405 Bytecode BytecodeArrayBuilder::BytecodeForCountOperation(Token::Value op) { | 1254 Bytecode BytecodeArrayBuilder::BytecodeForCountOperation(Token::Value op) { |
1406 switch (op) { | 1255 switch (op) { |
1407 case Token::Value::ADD: | 1256 case Token::Value::ADD: |
1408 return Bytecode::kInc; | 1257 return Bytecode::kInc; |
1409 case Token::Value::SUB: | 1258 case Token::Value::SUB: |
1410 return Bytecode::kDec; | 1259 return Bytecode::kDec; |
1411 default: | 1260 default: |
1412 UNREACHABLE(); | 1261 UNREACHABLE(); |
1413 return static_cast<Bytecode>(-1); | 1262 return Bytecode::kIllegal; |
1414 } | 1263 } |
1415 } | 1264 } |
1416 | 1265 |
1417 | 1266 |
1418 // static | 1267 // static |
1419 Bytecode BytecodeArrayBuilder::BytecodeForCompareOperation(Token::Value op) { | 1268 Bytecode BytecodeArrayBuilder::BytecodeForCompareOperation(Token::Value op) { |
1420 switch (op) { | 1269 switch (op) { |
1421 case Token::Value::EQ: | 1270 case Token::Value::EQ: |
1422 return Bytecode::kTestEqual; | 1271 return Bytecode::kTestEqual; |
1423 case Token::Value::NE: | 1272 case Token::Value::NE: |
1424 return Bytecode::kTestNotEqual; | 1273 return Bytecode::kTestNotEqual; |
1425 case Token::Value::EQ_STRICT: | 1274 case Token::Value::EQ_STRICT: |
1426 return Bytecode::kTestEqualStrict; | 1275 return Bytecode::kTestEqualStrict; |
1427 case Token::Value::LT: | 1276 case Token::Value::LT: |
1428 return Bytecode::kTestLessThan; | 1277 return Bytecode::kTestLessThan; |
1429 case Token::Value::GT: | 1278 case Token::Value::GT: |
1430 return Bytecode::kTestGreaterThan; | 1279 return Bytecode::kTestGreaterThan; |
1431 case Token::Value::LTE: | 1280 case Token::Value::LTE: |
1432 return Bytecode::kTestLessThanOrEqual; | 1281 return Bytecode::kTestLessThanOrEqual; |
1433 case Token::Value::GTE: | 1282 case Token::Value::GTE: |
1434 return Bytecode::kTestGreaterThanOrEqual; | 1283 return Bytecode::kTestGreaterThanOrEqual; |
1435 case Token::Value::INSTANCEOF: | 1284 case Token::Value::INSTANCEOF: |
1436 return Bytecode::kTestInstanceOf; | 1285 return Bytecode::kTestInstanceOf; |
1437 case Token::Value::IN: | 1286 case Token::Value::IN: |
1438 return Bytecode::kTestIn; | 1287 return Bytecode::kTestIn; |
1439 default: | 1288 default: |
1440 UNREACHABLE(); | 1289 UNREACHABLE(); |
1441 return static_cast<Bytecode>(-1); | 1290 return Bytecode::kIllegal; |
1442 } | 1291 } |
1443 } | 1292 } |
1444 | 1293 |
1445 | |
1446 // static | |
1447 Bytecode BytecodeArrayBuilder::BytecodeForWideOperands(Bytecode bytecode) { | |
1448 switch (bytecode) { | |
1449 case Bytecode::kCall: | |
1450 return Bytecode::kCallWide; | |
1451 case Bytecode::kTailCall: | |
1452 return Bytecode::kTailCallWide; | |
1453 case Bytecode::kLoadIC: | |
1454 return Bytecode::kLoadICWide; | |
1455 case Bytecode::kKeyedLoadIC: | |
1456 return Bytecode::kKeyedLoadICWide; | |
1457 case Bytecode::kStoreICSloppy: | |
1458 return Bytecode::kStoreICSloppyWide; | |
1459 case Bytecode::kStoreICStrict: | |
1460 return Bytecode::kStoreICStrictWide; | |
1461 case Bytecode::kKeyedStoreICSloppy: | |
1462 return Bytecode::kKeyedStoreICSloppyWide; | |
1463 case Bytecode::kKeyedStoreICStrict: | |
1464 return Bytecode::kKeyedStoreICStrictWide; | |
1465 case Bytecode::kLdaGlobal: | |
1466 return Bytecode::kLdaGlobalWide; | |
1467 case Bytecode::kLdaGlobalInsideTypeof: | |
1468 return Bytecode::kLdaGlobalInsideTypeofWide; | |
1469 case Bytecode::kStaGlobalSloppy: | |
1470 return Bytecode::kStaGlobalSloppyWide; | |
1471 case Bytecode::kStaGlobalStrict: | |
1472 return Bytecode::kStaGlobalStrictWide; | |
1473 case Bytecode::kLdaLookupSlot: | |
1474 return Bytecode::kLdaLookupSlotWide; | |
1475 case Bytecode::kLdaLookupSlotInsideTypeof: | |
1476 return Bytecode::kLdaLookupSlotInsideTypeofWide; | |
1477 case Bytecode::kStaLookupSlotStrict: | |
1478 return Bytecode::kStaLookupSlotStrictWide; | |
1479 case Bytecode::kStaLookupSlotSloppy: | |
1480 return Bytecode::kStaLookupSlotSloppyWide; | |
1481 default: | |
1482 UNREACHABLE(); | |
1483 return static_cast<Bytecode>(-1); | |
1484 } | |
1485 } | |
1486 | |
1487 | 1294 |
1488 // static | 1295 // static |
1489 Bytecode BytecodeArrayBuilder::BytecodeForStoreIC(LanguageMode language_mode) { | 1296 Bytecode BytecodeArrayBuilder::BytecodeForStoreIC(LanguageMode language_mode) { |
1490 switch (language_mode) { | 1297 switch (language_mode) { |
1491 case SLOPPY: | 1298 case SLOPPY: |
1492 return Bytecode::kStoreICSloppy; | 1299 return Bytecode::kStoreICSloppy; |
1493 case STRICT: | 1300 case STRICT: |
1494 return Bytecode::kStoreICStrict; | 1301 return Bytecode::kStoreICStrict; |
1495 default: | 1302 default: |
1496 UNREACHABLE(); | 1303 UNREACHABLE(); |
1497 } | 1304 } |
1498 return static_cast<Bytecode>(-1); | 1305 return Bytecode::kIllegal; |
1499 } | 1306 } |
1500 | 1307 |
1501 | 1308 |
1502 // static | 1309 // static |
1503 Bytecode BytecodeArrayBuilder::BytecodeForKeyedStoreIC( | 1310 Bytecode BytecodeArrayBuilder::BytecodeForKeyedStoreIC( |
1504 LanguageMode language_mode) { | 1311 LanguageMode language_mode) { |
1505 switch (language_mode) { | 1312 switch (language_mode) { |
1506 case SLOPPY: | 1313 case SLOPPY: |
1507 return Bytecode::kKeyedStoreICSloppy; | 1314 return Bytecode::kKeyedStoreICSloppy; |
1508 case STRICT: | 1315 case STRICT: |
1509 return Bytecode::kKeyedStoreICStrict; | 1316 return Bytecode::kKeyedStoreICStrict; |
1510 default: | 1317 default: |
1511 UNREACHABLE(); | 1318 UNREACHABLE(); |
1512 } | 1319 } |
1513 return static_cast<Bytecode>(-1); | 1320 return Bytecode::kIllegal; |
1514 } | 1321 } |
1515 | 1322 |
1516 | 1323 |
1517 // static | 1324 // static |
1518 Bytecode BytecodeArrayBuilder::BytecodeForLoadGlobal(TypeofMode typeof_mode) { | 1325 Bytecode BytecodeArrayBuilder::BytecodeForLoadGlobal(TypeofMode typeof_mode) { |
1519 return typeof_mode == INSIDE_TYPEOF ? Bytecode::kLdaGlobalInsideTypeof | 1326 return typeof_mode == INSIDE_TYPEOF ? Bytecode::kLdaGlobalInsideTypeof |
1520 : Bytecode::kLdaGlobal; | 1327 : Bytecode::kLdaGlobal; |
1521 } | 1328 } |
1522 | 1329 |
1523 | 1330 |
1524 // static | 1331 // static |
1525 Bytecode BytecodeArrayBuilder::BytecodeForStoreGlobal( | 1332 Bytecode BytecodeArrayBuilder::BytecodeForStoreGlobal( |
1526 LanguageMode language_mode) { | 1333 LanguageMode language_mode) { |
1527 switch (language_mode) { | 1334 switch (language_mode) { |
1528 case SLOPPY: | 1335 case SLOPPY: |
1529 return Bytecode::kStaGlobalSloppy; | 1336 return Bytecode::kStaGlobalSloppy; |
1530 case STRICT: | 1337 case STRICT: |
1531 return Bytecode::kStaGlobalStrict; | 1338 return Bytecode::kStaGlobalStrict; |
1532 default: | 1339 default: |
1533 UNREACHABLE(); | 1340 UNREACHABLE(); |
1534 } | 1341 } |
1535 return static_cast<Bytecode>(-1); | 1342 return Bytecode::kIllegal; |
1536 } | 1343 } |
1537 | 1344 |
1538 | 1345 |
1539 // static | 1346 // static |
1540 Bytecode BytecodeArrayBuilder::BytecodeForStoreLookupSlot( | 1347 Bytecode BytecodeArrayBuilder::BytecodeForStoreLookupSlot( |
1541 LanguageMode language_mode) { | 1348 LanguageMode language_mode) { |
1542 switch (language_mode) { | 1349 switch (language_mode) { |
1543 case SLOPPY: | 1350 case SLOPPY: |
1544 return Bytecode::kStaLookupSlotSloppy; | 1351 return Bytecode::kStaLookupSlotSloppy; |
1545 case STRICT: | 1352 case STRICT: |
1546 return Bytecode::kStaLookupSlotStrict; | 1353 return Bytecode::kStaLookupSlotStrict; |
1547 default: | 1354 default: |
1548 UNREACHABLE(); | 1355 UNREACHABLE(); |
1549 } | 1356 } |
1550 return static_cast<Bytecode>(-1); | 1357 return Bytecode::kIllegal; |
1551 } | 1358 } |
1552 | 1359 |
1553 // static | 1360 // static |
1554 Bytecode BytecodeArrayBuilder::BytecodeForCreateArguments( | 1361 Bytecode BytecodeArrayBuilder::BytecodeForCreateArguments( |
1555 CreateArgumentsType type) { | 1362 CreateArgumentsType type) { |
1556 switch (type) { | 1363 switch (type) { |
1557 case CreateArgumentsType::kMappedArguments: | 1364 case CreateArgumentsType::kMappedArguments: |
1558 return Bytecode::kCreateMappedArguments; | 1365 return Bytecode::kCreateMappedArguments; |
1559 case CreateArgumentsType::kUnmappedArguments: | 1366 case CreateArgumentsType::kUnmappedArguments: |
1560 return Bytecode::kCreateUnmappedArguments; | 1367 return Bytecode::kCreateUnmappedArguments; |
1561 case CreateArgumentsType::kRestParameter: | 1368 case CreateArgumentsType::kRestParameter: |
1562 return Bytecode::kCreateRestParameter; | 1369 return Bytecode::kCreateRestParameter; |
1563 } | 1370 } |
1564 UNREACHABLE(); | 1371 UNREACHABLE(); |
1565 return static_cast<Bytecode>(-1); | 1372 return Bytecode::kIllegal; |
1566 } | 1373 } |
1567 | 1374 |
1568 | 1375 |
1569 // static | 1376 // static |
1570 Bytecode BytecodeArrayBuilder::BytecodeForDelete(LanguageMode language_mode) { | 1377 Bytecode BytecodeArrayBuilder::BytecodeForDelete(LanguageMode language_mode) { |
1571 switch (language_mode) { | 1378 switch (language_mode) { |
1572 case SLOPPY: | 1379 case SLOPPY: |
1573 return Bytecode::kDeletePropertySloppy; | 1380 return Bytecode::kDeletePropertySloppy; |
1574 case STRICT: | 1381 case STRICT: |
1575 return Bytecode::kDeletePropertyStrict; | 1382 return Bytecode::kDeletePropertyStrict; |
1576 default: | 1383 default: |
1577 UNREACHABLE(); | 1384 UNREACHABLE(); |
1578 } | 1385 } |
1579 return static_cast<Bytecode>(-1); | 1386 return Bytecode::kIllegal; |
1580 } | 1387 } |
1581 | 1388 |
1582 // static | 1389 // static |
1583 Bytecode BytecodeArrayBuilder::BytecodeForCall(TailCallMode tail_call_mode) { | 1390 Bytecode BytecodeArrayBuilder::BytecodeForCall(TailCallMode tail_call_mode) { |
1584 switch (tail_call_mode) { | 1391 switch (tail_call_mode) { |
1585 case TailCallMode::kDisallow: | 1392 case TailCallMode::kDisallow: |
1586 return Bytecode::kCall; | 1393 return Bytecode::kCall; |
1587 case TailCallMode::kAllow: | 1394 case TailCallMode::kAllow: |
1588 return Bytecode::kTailCall; | 1395 return Bytecode::kTailCall; |
1589 default: | 1396 default: |
1590 UNREACHABLE(); | 1397 UNREACHABLE(); |
1591 } | 1398 } |
1592 return static_cast<Bytecode>(-1); | 1399 return Bytecode::kIllegal; |
1593 } | 1400 } |
1594 | 1401 |
1595 // static | 1402 // static |
1596 bool BytecodeArrayBuilder::FitsInIdx8Operand(int value) { | 1403 OperandSize BytecodeArrayBuilder::SizeForRegisterOperand(Register value) { |
1597 return kMinUInt8 <= value && value <= kMaxUInt8; | 1404 if (value.is_byte_operand()) { |
1598 } | 1405 return OperandSize::kByte; |
1599 | 1406 } else if (value.is_short_operand()) { |
1600 | 1407 return OperandSize::kShort; |
1601 // static | 1408 } else { |
1602 bool BytecodeArrayBuilder::FitsInIdx8Operand(size_t value) { | 1409 return OperandSize::kQuad; |
1603 return value <= static_cast<size_t>(kMaxUInt8); | 1410 } |
1604 } | |
1605 | |
1606 | |
1607 // static | |
1608 bool BytecodeArrayBuilder::FitsInImm8Operand(int value) { | |
1609 return kMinInt8 <= value && value <= kMaxInt8; | |
1610 } | |
1611 | |
1612 | |
1613 // static | |
1614 bool BytecodeArrayBuilder::FitsInIdx16Operand(int value) { | |
1615 return kMinUInt16 <= value && value <= kMaxUInt16; | |
1616 } | |
1617 | |
1618 | |
1619 // static | |
1620 bool BytecodeArrayBuilder::FitsInIdx16Operand(size_t value) { | |
1621 return value <= static_cast<size_t>(kMaxUInt16); | |
1622 } | |
1623 | |
1624 | |
1625 // static | |
1626 bool BytecodeArrayBuilder::FitsInReg8Operand(Register value) { | |
1627 return RegisterTranslator::FitsInReg8Operand(value); | |
1628 } | 1411 } |
1629 | 1412 |
1630 // static | 1413 // static |
1631 bool BytecodeArrayBuilder::FitsInReg8OperandUntranslated(Register value) { | 1414 OperandSize BytecodeArrayBuilder::SizeForSignedOperand(int value) { |
1632 return value.is_byte_operand(); | 1415 if (kMinInt8 <= value && value <= kMaxInt8) { |
1633 } | 1416 return OperandSize::kByte; |
1634 | 1417 } else if (kMinInt16 <= value && value <= kMaxInt16) { |
1635 | 1418 return OperandSize::kShort; |
1636 // static | 1419 } else { |
1637 bool BytecodeArrayBuilder::FitsInReg16Operand(Register value) { | 1420 return OperandSize::kQuad; |
1638 return RegisterTranslator::FitsInReg16Operand(value); | 1421 } |
1639 } | 1422 } |
1640 | 1423 |
1641 // static | 1424 // static |
1642 bool BytecodeArrayBuilder::FitsInReg16OperandUntranslated(Register value) { | 1425 OperandSize BytecodeArrayBuilder::SizeForUnsignedOperand(int value) { |
1643 return value.is_short_operand(); | 1426 DCHECK_GE(value, 0); |
1427 if (value <= kMaxUInt8) { | |
1428 return OperandSize::kByte; | |
1429 } else if (value <= kMaxUInt16) { | |
1430 return OperandSize::kShort; | |
1431 } else { | |
1432 return OperandSize::kQuad; | |
1433 } | |
1434 } | |
1435 | |
1436 OperandSize BytecodeArrayBuilder::SizeForUnsignedOperand(size_t value) { | |
1437 if (value <= static_cast<size_t>(kMaxUInt8)) { | |
1438 return OperandSize::kByte; | |
1439 } else if (value <= static_cast<size_t>(kMaxUInt16)) { | |
1440 return OperandSize::kShort; | |
1441 } else if (value <= kMaxUInt32) { | |
1442 return OperandSize::kQuad; | |
1443 } else { | |
1444 UNREACHABLE(); | |
1445 return OperandSize::kQuad; | |
1446 } | |
1447 } | |
1448 | |
1449 int BytecodeArrayBuilder::OperandScale(OperandSize size0, OperandSize size1, | |
1450 OperandSize size2, OperandSize size3) { | |
1451 OperandSize upper = std::max(size0, size1); | |
1452 OperandSize lower = std::max(size2, size3); | |
1453 OperandSize result = std::max(upper, lower); | |
1454 DCHECK(result <= OperandSize::kQuad); | |
1455 int operand_scale = static_cast<int>(result); | |
1456 DCHECK(base::bits::IsPowerOfTwo32(static_cast<uint32_t>(operand_scale))); | |
1457 return operand_scale; | |
1458 } | |
1459 | |
1460 uint32_t BytecodeArrayBuilder::RegisterOperand(Register reg) { | |
1461 return static_cast<uint32_t>(reg.ToOperand()); | |
1462 } | |
1463 | |
1464 Register BytecodeArrayBuilder::RegisterFromOperand(uint32_t operand) { | |
1465 return Register::FromOperand(static_cast<int32_t>(operand)); | |
1466 } | |
1467 | |
1468 uint32_t BytecodeArrayBuilder::SignedOperand(int value, OperandSize size) { | |
1469 switch (size) { | |
1470 case OperandSize::kByte: | |
1471 return static_cast<uint8_t>(value & 0xff); | |
1472 case OperandSize::kShort: | |
1473 return static_cast<uint16_t>(value & 0xffff); | |
1474 case OperandSize::kQuad: | |
1475 return static_cast<uint32_t>(value); | |
1476 case OperandSize::kNone: | |
1477 UNREACHABLE(); | |
1478 } | |
1479 return 0; | |
1480 } | |
1481 | |
1482 uint32_t BytecodeArrayBuilder::UnsignedOperand(int value) { | |
1483 DCHECK_GE(value, 0); | |
1484 return static_cast<uint32_t>(value); | |
1485 } | |
1486 | |
1487 uint32_t BytecodeArrayBuilder::UnsignedOperand(size_t value) { | |
1488 DCHECK_LE(value, kMaxUInt32); | |
1489 return static_cast<uint32_t>(value); | |
1644 } | 1490 } |
1645 | 1491 |
1646 } // namespace interpreter | 1492 } // namespace interpreter |
1647 } // namespace internal | 1493 } // namespace internal |
1648 } // namespace v8 | 1494 } // namespace v8 |
OLD | NEW |