[interpreter] Add bytecodes for JumpIfNotHole with constant
Adds JumpIfNotHoleConstant and JumpIfNotHoleConstantWide bytecodes and removes JumpIfHole bytecode. In situations with large numbers of constants, the generator would fail because an 8-bit constant could not be reserved for JumpIfHole/JumpIfNotHole and so a 16-bit constant would be reserved. Then when patching the bytecode the patcher would discover there was no wide constant variant of the emitted jump. BUG=v8:4280,v8:4680 LOG=N Review URL: https://codereview.chromium.org/1697473002 Cr-Commit-Position: refs/heads/master@{#33952}
This commit is contained in:
parent
d00644a011
commit
47c08f5f71
@ -1426,6 +1426,16 @@ void BytecodeGraphBuilder::VisitJumpIfToBooleanFalseConstantWide() {
|
|||||||
BuildJumpIfToBooleanEqual(jsgraph()->FalseConstant());
|
BuildJumpIfToBooleanEqual(jsgraph()->FalseConstant());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void BytecodeGraphBuilder::VisitJumpIfNotHole() { BuildJumpIfNotHole(); }
|
||||||
|
|
||||||
|
void BytecodeGraphBuilder::VisitJumpIfNotHoleConstant() {
|
||||||
|
BuildJumpIfNotHole();
|
||||||
|
}
|
||||||
|
|
||||||
|
void BytecodeGraphBuilder::VisitJumpIfNotHoleConstantWide() {
|
||||||
|
BuildJumpIfNotHole();
|
||||||
|
}
|
||||||
|
|
||||||
void BytecodeGraphBuilder::VisitJumpIfNull() {
|
void BytecodeGraphBuilder::VisitJumpIfNull() {
|
||||||
BuildJumpIfEqual(jsgraph()->NullConstant());
|
BuildJumpIfEqual(jsgraph()->NullConstant());
|
||||||
}
|
}
|
||||||
@ -1450,20 +1460,6 @@ void BytecodeGraphBuilder::VisitJumpIfUndefinedConstantWide() {
|
|||||||
BuildJumpIfEqual(jsgraph()->UndefinedConstant());
|
BuildJumpIfEqual(jsgraph()->UndefinedConstant());
|
||||||
}
|
}
|
||||||
|
|
||||||
void BytecodeGraphBuilder::VisitJumpIfHole() {
|
|
||||||
BuildJumpIfEqual(jsgraph()->TheHoleConstant());
|
|
||||||
}
|
|
||||||
|
|
||||||
void BytecodeGraphBuilder::VisitJumpIfNotHole() {
|
|
||||||
Node* accumulator = environment()->LookupAccumulator();
|
|
||||||
Node* condition = NewNode(javascript()->StrictEqual(), accumulator,
|
|
||||||
jsgraph()->TheHoleConstant());
|
|
||||||
Node* node =
|
|
||||||
NewNode(common()->Select(MachineRepresentation::kTagged), condition,
|
|
||||||
jsgraph()->FalseConstant(), jsgraph()->TrueConstant());
|
|
||||||
BuildConditionalJump(node);
|
|
||||||
}
|
|
||||||
|
|
||||||
void BytecodeGraphBuilder::VisitStackCheck() {
|
void BytecodeGraphBuilder::VisitStackCheck() {
|
||||||
FrameStateBeforeAndAfter states(this);
|
FrameStateBeforeAndAfter states(this);
|
||||||
Node* node = NewNode(javascript()->StackCheck());
|
Node* node = NewNode(javascript()->StackCheck());
|
||||||
@ -1601,6 +1597,15 @@ void BytecodeGraphBuilder::BuildJumpIfToBooleanEqual(Node* comperand) {
|
|||||||
BuildConditionalJump(condition);
|
BuildConditionalJump(condition);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void BytecodeGraphBuilder::BuildJumpIfNotHole() {
|
||||||
|
Node* accumulator = environment()->LookupAccumulator();
|
||||||
|
Node* condition = NewNode(javascript()->StrictEqual(), accumulator,
|
||||||
|
jsgraph()->TheHoleConstant());
|
||||||
|
Node* node =
|
||||||
|
NewNode(common()->Select(MachineRepresentation::kTagged), condition,
|
||||||
|
jsgraph()->FalseConstant(), jsgraph()->TrueConstant());
|
||||||
|
BuildConditionalJump(node);
|
||||||
|
}
|
||||||
|
|
||||||
Node** BytecodeGraphBuilder::EnsureInputBufferSize(int size) {
|
Node** BytecodeGraphBuilder::EnsureInputBufferSize(int size) {
|
||||||
if (size > input_buffer_size_) {
|
if (size > input_buffer_size_) {
|
||||||
|
@ -141,6 +141,7 @@ class BytecodeGraphBuilder {
|
|||||||
void BuildConditionalJump(Node* condition);
|
void BuildConditionalJump(Node* condition);
|
||||||
void BuildJumpIfEqual(Node* comperand);
|
void BuildJumpIfEqual(Node* comperand);
|
||||||
void BuildJumpIfToBooleanEqual(Node* boolean_comperand);
|
void BuildJumpIfToBooleanEqual(Node* boolean_comperand);
|
||||||
|
void BuildJumpIfNotHole();
|
||||||
|
|
||||||
// Simulates control flow by forward-propagating environments.
|
// Simulates control flow by forward-propagating environments.
|
||||||
void MergeIntoSuccessorEnvironment(int target_offset);
|
void MergeIntoSuccessorEnvironment(int target_offset);
|
||||||
|
@ -761,6 +761,8 @@ Bytecode BytecodeArrayBuilder::GetJumpWithConstantOperand(
|
|||||||
return Bytecode::kJumpIfToBooleanTrueConstant;
|
return Bytecode::kJumpIfToBooleanTrueConstant;
|
||||||
case Bytecode::kJumpIfToBooleanFalse:
|
case Bytecode::kJumpIfToBooleanFalse:
|
||||||
return Bytecode::kJumpIfToBooleanFalseConstant;
|
return Bytecode::kJumpIfToBooleanFalseConstant;
|
||||||
|
case Bytecode::kJumpIfNotHole:
|
||||||
|
return Bytecode::kJumpIfNotHoleConstant;
|
||||||
case Bytecode::kJumpIfNull:
|
case Bytecode::kJumpIfNull:
|
||||||
return Bytecode::kJumpIfNullConstant;
|
return Bytecode::kJumpIfNullConstant;
|
||||||
case Bytecode::kJumpIfUndefined:
|
case Bytecode::kJumpIfUndefined:
|
||||||
@ -786,6 +788,8 @@ Bytecode BytecodeArrayBuilder::GetJumpWithConstantWideOperand(
|
|||||||
return Bytecode::kJumpIfToBooleanTrueConstantWide;
|
return Bytecode::kJumpIfToBooleanTrueConstantWide;
|
||||||
case Bytecode::kJumpIfToBooleanFalse:
|
case Bytecode::kJumpIfToBooleanFalse:
|
||||||
return Bytecode::kJumpIfToBooleanFalseConstantWide;
|
return Bytecode::kJumpIfToBooleanFalseConstantWide;
|
||||||
|
case Bytecode::kJumpIfNotHole:
|
||||||
|
return Bytecode::kJumpIfNotHoleConstantWide;
|
||||||
case Bytecode::kJumpIfNull:
|
case Bytecode::kJumpIfNull:
|
||||||
return Bytecode::kJumpIfNullConstantWide;
|
return Bytecode::kJumpIfNullConstantWide;
|
||||||
case Bytecode::kJumpIfUndefined:
|
case Bytecode::kJumpIfUndefined:
|
||||||
@ -803,7 +807,6 @@ Bytecode BytecodeArrayBuilder::GetJumpWithToBoolean(Bytecode jump_bytecode) {
|
|||||||
case Bytecode::kJump:
|
case Bytecode::kJump:
|
||||||
case Bytecode::kJumpIfNull:
|
case Bytecode::kJumpIfNull:
|
||||||
case Bytecode::kJumpIfUndefined:
|
case Bytecode::kJumpIfUndefined:
|
||||||
case Bytecode::kJumpIfHole:
|
|
||||||
case Bytecode::kJumpIfNotHole:
|
case Bytecode::kJumpIfNotHole:
|
||||||
return jump_bytecode;
|
return jump_bytecode;
|
||||||
case Bytecode::kJumpIfTrue:
|
case Bytecode::kJumpIfTrue:
|
||||||
@ -970,10 +973,6 @@ BytecodeArrayBuilder& BytecodeArrayBuilder::StackCheck() {
|
|||||||
return *this;
|
return *this;
|
||||||
}
|
}
|
||||||
|
|
||||||
BytecodeArrayBuilder& BytecodeArrayBuilder::JumpIfHole(BytecodeLabel* label) {
|
|
||||||
return OutputJump(Bytecode::kJumpIfHole, label);
|
|
||||||
}
|
|
||||||
|
|
||||||
BytecodeArrayBuilder& BytecodeArrayBuilder::JumpIfNotHole(
|
BytecodeArrayBuilder& BytecodeArrayBuilder::JumpIfNotHole(
|
||||||
BytecodeLabel* label) {
|
BytecodeLabel* label) {
|
||||||
return OutputJump(Bytecode::kJumpIfNotHole, label);
|
return OutputJump(Bytecode::kJumpIfNotHole, label);
|
||||||
|
@ -225,10 +225,9 @@ class BytecodeArrayBuilder final : public ZoneObject, private RegisterMover {
|
|||||||
BytecodeArrayBuilder& Jump(BytecodeLabel* label);
|
BytecodeArrayBuilder& Jump(BytecodeLabel* label);
|
||||||
BytecodeArrayBuilder& JumpIfTrue(BytecodeLabel* label);
|
BytecodeArrayBuilder& JumpIfTrue(BytecodeLabel* label);
|
||||||
BytecodeArrayBuilder& JumpIfFalse(BytecodeLabel* label);
|
BytecodeArrayBuilder& JumpIfFalse(BytecodeLabel* label);
|
||||||
|
BytecodeArrayBuilder& JumpIfNotHole(BytecodeLabel* label);
|
||||||
BytecodeArrayBuilder& JumpIfNull(BytecodeLabel* label);
|
BytecodeArrayBuilder& JumpIfNull(BytecodeLabel* label);
|
||||||
BytecodeArrayBuilder& JumpIfUndefined(BytecodeLabel* label);
|
BytecodeArrayBuilder& JumpIfUndefined(BytecodeLabel* label);
|
||||||
BytecodeArrayBuilder& JumpIfHole(BytecodeLabel* label);
|
|
||||||
BytecodeArrayBuilder& JumpIfNotHole(BytecodeLabel* label);
|
|
||||||
|
|
||||||
BytecodeArrayBuilder& StackCheck();
|
BytecodeArrayBuilder& StackCheck();
|
||||||
|
|
||||||
|
@ -1698,9 +1698,7 @@ void BytecodeGenerator::BuildHoleCheckForVariableLoad(VariableMode mode,
|
|||||||
Handle<String> name) {
|
Handle<String> name) {
|
||||||
if (mode == CONST_LEGACY) {
|
if (mode == CONST_LEGACY) {
|
||||||
BytecodeLabel end_label;
|
BytecodeLabel end_label;
|
||||||
builder()->JumpIfNotHole(&end_label);
|
builder()->JumpIfNotHole(&end_label).LoadUndefined().Bind(&end_label);
|
||||||
builder()->LoadUndefined();
|
|
||||||
builder()->Bind(&end_label);
|
|
||||||
} else if (mode == LET || mode == CONST) {
|
} else if (mode == LET || mode == CONST) {
|
||||||
BuildThrowIfHole(name);
|
BuildThrowIfHole(name);
|
||||||
}
|
}
|
||||||
@ -1770,14 +1768,12 @@ void BytecodeGenerator::VisitVariableLoad(Variable* variable,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void BytecodeGenerator::VisitVariableLoadForAccumulatorValue(
|
void BytecodeGenerator::VisitVariableLoadForAccumulatorValue(
|
||||||
Variable* variable, FeedbackVectorSlot slot, TypeofMode typeof_mode) {
|
Variable* variable, FeedbackVectorSlot slot, TypeofMode typeof_mode) {
|
||||||
AccumulatorResultScope accumulator_result(this);
|
AccumulatorResultScope accumulator_result(this);
|
||||||
VisitVariableLoad(variable, slot, typeof_mode);
|
VisitVariableLoad(variable, slot, typeof_mode);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
Register BytecodeGenerator::VisitVariableLoadForRegisterValue(
|
Register BytecodeGenerator::VisitVariableLoadForRegisterValue(
|
||||||
Variable* variable, FeedbackVectorSlot slot, TypeofMode typeof_mode) {
|
Variable* variable, FeedbackVectorSlot slot, TypeofMode typeof_mode) {
|
||||||
RegisterResultScope register_scope(this);
|
RegisterResultScope register_scope(this);
|
||||||
@ -1785,43 +1781,42 @@ Register BytecodeGenerator::VisitVariableLoadForRegisterValue(
|
|||||||
return register_scope.ResultRegister();
|
return register_scope.ResultRegister();
|
||||||
}
|
}
|
||||||
|
|
||||||
void BytecodeGenerator::BuildThrowIfHole(Handle<String> name) {
|
void BytecodeGenerator::BuildThrowReferenceError(Handle<String> name) {
|
||||||
|
RegisterAllocationScope register_scope(this);
|
||||||
Register name_reg = register_allocator()->NewRegister();
|
Register name_reg = register_allocator()->NewRegister();
|
||||||
BytecodeLabel end_label;
|
builder()->LoadLiteral(name).StoreAccumulatorInRegister(name_reg).CallRuntime(
|
||||||
// TODO(mythria): This will be replaced by a new bytecode that throws an
|
Runtime::kThrowReferenceError, name_reg, 1);
|
||||||
// error if the value is the hole.
|
}
|
||||||
builder()
|
|
||||||
->JumpIfNotHole(&end_label)
|
void BytecodeGenerator::BuildThrowIfHole(Handle<String> name) {
|
||||||
.LoadLiteral(name)
|
// TODO(interpreter): Can the parser reduce the number of checks
|
||||||
.StoreAccumulatorInRegister(name_reg)
|
// performed? Or should there be a ThrowIfHole bytecode.
|
||||||
.CallRuntime(Runtime::kThrowReferenceError, name_reg, 1)
|
BytecodeLabel no_reference_error;
|
||||||
.Bind(&end_label);
|
builder()->JumpIfNotHole(&no_reference_error);
|
||||||
|
BuildThrowReferenceError(name);
|
||||||
|
builder()->Bind(&no_reference_error);
|
||||||
}
|
}
|
||||||
|
|
||||||
void BytecodeGenerator::BuildThrowIfNotHole(Handle<String> name) {
|
void BytecodeGenerator::BuildThrowIfNotHole(Handle<String> name) {
|
||||||
Register name_reg = register_allocator()->NewRegister();
|
// TODO(interpreter): Can the parser reduce the number of checks
|
||||||
BytecodeLabel end_label;
|
// performed? Or should there be a ThrowIfNotHole bytecode.
|
||||||
// TODO(mythria): This will be replaced by a new bytecode that throws an
|
BytecodeLabel no_reference_error, reference_error;
|
||||||
// error if the value is not the hole.
|
|
||||||
builder()
|
builder()
|
||||||
->JumpIfHole(&end_label)
|
->JumpIfNotHole(&reference_error)
|
||||||
.LoadLiteral(name)
|
.Jump(&no_reference_error)
|
||||||
.StoreAccumulatorInRegister(name_reg)
|
.Bind(&reference_error);
|
||||||
.CallRuntime(Runtime::kThrowReferenceError, name_reg, 1)
|
BuildThrowReferenceError(name);
|
||||||
.Bind(&end_label);
|
builder()->Bind(&no_reference_error);
|
||||||
}
|
}
|
||||||
|
|
||||||
void BytecodeGenerator::BuildThrowReassignConstant(Handle<String> name) {
|
void BytecodeGenerator::BuildThrowReassignConstant(Handle<String> name) {
|
||||||
Register name_reg = register_allocator()->NewRegister();
|
|
||||||
BytecodeLabel else_label;
|
|
||||||
// TODO(mythria): This will be replaced by a new bytecode that throws an
|
// TODO(mythria): This will be replaced by a new bytecode that throws an
|
||||||
// appropriate error depending on the whether the value is a hole or not.
|
// appropriate error depending on the whether the value is a hole or not.
|
||||||
|
BytecodeLabel const_assign_error;
|
||||||
|
builder()->JumpIfNotHole(&const_assign_error);
|
||||||
|
BuildThrowReferenceError(name);
|
||||||
builder()
|
builder()
|
||||||
->JumpIfNotHole(&else_label)
|
->Bind(&const_assign_error)
|
||||||
.LoadLiteral(name)
|
|
||||||
.StoreAccumulatorInRegister(name_reg)
|
|
||||||
.CallRuntime(Runtime::kThrowReferenceError, name_reg, 1)
|
|
||||||
.Bind(&else_label)
|
|
||||||
.CallRuntime(Runtime::kThrowConstAssignError, Register(), 0);
|
.CallRuntime(Runtime::kThrowConstAssignError, Register(), 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1841,7 +1836,7 @@ void BytecodeGenerator::BuildHoleCheckForVariableAssignment(Variable* variable,
|
|||||||
// Perform an initialization check for 'this'. 'this' variable is the
|
// Perform an initialization check for 'this'. 'this' variable is the
|
||||||
// only variable able to trigger bind operations outside the TDZ
|
// only variable able to trigger bind operations outside the TDZ
|
||||||
// via 'super' calls.
|
// via 'super' calls.
|
||||||
BuildThrowIfNotHole(variable->name());
|
BuildThrowIfHole(variable->name());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -78,9 +78,11 @@ class BytecodeGenerator final : public AstVisitor {
|
|||||||
TypeofMode typeof_mode = NOT_INSIDE_TYPEOF);
|
TypeofMode typeof_mode = NOT_INSIDE_TYPEOF);
|
||||||
void VisitVariableAssignment(Variable* variable, Token::Value op,
|
void VisitVariableAssignment(Variable* variable, Token::Value op,
|
||||||
FeedbackVectorSlot slot);
|
FeedbackVectorSlot slot);
|
||||||
|
|
||||||
void BuildThrowIfHole(Handle<String> name);
|
void BuildThrowIfHole(Handle<String> name);
|
||||||
void BuildThrowIfNotHole(Handle<String> name);
|
void BuildThrowIfNotHole(Handle<String> name);
|
||||||
void BuildThrowReassignConstant(Handle<String> name);
|
void BuildThrowReassignConstant(Handle<String> name);
|
||||||
|
void BuildThrowReferenceError(Handle<String> name);
|
||||||
void BuildHoleCheckForVariableLoad(VariableMode mode, Handle<String> name);
|
void BuildHoleCheckForVariableLoad(VariableMode mode, Handle<String> name);
|
||||||
void BuildHoleCheckForVariableAssignment(Variable* variable, Token::Value op);
|
void BuildHoleCheckForVariableAssignment(Variable* variable, Token::Value op);
|
||||||
|
|
||||||
|
@ -195,10 +195,9 @@ bool Bytecodes::IsConditionalJumpImmediate(Bytecode bytecode) {
|
|||||||
bytecode == Bytecode::kJumpIfFalse ||
|
bytecode == Bytecode::kJumpIfFalse ||
|
||||||
bytecode == Bytecode::kJumpIfToBooleanTrue ||
|
bytecode == Bytecode::kJumpIfToBooleanTrue ||
|
||||||
bytecode == Bytecode::kJumpIfToBooleanFalse ||
|
bytecode == Bytecode::kJumpIfToBooleanFalse ||
|
||||||
|
bytecode == Bytecode::kJumpIfNotHole ||
|
||||||
bytecode == Bytecode::kJumpIfNull ||
|
bytecode == Bytecode::kJumpIfNull ||
|
||||||
bytecode == Bytecode::kJumpIfUndefined ||
|
bytecode == Bytecode::kJumpIfUndefined;
|
||||||
bytecode == Bytecode::kJumpIfHole ||
|
|
||||||
bytecode == Bytecode::kJumpIfNotHole;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -208,6 +207,7 @@ bool Bytecodes::IsConditionalJumpConstant(Bytecode bytecode) {
|
|||||||
bytecode == Bytecode::kJumpIfFalseConstant ||
|
bytecode == Bytecode::kJumpIfFalseConstant ||
|
||||||
bytecode == Bytecode::kJumpIfToBooleanTrueConstant ||
|
bytecode == Bytecode::kJumpIfToBooleanTrueConstant ||
|
||||||
bytecode == Bytecode::kJumpIfToBooleanFalseConstant ||
|
bytecode == Bytecode::kJumpIfToBooleanFalseConstant ||
|
||||||
|
bytecode == Bytecode::kJumpIfNotHoleConstant ||
|
||||||
bytecode == Bytecode::kJumpIfNullConstant ||
|
bytecode == Bytecode::kJumpIfNullConstant ||
|
||||||
bytecode == Bytecode::kJumpIfUndefinedConstant;
|
bytecode == Bytecode::kJumpIfUndefinedConstant;
|
||||||
}
|
}
|
||||||
@ -219,6 +219,7 @@ bool Bytecodes::IsConditionalJumpConstantWide(Bytecode bytecode) {
|
|||||||
bytecode == Bytecode::kJumpIfFalseConstantWide ||
|
bytecode == Bytecode::kJumpIfFalseConstantWide ||
|
||||||
bytecode == Bytecode::kJumpIfToBooleanTrueConstantWide ||
|
bytecode == Bytecode::kJumpIfToBooleanTrueConstantWide ||
|
||||||
bytecode == Bytecode::kJumpIfToBooleanFalseConstantWide ||
|
bytecode == Bytecode::kJumpIfToBooleanFalseConstantWide ||
|
||||||
|
bytecode == Bytecode::kJumpIfNotHoleConstantWide ||
|
||||||
bytecode == Bytecode::kJumpIfNullConstantWide ||
|
bytecode == Bytecode::kJumpIfNullConstantWide ||
|
||||||
bytecode == Bytecode::kJumpIfUndefinedConstantWide;
|
bytecode == Bytecode::kJumpIfUndefinedConstantWide;
|
||||||
}
|
}
|
||||||
|
@ -248,9 +248,9 @@ namespace interpreter {
|
|||||||
V(JumpIfUndefined, OperandType::kImm8) \
|
V(JumpIfUndefined, OperandType::kImm8) \
|
||||||
V(JumpIfUndefinedConstant, OperandType::kIdx8) \
|
V(JumpIfUndefinedConstant, OperandType::kIdx8) \
|
||||||
V(JumpIfUndefinedConstantWide, OperandType::kIdx16) \
|
V(JumpIfUndefinedConstantWide, OperandType::kIdx16) \
|
||||||
/* TODO(mythria): Replace with opcodes that throw on a hole */ \
|
|
||||||
V(JumpIfHole, OperandType::kImm8) \
|
|
||||||
V(JumpIfNotHole, OperandType::kImm8) \
|
V(JumpIfNotHole, OperandType::kImm8) \
|
||||||
|
V(JumpIfNotHoleConstant, OperandType::kIdx8) \
|
||||||
|
V(JumpIfNotHoleConstantWide, OperandType::kIdx16) \
|
||||||
\
|
\
|
||||||
/* Complex flow control For..in */ \
|
/* Complex flow control For..in */ \
|
||||||
V(ForInPrepare, OperandType::kRegOutTriple8) \
|
V(ForInPrepare, OperandType::kRegOutTriple8) \
|
||||||
|
@ -1580,21 +1580,10 @@ void Interpreter::DoJumpIfUndefinedConstantWide(
|
|||||||
DoJumpIfUndefinedConstant(assembler);
|
DoJumpIfUndefinedConstant(assembler);
|
||||||
}
|
}
|
||||||
|
|
||||||
// JumpIfHole <imm8>
|
|
||||||
//
|
|
||||||
// Jump by number of bytes represented by an immediate operand if the object
|
|
||||||
// referenced by the accumulator is the hole.
|
|
||||||
void Interpreter::DoJumpIfHole(InterpreterAssembler* assembler) {
|
|
||||||
Node* accumulator = __ GetAccumulator();
|
|
||||||
Node* the_hole_value = __ HeapConstant(isolate_->factory()->the_hole_value());
|
|
||||||
Node* relative_jump = __ BytecodeOperandImm(0);
|
|
||||||
__ JumpIfWordEqual(accumulator, the_hole_value, relative_jump);
|
|
||||||
}
|
|
||||||
|
|
||||||
// JumpIfNotHole <imm8>
|
// JumpIfNotHole <imm8>
|
||||||
//
|
//
|
||||||
// Jump by number of bytes represented by an immediate operand if the object
|
// Jump by number of bytes represented by an immediate operand if the object
|
||||||
// referenced by the accumulator is not the hole.
|
// referenced by the accumulator is the hole.
|
||||||
void Interpreter::DoJumpIfNotHole(InterpreterAssembler* assembler) {
|
void Interpreter::DoJumpIfNotHole(InterpreterAssembler* assembler) {
|
||||||
Node* accumulator = __ GetAccumulator();
|
Node* accumulator = __ GetAccumulator();
|
||||||
Node* the_hole_value = __ HeapConstant(isolate_->factory()->the_hole_value());
|
Node* the_hole_value = __ HeapConstant(isolate_->factory()->the_hole_value());
|
||||||
@ -1602,6 +1591,27 @@ void Interpreter::DoJumpIfNotHole(InterpreterAssembler* assembler) {
|
|||||||
__ JumpIfWordNotEqual(accumulator, the_hole_value, relative_jump);
|
__ JumpIfWordNotEqual(accumulator, the_hole_value, relative_jump);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// JumpIfNotHoleConstant <idx8>
|
||||||
|
//
|
||||||
|
// Jump by number of bytes in the Smi in the |idx8| entry in the constant pool
|
||||||
|
// if the object referenced by the accumulator is the hole constant.
|
||||||
|
void Interpreter::DoJumpIfNotHoleConstant(InterpreterAssembler* assembler) {
|
||||||
|
Node* accumulator = __ GetAccumulator();
|
||||||
|
Node* the_hole_value = __ HeapConstant(isolate_->factory()->the_hole_value());
|
||||||
|
Node* index = __ BytecodeOperandIdx(0);
|
||||||
|
Node* constant = __ LoadConstantPoolEntry(index);
|
||||||
|
Node* relative_jump = __ SmiUntag(constant);
|
||||||
|
__ JumpIfWordNotEqual(accumulator, the_hole_value, relative_jump);
|
||||||
|
}
|
||||||
|
|
||||||
|
// JumpIfNotHoleConstantWide <idx16>
|
||||||
|
//
|
||||||
|
// Jump by number of bytes in the Smi in the |idx16| entry in the constant pool
|
||||||
|
// if the object referenced by the accumulator is the hole constant.
|
||||||
|
void Interpreter::DoJumpIfNotHoleConstantWide(InterpreterAssembler* assembler) {
|
||||||
|
DoJumpIfNotHoleConstant(assembler);
|
||||||
|
}
|
||||||
|
|
||||||
void Interpreter::DoCreateLiteral(Runtime::FunctionId function_id,
|
void Interpreter::DoCreateLiteral(Runtime::FunctionId function_id,
|
||||||
InterpreterAssembler* assembler) {
|
InterpreterAssembler* assembler) {
|
||||||
Node* index = __ BytecodeOperandIdx(0);
|
Node* index = __ BytecodeOperandIdx(0);
|
||||||
|
@ -878,10 +878,6 @@
|
|||||||
# BytecodeGenerator::VisitFunctionLiteral - !shared_info.is_null().
|
# BytecodeGenerator::VisitFunctionLiteral - !shared_info.is_null().
|
||||||
'regress/regress-crbug-429159': [FAIL],
|
'regress/regress-crbug-429159': [FAIL],
|
||||||
|
|
||||||
# TODO(rmcilroy,4680): Hits unreachable in
|
|
||||||
# BytecodeArrayBuilder::GetJumpWithConstantWideOperand().
|
|
||||||
'regress/regress-455207': [FAIL],
|
|
||||||
|
|
||||||
# TODO(rmcilroy,4680): Check failed: osr_normal_entry.
|
# TODO(rmcilroy,4680): Check failed: osr_normal_entry.
|
||||||
'regress/regress-123919': [FAIL],
|
'regress/regress-123919': [FAIL],
|
||||||
|
|
||||||
|
@ -163,8 +163,8 @@ TEST_F(BytecodeArrayBuilderTest, AllBytecodesGenerated) {
|
|||||||
builder.Jump(&start)
|
builder.Jump(&start)
|
||||||
.JumpIfNull(&start)
|
.JumpIfNull(&start)
|
||||||
.JumpIfUndefined(&start)
|
.JumpIfUndefined(&start)
|
||||||
.JumpIfHole(&start)
|
|
||||||
.JumpIfNotHole(&start);
|
.JumpIfNotHole(&start);
|
||||||
|
|
||||||
// Perform an operation that returns boolean value to
|
// Perform an operation that returns boolean value to
|
||||||
// generate JumpIfTrue/False
|
// generate JumpIfTrue/False
|
||||||
builder.CompareOperation(Token::Value::EQ, reg, Strength::WEAK)
|
builder.CompareOperation(Token::Value::EQ, reg, Strength::WEAK)
|
||||||
@ -182,7 +182,8 @@ TEST_F(BytecodeArrayBuilderTest, AllBytecodesGenerated) {
|
|||||||
builder.LoadTrue();
|
builder.LoadTrue();
|
||||||
}
|
}
|
||||||
// Longer jumps requiring Constant operand
|
// Longer jumps requiring Constant operand
|
||||||
builder.Jump(&start).JumpIfNull(&start).JumpIfUndefined(&start);
|
builder.Jump(&start).JumpIfNull(&start).JumpIfUndefined(&start).JumpIfNotHole(
|
||||||
|
&start);
|
||||||
// Perform an operation that returns boolean value to
|
// Perform an operation that returns boolean value to
|
||||||
// generate JumpIfTrue/False
|
// generate JumpIfTrue/False
|
||||||
builder.CompareOperation(Token::Value::EQ, reg, Strength::WEAK)
|
builder.CompareOperation(Token::Value::EQ, reg, Strength::WEAK)
|
||||||
@ -265,7 +266,8 @@ TEST_F(BytecodeArrayBuilderTest, AllBytecodesGenerated) {
|
|||||||
.CreateObjectLiteral(factory->NewFixedArray(2), 0, 0);
|
.CreateObjectLiteral(factory->NewFixedArray(2), 0, 0);
|
||||||
|
|
||||||
// Longer jumps requiring ConstantWide operand
|
// Longer jumps requiring ConstantWide operand
|
||||||
builder.Jump(&start).JumpIfNull(&start).JumpIfUndefined(&start);
|
builder.Jump(&start).JumpIfNull(&start).JumpIfUndefined(&start).JumpIfNotHole(
|
||||||
|
&start);
|
||||||
// Perform an operation that returns boolean value to
|
// Perform an operation that returns boolean value to
|
||||||
// generate JumpIfTrue/False
|
// generate JumpIfTrue/False
|
||||||
builder.CompareOperation(Token::Value::EQ, reg, Strength::WEAK)
|
builder.CompareOperation(Token::Value::EQ, reg, Strength::WEAK)
|
||||||
|
Loading…
Reference in New Issue
Block a user