LCOV - code coverage report
Current view: top level - src/interpreter - bytecode-array-accessor.cc (source / functions) Hit Total Coverage
Test: app.info Lines: 112 120 93.3 %
Date: 2017-10-20 Functions: 29 34 85.3 %

          Line data    Source code
       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
       3             : // found in the LICENSE file.
       4             : 
       5             : #include "src/interpreter/bytecode-array-accessor.h"
       6             : 
       7             : #include "src/interpreter/bytecode-decoder.h"
       8             : #include "src/interpreter/interpreter-intrinsics.h"
       9             : #include "src/objects-inl.h"
      10             : #include "src/objects/code-inl.h"
      11             : 
      12             : namespace v8 {
      13             : namespace internal {
      14             : namespace interpreter {
      15             : 
      16     1020200 : BytecodeArrayAccessor::BytecodeArrayAccessor(
      17             :     Handle<BytecodeArray> bytecode_array, int initial_offset)
      18             :     : bytecode_array_(bytecode_array),
      19             :       bytecode_offset_(initial_offset),
      20             :       operand_scale_(OperandScale::kSingle),
      21     1020200 :       prefix_offset_(0) {
      22     1020200 :   UpdateOperandScale();
      23     1020202 : }
      24             : 
      25    51327241 : void BytecodeArrayAccessor::SetOffset(int offset) {
      26    51327241 :   bytecode_offset_ = offset;
      27    51327241 :   UpdateOperandScale();
      28    51327258 : }
      29             : 
      30    52347432 : void BytecodeArrayAccessor::UpdateOperandScale() {
      31    52347432 :   if (OffsetInBounds()) {
      32             :     uint8_t current_byte = bytecode_array()->get(bytecode_offset_);
      33             :     Bytecode current_bytecode = Bytecodes::FromByte(current_byte);
      34    51331518 :     if (Bytecodes::IsPrefixScalingBytecode(current_bytecode)) {
      35             :       operand_scale_ =
      36     4958302 :           Bytecodes::PrefixBytecodeToOperandScale(current_bytecode);
      37     4958302 :       prefix_offset_ = 1;
      38             :     } else {
      39    46373216 :       operand_scale_ = OperandScale::kSingle;
      40    46373216 :       prefix_offset_ = 0;
      41             :     }
      42             :   }
      43    52347432 : }
      44             : 
      45           0 : bool BytecodeArrayAccessor::OffsetInBounds() const {
      46   104694867 :   return bytecode_offset_ >= 0 && bytecode_offset_ < bytecode_array()->length();
      47             : }
      48             : 
      49    96316756 : Bytecode BytecodeArrayAccessor::current_bytecode() const {
      50             :   DCHECK(OffsetInBounds());
      51             :   uint8_t current_byte =
      52   173236652 :       bytecode_array()->get(bytecode_offset_ + current_prefix_offset());
      53             :   Bytecode current_bytecode = Bytecodes::FromByte(current_byte);
      54             :   DCHECK(!Bytecodes::IsPrefixScalingBytecode(current_bytecode));
      55    32419066 :   return current_bytecode;
      56             : }
      57             : 
      58    32608893 : int BytecodeArrayAccessor::current_bytecode_size() const {
      59             :   return current_prefix_offset() +
      60    32608893 :          Bytecodes::Size(current_bytecode(), current_operand_scale());
      61             : }
      62             : 
      63    11831868 : uint32_t BytecodeArrayAccessor::GetUnsignedOperand(
      64    35495600 :     int operand_index, OperandType operand_type) const {
      65             :   DCHECK_GE(operand_index, 0);
      66             :   DCHECK_LT(operand_index, Bytecodes::NumberOfOperands(current_bytecode()));
      67             :   DCHECK_EQ(operand_type,
      68             :             Bytecodes::GetOperandType(current_bytecode(), operand_index));
      69             :   DCHECK(Bytecodes::IsUnsignedOperandType(operand_type));
      70             :   const uint8_t* operand_start =
      71    11831868 :       bytecode_array()->GetFirstBytecodeAddress() + bytecode_offset_ +
      72    23663736 :       current_prefix_offset() +
      73             :       Bytecodes::GetOperandOffset(current_bytecode(), operand_index,
      74    11831868 :                                   current_operand_scale());
      75             :   return BytecodeDecoder::DecodeUnsignedOperand(operand_start, operand_type,
      76    11831864 :                                                 current_operand_scale());
      77             : }
      78             : 
      79     1000511 : int32_t BytecodeArrayAccessor::GetSignedOperand(
      80     3001533 :     int operand_index, OperandType operand_type) const {
      81             :   DCHECK_GE(operand_index, 0);
      82             :   DCHECK_LT(operand_index, Bytecodes::NumberOfOperands(current_bytecode()));
      83             :   DCHECK_EQ(operand_type,
      84             :             Bytecodes::GetOperandType(current_bytecode(), operand_index));
      85             :   DCHECK(!Bytecodes::IsUnsignedOperandType(operand_type));
      86             :   const uint8_t* operand_start =
      87     1000511 :       bytecode_array()->GetFirstBytecodeAddress() + bytecode_offset_ +
      88     2001022 :       current_prefix_offset() +
      89             :       Bytecodes::GetOperandOffset(current_bytecode(), operand_index,
      90     1000511 :                                   current_operand_scale());
      91             :   return BytecodeDecoder::DecodeSignedOperand(operand_start, operand_type,
      92     1000511 :                                               current_operand_scale());
      93             : }
      94             : 
      95      754317 : uint32_t BytecodeArrayAccessor::GetFlagOperand(int operand_index) const {
      96             :   DCHECK_EQ(Bytecodes::GetOperandType(current_bytecode(), operand_index),
      97             :             OperandType::kFlag8);
      98      754317 :   return GetUnsignedOperand(operand_index, OperandType::kFlag8);
      99             : }
     100             : 
     101      131489 : uint32_t BytecodeArrayAccessor::GetUnsignedImmediateOperand(
     102             :     int operand_index) const {
     103             :   DCHECK_EQ(Bytecodes::GetOperandType(current_bytecode(), operand_index),
     104             :             OperandType::kUImm);
     105     1777099 :   return GetUnsignedOperand(operand_index, OperandType::kUImm);
     106             : }
     107             : 
     108      985435 : int32_t BytecodeArrayAccessor::GetImmediateOperand(int operand_index) const {
     109             :   DCHECK_EQ(Bytecodes::GetOperandType(current_bytecode(), operand_index),
     110             :             OperandType::kImm);
     111     1000511 :   return GetSignedOperand(operand_index, OperandType::kImm);
     112             : }
     113             : 
     114      630874 : uint32_t BytecodeArrayAccessor::GetRegisterCountOperand(
     115             :     int operand_index) const {
     116             :   DCHECK_EQ(Bytecodes::GetOperandType(current_bytecode(), operand_index),
     117             :             OperandType::kRegCount);
     118      630878 :   return GetUnsignedOperand(operand_index, OperandType::kRegCount);
     119             : }
     120             : 
     121     8486927 : uint32_t BytecodeArrayAccessor::GetIndexOperand(int operand_index) const {
     122             :   OperandType operand_type =
     123             :       Bytecodes::GetOperandType(current_bytecode(), operand_index);
     124             :   DCHECK_EQ(operand_type, OperandType::kIdx);
     125     8486927 :   return GetUnsignedOperand(operand_index, operand_type);
     126             : }
     127             : 
     128    63473669 : Register BytecodeArrayAccessor::GetRegisterOperand(int operand_index) const {
     129             :   OperandType operand_type =
     130             :       Bytecodes::GetOperandType(current_bytecode(), operand_index);
     131             :   const uint8_t* operand_start =
     132    21157890 :       bytecode_array()->GetFirstBytecodeAddress() + bytecode_offset_ +
     133    21157890 :       current_prefix_offset() +
     134             :       Bytecodes::GetOperandOffset(current_bytecode(), operand_index,
     135    21157890 :                                   current_operand_scale());
     136             :   return BytecodeDecoder::DecodeRegisterOperand(operand_start, operand_type,
     137    21157889 :                                                 current_operand_scale());
     138             : }
     139             : 
     140          40 : int BytecodeArrayAccessor::GetRegisterOperandRange(int operand_index) const {
     141             :   DCHECK_LE(operand_index, Bytecodes::NumberOfOperands(current_bytecode()));
     142             :   const OperandType* operand_types =
     143             :       Bytecodes::GetOperandTypes(current_bytecode());
     144          40 :   OperandType operand_type = operand_types[operand_index];
     145             :   DCHECK(Bytecodes::IsRegisterOperandType(operand_type));
     146          80 :   if (operand_type == OperandType::kRegList ||
     147          40 :       operand_type == OperandType::kRegOutList) {
     148           8 :     return GetRegisterCountOperand(operand_index + 1);
     149             :   } else {
     150          36 :     return Bytecodes::GetNumberOfRegistersRepresentedBy(operand_type);
     151             :   }
     152             : }
     153             : 
     154      128885 : Runtime::FunctionId BytecodeArrayAccessor::GetRuntimeIdOperand(
     155             :     int operand_index) const {
     156             :   OperandType operand_type =
     157             :       Bytecodes::GetOperandType(current_bytecode(), operand_index);
     158             :   DCHECK_EQ(operand_type, OperandType::kRuntimeId);
     159      128885 :   uint32_t raw_id = GetUnsignedOperand(operand_index, operand_type);
     160      128885 :   return static_cast<Runtime::FunctionId>(raw_id);
     161             : }
     162             : 
     163        9799 : uint32_t BytecodeArrayAccessor::GetNativeContextIndexOperand(
     164             :     int operand_index) const {
     165             :   OperandType operand_type =
     166             :       Bytecodes::GetOperandType(current_bytecode(), operand_index);
     167             :   DCHECK_EQ(operand_type, OperandType::kNativeContextIndex);
     168        9799 :   return GetUnsignedOperand(operand_index, operand_type);
     169             : }
     170             : 
     171       43988 : Runtime::FunctionId BytecodeArrayAccessor::GetIntrinsicIdOperand(
     172             :     int operand_index) const {
     173             :   OperandType operand_type =
     174             :       Bytecodes::GetOperandType(current_bytecode(), operand_index);
     175             :   DCHECK_EQ(operand_type, OperandType::kIntrinsicId);
     176       43988 :   uint32_t raw_id = GetUnsignedOperand(operand_index, operand_type);
     177             :   return IntrinsicsHelper::ToRuntimeId(
     178       43988 :       static_cast<IntrinsicsHelper::IntrinsicId>(raw_id));
     179             : }
     180             : 
     181     3153728 : Handle<Object> BytecodeArrayAccessor::GetConstantAtIndex(int index) const {
     182             :   return FixedArray::get(bytecode_array()->constant_pool(), index,
     183     3153728 :                          bytecode_array()->GetIsolate());
     184             : }
     185             : 
     186     3103381 : Handle<Object> BytecodeArrayAccessor::GetConstantForIndexOperand(
     187             :     int operand_index) const {
     188     3103381 :   return GetConstantAtIndex(GetIndexOperand(operand_index));
     189             : }
     190             : 
     191     1651095 : int BytecodeArrayAccessor::GetJumpTargetOffset() const {
     192             :   Bytecode bytecode = current_bytecode();
     193     1651095 :   if (interpreter::Bytecodes::IsJumpImmediate(bytecode)) {
     194     1630534 :     int relative_offset = GetUnsignedImmediateOperand(0);
     195     1630534 :     if (bytecode == Bytecode::kJumpLoop) {
     196      167279 :       relative_offset = -relative_offset;
     197             :     }
     198     1630534 :     return GetAbsoluteOffset(relative_offset);
     199       20561 :   } else if (interpreter::Bytecodes::IsJumpConstant(bytecode)) {
     200       41122 :     Smi* smi = Smi::cast(*GetConstantForIndexOperand(0));
     201       20561 :     return GetAbsoluteOffset(smi->value());
     202             :   } else {
     203           0 :     UNREACHABLE();
     204             :   }
     205             : }
     206             : 
     207       15076 : JumpTableTargetOffsets BytecodeArrayAccessor::GetJumpTableTargetOffsets()
     208             :     const {
     209             :   DCHECK_EQ(current_bytecode(), Bytecode::kSwitchOnSmiNoFeedback);
     210             : 
     211       15076 :   uint32_t table_start = GetIndexOperand(0);
     212             :   uint32_t table_size = GetUnsignedImmediateOperand(1);
     213             :   int32_t case_value_base = GetImmediateOperand(2);
     214             : 
     215       30152 :   return JumpTableTargetOffsets(this, table_start, table_size, case_value_base);
     216             : }
     217             : 
     218     3370578 : int BytecodeArrayAccessor::GetAbsoluteOffset(int relative_offset) const {
     219     3370578 :   return current_offset() + relative_offset + current_prefix_offset();
     220             : }
     221             : 
     222           0 : bool BytecodeArrayAccessor::OffsetWithinBytecode(int offset) const {
     223           0 :   return current_offset() <= offset &&
     224           0 :          offset < current_offset() + current_bytecode_size();
     225             : }
     226             : 
     227          54 : std::ostream& BytecodeArrayAccessor::PrintTo(std::ostream& os) const {
     228             :   return BytecodeDecoder::Decode(
     229          54 :       os, bytecode_array()->GetFirstBytecodeAddress() + bytecode_offset_,
     230          54 :       bytecode_array()->parameter_count());
     231             : }
     232             : 
     233           0 : JumpTableTargetOffsets::JumpTableTargetOffsets(
     234             :     const BytecodeArrayAccessor* accessor, int table_start, int table_size,
     235             :     int case_value_base)
     236             :     : accessor_(accessor),
     237             :       table_start_(table_start),
     238             :       table_size_(table_size),
     239       15076 :       case_value_base_(case_value_base) {}
     240             : 
     241       15076 : JumpTableTargetOffsets::iterator JumpTableTargetOffsets::begin() const {
     242             :   return iterator(case_value_base_, table_start_, table_start_ + table_size_,
     243       37158 :                   accessor_);
     244             : }
     245       15076 : JumpTableTargetOffsets::iterator JumpTableTargetOffsets::end() const {
     246             :   return iterator(case_value_base_ + table_size_, table_start_ + table_size_,
     247       37158 :                   table_start_ + table_size_, accessor_);
     248             : }
     249        7006 : int JumpTableTargetOffsets::size() const {
     250             :   int ret = 0;
     251             :   // TODO(leszeks): Is there a more efficient way of doing this than iterating?
     252       23104 :   for (const auto& entry : *this) {
     253             :     USE(entry);
     254       16098 :     ret++;
     255             :   }
     256        7006 :   return ret;
     257             : }
     258             : 
     259           0 : JumpTableTargetOffsets::iterator::iterator(
     260             :     int case_value, int table_offset, int table_end,
     261             :     const BytecodeArrayAccessor* accessor)
     262             :     : accessor_(accessor),
     263             :       index_(case_value),
     264             :       table_offset_(table_offset),
     265       88328 :       table_end_(table_end) {
     266       44164 :   UpdateAndAdvanceToValid();
     267           0 : }
     268             : 
     269       34194 : JumpTableTargetOffset JumpTableTargetOffsets::iterator::operator*() {
     270             :   DCHECK_LT(table_offset_, table_end_);
     271             :   DCHECK(current_->IsSmi());
     272      102582 :   return {index_, accessor_->GetAbsoluteOffset(Smi::ToInt(*current_))};
     273             : }
     274             : 
     275       34194 : JumpTableTargetOffsets::iterator& JumpTableTargetOffsets::iterator::
     276             : operator++() {
     277             :   DCHECK_LT(table_offset_, table_end_);
     278       50292 :   ++table_offset_;
     279       50292 :   ++index_;
     280       50292 :   UpdateAndAdvanceToValid();
     281       34194 :   return *this;
     282             : }
     283             : 
     284       49270 : bool JumpTableTargetOffsets::iterator::operator!=(
     285             :     const JumpTableTargetOffsets::iterator& other) {
     286             :   DCHECK_EQ(accessor_, other.accessor_);
     287             :   DCHECK_EQ(table_end_, other.table_end_);
     288             :   DCHECK_EQ(index_ - other.index_, table_offset_ - other.table_offset_);
     289       72374 :   return index_ != other.index_;
     290             : }
     291             : 
     292       94456 : void JumpTableTargetOffsets::iterator::UpdateAndAdvanceToValid() {
     293      188912 :   if (table_offset_ >= table_end_) return;
     294             : 
     295       50292 :   current_ = accessor_->GetConstantAtIndex(table_offset_);
     296       50292 :   Isolate* isolate = accessor_->bytecode_array()->GetIsolate();
     297      100638 :   while (current_->IsTheHole(isolate)) {
     298          54 :     ++table_offset_;
     299          54 :     ++index_;
     300          54 :     current_ = accessor_->GetConstantAtIndex(table_offset_);
     301             :   }
     302             : }
     303             : 
     304             : }  // namespace interpreter
     305             : }  // namespace internal
     306             : }  // namespace v8

Generated by: LCOV version 1.10