Chromium Code Reviews| 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 |