Chromium Code Reviews| Index: src/interpreter/bytecode-array-builder.cc |
| diff --git a/src/interpreter/bytecode-array-builder.cc b/src/interpreter/bytecode-array-builder.cc |
| index 24ef30839644dee2613bd79368f6200836d7d7d7..3a623fa2466721949e170059d161fa91b6aebd92 100644 |
| --- a/src/interpreter/bytecode-array-builder.cc |
| +++ b/src/interpreter/bytecode-array-builder.cc |
| @@ -52,7 +52,8 @@ class BytecodeArrayBuilder::PreviousBytecodeHelper { |
| } |
| Handle<Object> GetConstantForIndexOperand(int operand_index) const { |
| - return array_builder_.constants_.at(GetOperand(operand_index)); |
| + return array_builder_.constant_array_builder()->at( |
| + GetOperand(operand_index)); |
| } |
| private: |
| @@ -68,12 +69,11 @@ BytecodeArrayBuilder::BytecodeArrayBuilder(Isolate* isolate, Zone* zone) |
| zone_(zone), |
| bytecodes_(zone), |
| bytecode_generated_(false), |
| + constant_array_builder_(isolate, zone), |
| last_block_end_(0), |
| last_bytecode_start_(~0), |
| exit_seen_in_block_(false), |
| unbound_jumps_(0), |
| - constants_map_(isolate->heap(), zone), |
| - constants_(zone), |
| parameter_count_(-1), |
| local_register_count_(-1), |
| context_register_count_(-1), |
| @@ -144,21 +144,14 @@ bool BytecodeArrayBuilder::RegisterIsTemporary(Register reg) const { |
| Handle<BytecodeArray> BytecodeArrayBuilder::ToBytecodeArray() { |
| DCHECK_EQ(bytecode_generated_, false); |
| - |
| EnsureReturn(); |
| int bytecode_size = static_cast<int>(bytecodes_.size()); |
| int register_count = fixed_register_count() + temporary_register_count_; |
| int frame_size = register_count * kPointerSize; |
| - |
| Factory* factory = isolate_->factory(); |
| - int constants_count = static_cast<int>(constants_.size()); |
| Handle<FixedArray> constant_pool = |
| - factory->NewFixedArray(constants_count, TENURED); |
| - for (int i = 0; i < constants_count; i++) { |
| - constant_pool->set(i, *constants_[i]); |
| - } |
| - |
| + constant_array_builder()->ToFixedArray(factory, TENURED); |
| Handle<BytecodeArray> output = |
| factory->NewBytecodeArray(bytecode_size, &bytecodes_.front(), frame_size, |
| parameter_count(), constant_pool); |
| @@ -754,39 +747,28 @@ Bytecode BytecodeArrayBuilder::GetJumpWithConstantOperand( |
| } |
| -void BytecodeArrayBuilder::PatchJump( |
| - const ZoneVector<uint8_t>::iterator& jump_target, |
| - ZoneVector<uint8_t>::iterator jump_location) { |
| - Bytecode jump_bytecode = Bytecodes::FromByte(*jump_location); |
| - int delta = static_cast<int>(jump_target - jump_location); |
| - |
| - DCHECK(Bytecodes::IsJump(jump_bytecode)); |
| - DCHECK_EQ(Bytecodes::Size(jump_bytecode), 2); |
| - DCHECK_NE(delta, 0); |
| - |
| - if (FitsInImm8Operand(delta)) { |
| - // Just update the operand |
| - jump_location++; |
| - *jump_location = static_cast<uint8_t>(delta); |
| - } else { |
| - // Update the jump type and operand |
| - size_t entry = GetConstantPoolEntry(handle(Smi::FromInt(delta), isolate())); |
| - if (FitsInIdx8Operand(entry)) { |
| - jump_bytecode = GetJumpWithConstantOperand(jump_bytecode); |
| - *jump_location++ = Bytecodes::ToByte(jump_bytecode); |
| - *jump_location = static_cast<uint8_t>(entry); |
| - } else { |
| - // TODO(oth): OutputJump should reserve a constant pool entry |
| - // when jump is written. The reservation should be used here if |
| - // needed, or cancelled if not. This is due to the patch needing |
| - // to match the size of the code it's replacing. In future, |
| - // there will probably be a jump with 32-bit operand for cases |
| - // when constant pool is full, but that needs to be emitted in |
| - // OutputJump too. |
| - UNIMPLEMENTED(); |
| - } |
| +// static |
| +Bytecode BytecodeArrayBuilder::GetJumpWithConstantWideOperand( |
| + Bytecode jump_bytecode) { |
| + switch (jump_bytecode) { |
| + case Bytecode::kJump: |
| + return Bytecode::kJumpConstantWide; |
| + case Bytecode::kJumpIfTrue: |
| + return Bytecode::kJumpIfTrueConstantWide; |
| + case Bytecode::kJumpIfFalse: |
| + return Bytecode::kJumpIfFalseConstantWide; |
| + case Bytecode::kJumpIfToBooleanTrue: |
| + return Bytecode::kJumpIfToBooleanTrueConstantWide; |
| + case Bytecode::kJumpIfToBooleanFalse: |
| + return Bytecode::kJumpIfToBooleanFalseConstantWide; |
| + case Bytecode::kJumpIfNull: |
| + return Bytecode::kJumpIfNullConstantWide; |
| + case Bytecode::kJumpIfUndefined: |
| + return Bytecode::kJumpIfUndefinedConstantWide; |
| + default: |
| + UNREACHABLE(); |
| + return Bytecode::kJumpConstantWide; |
| } |
| - unbound_jumps_--; |
| } |
| @@ -808,6 +790,48 @@ Bytecode BytecodeArrayBuilder::GetJumpWithToBoolean(Bytecode jump_bytecode) { |
| } |
| +void BytecodeArrayBuilder::PatchJump( |
| + const ZoneVector<uint8_t>::iterator& jump_target, |
| + const ZoneVector<uint8_t>::iterator& jump_location) { |
| + int delta = static_cast<int>(jump_target - jump_location); |
| + Bytecode jump_bytecode = Bytecodes::FromByte(*jump_location); |
| + auto operand_location = jump_location + 1; |
| + auto reservation_token = |
| + static_cast<ConstantArrayBuilder::ReservationToken>(*operand_location); |
| + if (Bytecodes::IsJumpImmediate(jump_bytecode)) { |
|
mythria
2015/12/24 15:53:44
May be we can check for reservation token to be Id
oth
2015/12/27 08:42:34
Done.
|
| + // A reservation for an entry in the constant array with an 8-bit index. |
| + DCHECK(ConstantArrayBuilder::ReservationToken::kIdx8 == reservation_token); |
| + if (FitsInImm8Operand(delta)) { |
| + // The jump fits with the range of an Imm8 operand, so cancel |
| + // the reservation and jump directly. |
| + constant_array_builder()->DiscardReservedEntry(reservation_token); |
| + *operand_location = static_cast<uint8_t>(delta); |
| + } else { |
| + // The jump does not fit in range of an Imm8 operand, so commit |
| + // reservation and update the jump instruction and operand. |
| + size_t entry = constant_array_builder()->CommitReservedEntry( |
| + reservation_token, handle(Smi::FromInt(delta), isolate())); |
| + DCHECK(FitsInIdx8Operand(entry)); |
| + jump_bytecode = GetJumpWithConstantOperand(jump_bytecode); |
| + *jump_location = Bytecodes::ToByte(jump_bytecode); |
| + *operand_location = static_cast<uint8_t>(entry); |
| + } |
| + } else { |
| + // A reservation for an entry in the constant array with a 16-bit index. |
| + DCHECK(ConstantArrayBuilder::ReservationToken::kIdx16 == reservation_token); |
| + DCHECK(Bytecodes::IsJumpConstantWide(jump_bytecode)); |
| + size_t entry = constant_array_builder()->CommitReservedEntry( |
| + reservation_token, handle(Smi::FromInt(delta), isolate())); |
| + DCHECK(FitsInIdx16Operand(entry)); |
| + uint8_t operand_bytes[2]; |
| + WriteUnalignedUInt16(operand_bytes, static_cast<uint16_t>(entry)); |
| + *operand_location++ = operand_bytes[0]; |
| + *operand_location = operand_bytes[1]; |
| + } |
| + unbound_jumps_--; |
| +} |
| + |
| + |
| BytecodeArrayBuilder& BytecodeArrayBuilder::OutputJump(Bytecode jump_bytecode, |
| BytecodeLabel* label) { |
| // Don't emit dead code. |
| @@ -819,32 +843,48 @@ BytecodeArrayBuilder& BytecodeArrayBuilder::OutputJump(Bytecode jump_bytecode, |
| jump_bytecode = GetJumpWithToBoolean(jump_bytecode); |
| } |
| - int delta; |
| if (label->is_bound()) { |
| // Label has been bound already so this is a backwards jump. |
| CHECK_GE(bytecodes()->size(), label->offset()); |
| CHECK_LE(bytecodes()->size(), static_cast<size_t>(kMaxInt)); |
| size_t abs_delta = bytecodes()->size() - label->offset(); |
| - delta = -static_cast<int>(abs_delta); |
| + int delta = -static_cast<int>(abs_delta); |
| + |
| + if (FitsInImm8Operand(delta)) { |
| + Output(jump_bytecode, static_cast<uint8_t>(delta)); |
| + } else { |
| + size_t entry = |
| + GetConstantPoolEntry(handle(Smi::FromInt(delta), isolate())); |
| + if (FitsInIdx8Operand(entry)) { |
| + Output(GetJumpWithConstantOperand(jump_bytecode), |
| + static_cast<uint8_t>(entry)); |
| + } else if (FitsInIdx16Operand(entry)) { |
| + Output(GetJumpWithConstantWideOperand(jump_bytecode), |
| + static_cast<uint16_t>(entry)); |
| + } else { |
| + UNREACHABLE(); |
| + } |
| + } |
| } else { |
| // Label has not yet been bound so this is a forward reference |
| // that will be patched when the label is bound. |
| label->set_referrer(bytecodes()->size()); |
| - delta = 0; |
| unbound_jumps_++; |
| - } |
| - |
| - if (FitsInImm8Operand(delta)) { |
| - Output(jump_bytecode, static_cast<uint8_t>(delta)); |
| - } else { |
| - size_t entry = GetConstantPoolEntry(handle(Smi::FromInt(delta), isolate())); |
| - if (FitsInIdx8Operand(entry)) { |
| - Output(GetJumpWithConstantOperand(jump_bytecode), |
| - static_cast<uint8_t>(entry)); |
| - } else { |
| - UNIMPLEMENTED(); |
| + auto token = constant_array_builder()->CreateReservedEntry(); |
| + switch (token) { |
| + case ConstantArrayBuilder::ReservationToken::kIdx8: { |
| + Output(jump_bytecode, static_cast<uint8_t>(token)); |
| + break; |
| + } |
| + case ConstantArrayBuilder::ReservationToken::kIdx16: { |
| + uint16_t target = static_cast<uint16_t>(token); |
| + target |= target << 8; |
| + Output(GetJumpWithConstantWideOperand(jump_bytecode), target); |
| + break; |
| + } |
| } |
| } |
| + |
| LeaveBasicBlock(); |
| return *this; |
| } |
| @@ -1002,22 +1042,7 @@ BytecodeArrayBuilder& BytecodeArrayBuilder::Delete(Register object, |
| size_t BytecodeArrayBuilder::GetConstantPoolEntry(Handle<Object> object) { |
| - // These constants shouldn't be added to the constant pool, the should use |
| - // specialzed bytecodes instead. |
| - DCHECK(!object.is_identical_to(isolate_->factory()->undefined_value())); |
| - DCHECK(!object.is_identical_to(isolate_->factory()->null_value())); |
| - DCHECK(!object.is_identical_to(isolate_->factory()->the_hole_value())); |
| - DCHECK(!object.is_identical_to(isolate_->factory()->true_value())); |
| - DCHECK(!object.is_identical_to(isolate_->factory()->false_value())); |
| - |
| - size_t* entry = constants_map_.Find(object); |
| - if (!entry) { |
| - entry = constants_map_.Get(object); |
| - *entry = constants_.size(); |
| - constants_.push_back(object); |
| - } |
| - DCHECK(constants_[*entry].is_identical_to(object)); |
| - return *entry; |
| + return constant_array_builder()->Insert(object); |
| } |