[Interpreter / TurboFan] Add TestTypeof bytecode.
Adds a TestTypeof bytecode to deal with comparisons of the form: typeof(object) === 'string'; Also adds support to Turbofan to perform these comparisons without inserting checkpoints. BUG=v8:4280,v8:5267 Change-Id: Ib5cc1c6816dfe70a4120838d8eada2fc0267750f Reviewed-on: https://chromium-review.googlesource.com/454837 Reviewed-by: Mythri Alle <mythria@chromium.org> Reviewed-by: Benedikt Meurer <bmeurer@chromium.org> Commit-Queue: Ross McIlroy <rmcilroy@chromium.org> Cr-Commit-Position: refs/heads/master@{#43832}
This commit is contained in:
parent
8692e7b86b
commit
3db32e064f
@ -310,6 +310,7 @@ class AstValue : public ZoneObject {
|
||||
F(arguments, "arguments") \
|
||||
F(async, "async") \
|
||||
F(await, "await") \
|
||||
F(boolean, "boolean") \
|
||||
F(constructor, "constructor") \
|
||||
F(default, "default") \
|
||||
F(done, "done") \
|
||||
@ -330,11 +331,15 @@ class AstValue : public ZoneObject {
|
||||
F(native, "native") \
|
||||
F(new_target, ".new.target") \
|
||||
F(next, "next") \
|
||||
F(number, "number") \
|
||||
F(object, "object") \
|
||||
F(proto, "__proto__") \
|
||||
F(prototype, "prototype") \
|
||||
F(return, "return") \
|
||||
F(set_space, "set ") \
|
||||
F(star_default_star, "*default*") \
|
||||
F(string, "string") \
|
||||
F(symbol, "symbol") \
|
||||
F(this, "this") \
|
||||
F(this_function, ".this_function") \
|
||||
F(throw, "throw") \
|
||||
|
@ -905,24 +905,21 @@ void CompareOperation::AssignFeedbackSlots(FeedbackVectorSpec* spec,
|
||||
}
|
||||
|
||||
// Check for the pattern: typeof <expression> equals <string literal>.
|
||||
static bool MatchLiteralCompareTypeof(Expression* left,
|
||||
Token::Value op,
|
||||
Expression* right,
|
||||
Expression** expr,
|
||||
Handle<String>* check) {
|
||||
static bool MatchLiteralCompareTypeof(Expression* left, Token::Value op,
|
||||
Expression* right, Expression** expr,
|
||||
Literal** literal) {
|
||||
if (IsTypeof(left) && right->IsStringLiteral() && Token::IsEqualityOp(op)) {
|
||||
*expr = left->AsUnaryOperation()->expression();
|
||||
*check = Handle<String>::cast(right->AsLiteral()->value());
|
||||
*literal = right->AsLiteral();
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
bool CompareOperation::IsLiteralCompareTypeof(Expression** expr,
|
||||
Handle<String>* check) {
|
||||
return MatchLiteralCompareTypeof(left_, op(), right_, expr, check) ||
|
||||
MatchLiteralCompareTypeof(right_, op(), left_, expr, check);
|
||||
Literal** literal) {
|
||||
return MatchLiteralCompareTypeof(left_, op(), right_, expr, literal) ||
|
||||
MatchLiteralCompareTypeof(right_, op(), left_, expr, literal);
|
||||
}
|
||||
|
||||
|
||||
|
@ -2275,7 +2275,7 @@ class CompareOperation final : public Expression {
|
||||
FeedbackSlot CompareOperationFeedbackSlot() const { return feedback_slot_; }
|
||||
|
||||
// Match special cases.
|
||||
bool IsLiteralCompareTypeof(Expression** expr, Handle<String>* check);
|
||||
bool IsLiteralCompareTypeof(Expression** expr, Literal** literal);
|
||||
bool IsLiteralCompareUndefined(Expression** expr);
|
||||
bool IsLiteralCompareNull(Expression** expr);
|
||||
|
||||
|
@ -237,6 +237,8 @@ namespace internal {
|
||||
V(kUnexpectedStackDepth, "Unexpected operand stack depth in full-codegen") \
|
||||
V(kUnexpectedStackPointer, "The stack pointer is not the expected value") \
|
||||
V(kUnexpectedStringType, "Unexpected string type") \
|
||||
V(kUnexpectedTestTypeofLiteralFlag, \
|
||||
"Unexpected literal flag for TestTypeof bytecode") \
|
||||
V(kUnexpectedTypeForRegExpDataFixedArrayExpected, \
|
||||
"Unexpected type for RegExp data, FixedArray expected") \
|
||||
V(kUnexpectedValue, "Unexpected value") \
|
||||
|
@ -1972,9 +1972,10 @@ void AstGraphBuilder::VisitCompareOperation(CompareOperation* expr) {
|
||||
// with the full codegen: We don't push both left and right values onto
|
||||
// the expression stack when one side is a special-case literal.
|
||||
Expression* sub_expr = nullptr;
|
||||
Handle<String> check;
|
||||
if (expr->IsLiteralCompareTypeof(&sub_expr, &check)) {
|
||||
return VisitLiteralCompareTypeof(expr, sub_expr, check);
|
||||
Literal* literal;
|
||||
if (expr->IsLiteralCompareTypeof(&sub_expr, &literal)) {
|
||||
return VisitLiteralCompareTypeof(expr, sub_expr,
|
||||
Handle<String>::cast(literal->value()));
|
||||
}
|
||||
if (expr->IsLiteralCompareUndefined(&sub_expr)) {
|
||||
return VisitLiteralCompareNil(expr, sub_expr,
|
||||
|
@ -7,6 +7,7 @@
|
||||
#include "src/ast/ast.h"
|
||||
#include "src/ast/scopes.h"
|
||||
#include "src/compilation-info.h"
|
||||
#include "src/compiler/access-builder.h"
|
||||
#include "src/compiler/compiler-source-position-table.h"
|
||||
#include "src/compiler/js-type-hint-lowering.h"
|
||||
#include "src/compiler/linkage.h"
|
||||
@ -1924,6 +1925,57 @@ void BytecodeGraphBuilder::VisitTestUndefined() {
|
||||
environment()->BindAccumulator(result);
|
||||
}
|
||||
|
||||
void BytecodeGraphBuilder::VisitTestTypeOf() {
|
||||
Node* object = environment()->LookupAccumulator();
|
||||
auto literal_flag = interpreter::TestTypeOfFlags::Decode(
|
||||
bytecode_iterator().GetFlagOperand(0));
|
||||
Node* result;
|
||||
switch (literal_flag) {
|
||||
case interpreter::TestTypeOfFlags::LiteralFlag::kNumber:
|
||||
result = NewNode(simplified()->ObjectIsNumber(), object);
|
||||
break;
|
||||
case interpreter::TestTypeOfFlags::LiteralFlag::kString:
|
||||
result = NewNode(simplified()->ObjectIsString(), object);
|
||||
break;
|
||||
case interpreter::TestTypeOfFlags::LiteralFlag::kSymbol:
|
||||
result = NewNode(simplified()->ObjectIsSymbol(), object);
|
||||
break;
|
||||
case interpreter::TestTypeOfFlags::LiteralFlag::kBoolean:
|
||||
result = NewNode(common()->Select(MachineRepresentation::kTagged),
|
||||
NewNode(simplified()->ReferenceEqual(), object,
|
||||
jsgraph()->TrueConstant()),
|
||||
jsgraph()->TrueConstant(),
|
||||
NewNode(simplified()->ReferenceEqual(), object,
|
||||
jsgraph()->FalseConstant()));
|
||||
break;
|
||||
case interpreter::TestTypeOfFlags::LiteralFlag::kUndefined:
|
||||
result = graph()->NewNode(
|
||||
common()->Select(MachineRepresentation::kTagged),
|
||||
graph()->NewNode(simplified()->ReferenceEqual(), object,
|
||||
jsgraph()->NullConstant()),
|
||||
jsgraph()->FalseConstant(),
|
||||
graph()->NewNode(simplified()->ObjectIsUndetectable(), object));
|
||||
break;
|
||||
case interpreter::TestTypeOfFlags::LiteralFlag::kFunction:
|
||||
result =
|
||||
graph()->NewNode(simplified()->ObjectIsDetectableCallable(), object);
|
||||
break;
|
||||
case interpreter::TestTypeOfFlags::LiteralFlag::kObject:
|
||||
result = graph()->NewNode(
|
||||
common()->Select(MachineRepresentation::kTagged),
|
||||
graph()->NewNode(simplified()->ObjectIsNonCallable(), object),
|
||||
jsgraph()->TrueConstant(),
|
||||
graph()->NewNode(simplified()->ReferenceEqual(), object,
|
||||
jsgraph()->NullConstant()));
|
||||
break;
|
||||
case interpreter::TestTypeOfFlags::LiteralFlag::kOther:
|
||||
UNREACHABLE(); // Should never be emitted.
|
||||
result = nullptr;
|
||||
break;
|
||||
}
|
||||
environment()->BindAccumulator(result);
|
||||
}
|
||||
|
||||
void BytecodeGraphBuilder::BuildCastOperator(const Operator* js_op) {
|
||||
Node* value = NewNode(js_op, environment()->LookupAccumulator());
|
||||
environment()->BindRegister(bytecode_iterator().GetRegisterOperand(0), value,
|
||||
|
@ -11200,9 +11200,10 @@ void HOptimizedGraphBuilder::VisitCompareOperation(CompareOperation* expr) {
|
||||
// with the full codegen: We don't push both left and right values onto
|
||||
// the expression stack when one side is a special-case literal.
|
||||
Expression* sub_expr = NULL;
|
||||
Handle<String> check;
|
||||
if (expr->IsLiteralCompareTypeof(&sub_expr, &check)) {
|
||||
return HandleLiteralCompareTypeof(expr, sub_expr, check);
|
||||
Literal* literal;
|
||||
if (expr->IsLiteralCompareTypeof(&sub_expr, &literal)) {
|
||||
return HandleLiteralCompareTypeof(expr, sub_expr,
|
||||
Handle<String>::cast(literal->value()));
|
||||
}
|
||||
if (expr->IsLiteralCompareUndefined(&sub_expr)) {
|
||||
return HandleLiteralCompareNil(expr, sub_expr, kUndefinedValue);
|
||||
|
@ -1445,10 +1445,11 @@ void FullCodeGenerator::VisitRewritableExpression(RewritableExpression* expr) {
|
||||
|
||||
bool FullCodeGenerator::TryLiteralCompare(CompareOperation* expr) {
|
||||
Expression* sub_expr;
|
||||
Handle<String> check;
|
||||
if (expr->IsLiteralCompareTypeof(&sub_expr, &check)) {
|
||||
Literal* literal;
|
||||
if (expr->IsLiteralCompareTypeof(&sub_expr, &literal)) {
|
||||
SetExpressionPosition(expr);
|
||||
EmitLiteralCompareTypeof(expr, sub_expr, check);
|
||||
EmitLiteralCompareTypeof(expr, sub_expr,
|
||||
Handle<String>::cast(literal->value()));
|
||||
return true;
|
||||
}
|
||||
|
||||
|
@ -364,6 +364,13 @@ BytecodeArrayBuilder& BytecodeArrayBuilder::CompareOperation(
|
||||
return *this;
|
||||
}
|
||||
|
||||
BytecodeArrayBuilder& BytecodeArrayBuilder::CompareTypeOf(
|
||||
TestTypeOfFlags::LiteralFlag literal_flag) {
|
||||
DCHECK(literal_flag != TestTypeOfFlags::LiteralFlag::kOther);
|
||||
OutputTestTypeOf(TestTypeOfFlags::Encode(literal_flag));
|
||||
return *this;
|
||||
}
|
||||
|
||||
BytecodeArrayBuilder& BytecodeArrayBuilder::LoadConstantPoolEntry(
|
||||
size_t entry) {
|
||||
OutputLdaConstant(entry);
|
||||
|
@ -9,6 +9,7 @@
|
||||
#include "src/base/compiler-specific.h"
|
||||
#include "src/globals.h"
|
||||
#include "src/interpreter/bytecode-array-writer.h"
|
||||
#include "src/interpreter/bytecode-flags.h"
|
||||
#include "src/interpreter/bytecode-register-allocator.h"
|
||||
#include "src/interpreter/bytecode-register.h"
|
||||
#include "src/interpreter/bytecodes.h"
|
||||
@ -306,6 +307,8 @@ class V8_EXPORT_PRIVATE BytecodeArrayBuilder final
|
||||
// Tests.
|
||||
BytecodeArrayBuilder& CompareOperation(Token::Value op, Register reg,
|
||||
int feedback_slot = kNoFeedbackSlot);
|
||||
BytecodeArrayBuilder& CompareTypeOf(
|
||||
TestTypeOfFlags::LiteralFlag literal_flag);
|
||||
|
||||
// Converts accumulator and stores result in register |out|.
|
||||
BytecodeArrayBuilder& ConvertAccumulatorToObject(Register out);
|
||||
|
@ -4,6 +4,8 @@
|
||||
|
||||
#include "src/interpreter/bytecode-flags.h"
|
||||
|
||||
#include "src/ast/ast-value-factory.h"
|
||||
#include "src/ast/ast.h"
|
||||
#include "src/builtins/builtins-constructor.h"
|
||||
#include "src/code-stubs.h"
|
||||
#include "src/objects-inl.h"
|
||||
@ -48,6 +50,40 @@ uint8_t CreateClosureFlags::Encode(bool pretenure, bool is_function_scope) {
|
||||
return result;
|
||||
}
|
||||
|
||||
// static
|
||||
TestTypeOfFlags::LiteralFlag TestTypeOfFlags::GetFlagForLiteral(
|
||||
const AstStringConstants* ast_constants, Literal* literal) {
|
||||
const AstRawString* raw_literal = literal->raw_value()->AsString();
|
||||
if (raw_literal == ast_constants->number_string()) {
|
||||
return LiteralFlag::kNumber;
|
||||
} else if (raw_literal == ast_constants->string_string()) {
|
||||
return LiteralFlag::kString;
|
||||
} else if (raw_literal == ast_constants->symbol_string()) {
|
||||
return LiteralFlag::kSymbol;
|
||||
} else if (raw_literal == ast_constants->boolean_string()) {
|
||||
return LiteralFlag::kBoolean;
|
||||
} else if (raw_literal == ast_constants->undefined_string()) {
|
||||
return LiteralFlag::kUndefined;
|
||||
} else if (raw_literal == ast_constants->function_string()) {
|
||||
return LiteralFlag::kFunction;
|
||||
} else if (raw_literal == ast_constants->object_string()) {
|
||||
return LiteralFlag::kObject;
|
||||
} else {
|
||||
return LiteralFlag::kOther;
|
||||
}
|
||||
}
|
||||
|
||||
// static
|
||||
uint8_t TestTypeOfFlags::Encode(LiteralFlag literal_flag) {
|
||||
return static_cast<uint8_t>(literal_flag);
|
||||
}
|
||||
|
||||
// static
|
||||
TestTypeOfFlags::LiteralFlag TestTypeOfFlags::Decode(uint8_t raw_flag) {
|
||||
DCHECK_LE(raw_flag, static_cast<uint8_t>(LiteralFlag::kOther));
|
||||
return static_cast<LiteralFlag>(raw_flag);
|
||||
}
|
||||
|
||||
} // namespace interpreter
|
||||
} // namespace internal
|
||||
} // namespace v8
|
||||
|
@ -9,6 +9,11 @@
|
||||
|
||||
namespace v8 {
|
||||
namespace internal {
|
||||
|
||||
// Forward declarations.
|
||||
class Literal;
|
||||
class AstStringConstants;
|
||||
|
||||
namespace interpreter {
|
||||
|
||||
class CreateArrayLiteralFlags {
|
||||
@ -46,6 +51,33 @@ class CreateClosureFlags {
|
||||
DISALLOW_IMPLICIT_CONSTRUCTORS(CreateClosureFlags);
|
||||
};
|
||||
|
||||
#define TYPEOF_LITERAL_LIST(V) \
|
||||
V(Number, number) \
|
||||
V(String, string) \
|
||||
V(Symbol, symbol) \
|
||||
V(Boolean, boolean) \
|
||||
V(Undefined, undefined) \
|
||||
V(Function, function) \
|
||||
V(Object, object) \
|
||||
V(Other, other)
|
||||
|
||||
class TestTypeOfFlags {
|
||||
public:
|
||||
enum class LiteralFlag : uint8_t {
|
||||
#define DECLARE_LITERAL_FLAG(name, _) k##name,
|
||||
TYPEOF_LITERAL_LIST(DECLARE_LITERAL_FLAG)
|
||||
#undef DECLARE_LITERAL_FLAG
|
||||
};
|
||||
|
||||
static LiteralFlag GetFlagForLiteral(const AstStringConstants* ast_constants,
|
||||
Literal* literal);
|
||||
static uint8_t Encode(LiteralFlag literal_flag);
|
||||
static LiteralFlag Decode(uint8_t raw_flag);
|
||||
|
||||
private:
|
||||
DISALLOW_IMPLICIT_CONSTRUCTORS(TestTypeOfFlags);
|
||||
};
|
||||
|
||||
} // namespace interpreter
|
||||
} // namespace internal
|
||||
} // namespace v8
|
||||
|
@ -621,6 +621,7 @@ BytecodeGenerator::BytecodeGenerator(CompilationInfo* info)
|
||||
info->scope()->num_stack_slots(), info->literal(),
|
||||
info->SourcePositionRecordingMode())),
|
||||
info_(info),
|
||||
ast_string_constants_(info->isolate()->ast_string_constants()),
|
||||
closure_scope_(info->scope()),
|
||||
current_scope_(info->scope()),
|
||||
globals_builder_(new (zone()) GlobalDeclarationsBuilder(info->zone())),
|
||||
@ -634,11 +635,7 @@ BytecodeGenerator::BytecodeGenerator(CompilationInfo* info)
|
||||
execution_result_(nullptr),
|
||||
generator_resume_points_(info->literal()->yield_count(), info->zone()),
|
||||
generator_state_(),
|
||||
loop_depth_(0),
|
||||
prototype_string_(
|
||||
info->isolate()->ast_string_constants()->prototype_string()),
|
||||
undefined_string_(
|
||||
info->isolate()->ast_string_constants()->undefined_string()) {
|
||||
loop_depth_(0) {
|
||||
DCHECK_EQ(closure_scope(), closure_scope()->GetClosureScope());
|
||||
}
|
||||
|
||||
@ -1556,7 +1553,7 @@ void BytecodeGenerator::VisitClassLiteralProperties(ClassLiteral* expr,
|
||||
// do not need to do this for every property.
|
||||
BytecodeLabel done;
|
||||
builder()
|
||||
->LoadLiteral(prototype_string())
|
||||
->LoadLiteral(ast_string_constants()->prototype_string())
|
||||
.CompareOperation(Token::Value::EQ_STRICT, key)
|
||||
.JumpIfFalse(&done)
|
||||
.CallRuntime(Runtime::kThrowStaticPrototypeError)
|
||||
@ -1945,7 +1942,7 @@ void BytecodeGenerator::BuildVariableLoad(Variable* variable, FeedbackSlot slot,
|
||||
// The global identifier "undefined" is immutable. Everything
|
||||
// else could be reassigned. For performance, we do a pointer comparison
|
||||
// rather than checking if the raw_name is really "undefined".
|
||||
if (variable->raw_name() == undefined_string()) {
|
||||
if (variable->raw_name() == ast_string_constants()->undefined_string()) {
|
||||
builder()->LoadUndefined();
|
||||
} else {
|
||||
builder()->LoadGlobal(variable->raw_name(), feedback_index(slot),
|
||||
@ -2710,17 +2707,21 @@ void BytecodeGenerator::VisitVoid(UnaryOperation* expr) {
|
||||
builder()->LoadUndefined();
|
||||
}
|
||||
|
||||
void BytecodeGenerator::VisitTypeOf(UnaryOperation* expr) {
|
||||
if (expr->expression()->IsVariableProxy()) {
|
||||
void BytecodeGenerator::VisitForTypeOfValue(Expression* expr) {
|
||||
if (expr->IsVariableProxy()) {
|
||||
// Typeof does not throw a reference error on global variables, hence we
|
||||
// perform a non-contextual load in case the operand is a variable proxy.
|
||||
VariableProxy* proxy = expr->expression()->AsVariableProxy();
|
||||
VariableProxy* proxy = expr->AsVariableProxy();
|
||||
BuildVariableLoadForAccumulatorValue(
|
||||
proxy->var(), proxy->VariableFeedbackSlot(), proxy->hole_check_mode(),
|
||||
INSIDE_TYPEOF);
|
||||
} else {
|
||||
VisitForAccumulatorValue(expr->expression());
|
||||
VisitForAccumulatorValue(expr);
|
||||
}
|
||||
}
|
||||
|
||||
void BytecodeGenerator::VisitTypeOf(UnaryOperation* expr) {
|
||||
VisitForTypeOfValue(expr->expression());
|
||||
builder()->TypeOf();
|
||||
}
|
||||
|
||||
@ -2963,11 +2964,27 @@ void BytecodeGenerator::VisitBinaryOperation(BinaryOperation* binop) {
|
||||
}
|
||||
|
||||
void BytecodeGenerator::VisitCompareOperation(CompareOperation* expr) {
|
||||
Register lhs = VisitForRegisterValue(expr->left());
|
||||
VisitForAccumulatorValue(expr->right());
|
||||
builder()->SetExpressionPosition(expr);
|
||||
FeedbackSlot slot = expr->CompareOperationFeedbackSlot();
|
||||
builder()->CompareOperation(expr->op(), lhs, feedback_index(slot));
|
||||
// Emit a fast literal comparion for expressions of the form:
|
||||
// typeof(x) === 'string'.
|
||||
Expression* typeof_sub_expr;
|
||||
Literal* literal;
|
||||
if (expr->IsLiteralCompareTypeof(&typeof_sub_expr, &literal)) {
|
||||
VisitForTypeOfValue(typeof_sub_expr);
|
||||
builder()->SetExpressionPosition(expr);
|
||||
TestTypeOfFlags::LiteralFlag literal_flag =
|
||||
TestTypeOfFlags::GetFlagForLiteral(ast_string_constants(), literal);
|
||||
if (literal_flag == TestTypeOfFlags::LiteralFlag::kOther) {
|
||||
builder()->LoadFalse();
|
||||
} else {
|
||||
builder()->CompareTypeOf(literal_flag);
|
||||
}
|
||||
} else {
|
||||
Register lhs = VisitForRegisterValue(expr->left());
|
||||
VisitForAccumulatorValue(expr->right());
|
||||
builder()->SetExpressionPosition(expr);
|
||||
FeedbackSlot slot = expr->CompareOperationFeedbackSlot();
|
||||
builder()->CompareOperation(expr->op(), lhs, feedback_index(slot));
|
||||
}
|
||||
}
|
||||
|
||||
void BytecodeGenerator::VisitArithmeticExpression(BinaryOperation* expr) {
|
||||
|
@ -14,6 +14,7 @@
|
||||
namespace v8 {
|
||||
namespace internal {
|
||||
|
||||
class AstStringConstants;
|
||||
class CompilationInfo;
|
||||
|
||||
namespace interpreter {
|
||||
@ -71,6 +72,9 @@ class BytecodeGenerator final : public AstVisitor<BytecodeGenerator> {
|
||||
void VisitNot(UnaryOperation* expr);
|
||||
void VisitDelete(UnaryOperation* expr);
|
||||
|
||||
// Visits a typeof expression for the value on which to perform the typeof.
|
||||
void VisitForTypeOfValue(Expression* expr);
|
||||
|
||||
// Used by flow control routines to evaluate loop condition.
|
||||
void VisitCondition(Expression* expr);
|
||||
|
||||
@ -175,6 +179,9 @@ class BytecodeGenerator final : public AstVisitor<BytecodeGenerator> {
|
||||
inline Zone* zone() const { return zone_; }
|
||||
inline DeclarationScope* closure_scope() const { return closure_scope_; }
|
||||
inline CompilationInfo* info() const { return info_; }
|
||||
inline const AstStringConstants* ast_string_constants() const {
|
||||
return ast_string_constants_;
|
||||
}
|
||||
|
||||
inline Scope* current_scope() const { return current_scope_; }
|
||||
inline void set_current_scope(Scope* scope) { current_scope_ = scope; }
|
||||
@ -202,12 +209,10 @@ class BytecodeGenerator final : public AstVisitor<BytecodeGenerator> {
|
||||
inline LanguageMode language_mode() const;
|
||||
int feedback_index(FeedbackSlot slot) const;
|
||||
|
||||
const AstRawString* prototype_string() const { return prototype_string_; }
|
||||
const AstRawString* undefined_string() const { return undefined_string_; }
|
||||
|
||||
Zone* zone_;
|
||||
BytecodeArrayBuilder* builder_;
|
||||
CompilationInfo* info_;
|
||||
const AstStringConstants* ast_string_constants_;
|
||||
DeclarationScope* closure_scope_;
|
||||
Scope* current_scope_;
|
||||
|
||||
@ -226,9 +231,6 @@ class BytecodeGenerator final : public AstVisitor<BytecodeGenerator> {
|
||||
ZoneVector<BytecodeLabel> generator_resume_points_;
|
||||
Register generator_state_;
|
||||
int loop_depth_;
|
||||
|
||||
const AstRawString* prototype_string_;
|
||||
const AstRawString* undefined_string_;
|
||||
};
|
||||
|
||||
} // namespace interpreter
|
||||
|
@ -205,11 +205,10 @@ namespace interpreter {
|
||||
OperandType::kIdx) \
|
||||
V(TestInstanceOf, AccumulatorUse::kReadWrite, OperandType::kReg) \
|
||||
V(TestIn, AccumulatorUse::kReadWrite, OperandType::kReg) \
|
||||
\
|
||||
/* TestEqual with Null or Undefined */ \
|
||||
V(TestUndetectable, AccumulatorUse::kWrite, OperandType::kReg) \
|
||||
V(TestNull, AccumulatorUse::kWrite, OperandType::kReg) \
|
||||
V(TestUndefined, AccumulatorUse::kWrite, OperandType::kReg) \
|
||||
V(TestTypeOf, AccumulatorUse::kReadWrite, OperandType::kFlag8) \
|
||||
\
|
||||
/* Cast operators */ \
|
||||
V(ToName, AccumulatorUse::kRead, OperandType::kRegOut) \
|
||||
@ -506,6 +505,7 @@ class V8_EXPORT_PRIVATE Bytecodes final {
|
||||
case Bytecode::kTestInstanceOf:
|
||||
case Bytecode::kTestIn:
|
||||
case Bytecode::kTestUndetectable:
|
||||
case Bytecode::kTestTypeOf:
|
||||
case Bytecode::kForInContinue:
|
||||
case Bytecode::kTestUndefined:
|
||||
case Bytecode::kTestNull:
|
||||
|
@ -2584,6 +2584,126 @@ void Interpreter::DoTestUndefined(InterpreterAssembler* assembler) {
|
||||
__ Dispatch();
|
||||
}
|
||||
|
||||
// TestTypeOf <literal_flag>
|
||||
//
|
||||
// Tests if the object in the <accumulator> is typeof the literal represented
|
||||
// by |literal_flag|.
|
||||
void Interpreter::DoTestTypeOf(InterpreterAssembler* assembler) {
|
||||
Node* object = __ GetAccumulator();
|
||||
Node* literal_flag = __ BytecodeOperandFlag(0);
|
||||
|
||||
#define MAKE_LABEL(name, lower_case) Label if_##lower_case(assembler);
|
||||
TYPEOF_LITERAL_LIST(MAKE_LABEL)
|
||||
#undef MAKE_LABEL
|
||||
|
||||
#define LABEL_POINTER(name, lower_case) &if_##lower_case,
|
||||
Label* labels[] = {TYPEOF_LITERAL_LIST(LABEL_POINTER)};
|
||||
#undef LABEL_POINTER
|
||||
|
||||
#define CASE(name, lower_case) \
|
||||
static_cast<int32_t>(TestTypeOfFlags::LiteralFlag::k##name),
|
||||
int32_t cases[] = {TYPEOF_LITERAL_LIST(CASE)};
|
||||
#undef CASE
|
||||
|
||||
Label if_true(assembler), if_false(assembler), end(assembler),
|
||||
abort(assembler, Label::kDeferred);
|
||||
|
||||
__ Switch(literal_flag, &abort, cases, labels, arraysize(cases));
|
||||
|
||||
__ Bind(&abort);
|
||||
{
|
||||
__ Comment("Abort");
|
||||
__ Abort(BailoutReason::kUnexpectedTestTypeofLiteralFlag);
|
||||
__ Goto(&if_false);
|
||||
}
|
||||
__ Bind(&if_number);
|
||||
{
|
||||
__ Comment("IfNumber");
|
||||
__ GotoIfNumber(object, &if_true);
|
||||
__ Goto(&if_false);
|
||||
}
|
||||
__ Bind(&if_string);
|
||||
{
|
||||
__ Comment("IfString");
|
||||
__ GotoIf(__ TaggedIsSmi(object), &if_false);
|
||||
__ Branch(__ IsString(object), &if_true, &if_false);
|
||||
}
|
||||
__ Bind(&if_symbol);
|
||||
{
|
||||
__ Comment("IfSymbol");
|
||||
__ GotoIf(__ TaggedIsSmi(object), &if_false);
|
||||
__ Branch(__ IsSymbol(object), &if_true, &if_false);
|
||||
}
|
||||
__ Bind(&if_boolean);
|
||||
{
|
||||
__ Comment("IfBoolean");
|
||||
__ GotoIf(__ WordEqual(object, __ BooleanConstant(true)), &if_true);
|
||||
__ Branch(__ WordEqual(object, __ BooleanConstant(false)), &if_true,
|
||||
&if_false);
|
||||
}
|
||||
__ Bind(&if_undefined);
|
||||
{
|
||||
__ Comment("IfUndefined");
|
||||
__ GotoIf(__ TaggedIsSmi(object), &if_false);
|
||||
// Check it is not null and the map has the undetectable bit set.
|
||||
__ GotoIf(__ WordEqual(object, __ NullConstant()), &if_false);
|
||||
Node* map_bitfield = __ LoadMapBitField(__ LoadMap(object));
|
||||
Node* undetectable_bit =
|
||||
__ Word32And(map_bitfield, __ Int32Constant(1 << Map::kIsUndetectable));
|
||||
__ Branch(__ Word32Equal(undetectable_bit, __ Int32Constant(0)), &if_false,
|
||||
&if_true);
|
||||
}
|
||||
__ Bind(&if_function);
|
||||
{
|
||||
__ Comment("IfFunction");
|
||||
__ GotoIf(__ TaggedIsSmi(object), &if_false);
|
||||
// Check if callable bit is set and not undetectable.
|
||||
Node* map_bitfield = __ LoadMapBitField(__ LoadMap(object));
|
||||
Node* callable_undetectable = __ Word32And(
|
||||
map_bitfield,
|
||||
__ Int32Constant(1 << Map::kIsUndetectable | 1 << Map::kIsCallable));
|
||||
__ Branch(__ Word32Equal(callable_undetectable,
|
||||
__ Int32Constant(1 << Map::kIsCallable)),
|
||||
&if_true, &if_false);
|
||||
}
|
||||
__ Bind(&if_object);
|
||||
{
|
||||
__ Comment("IfObject");
|
||||
__ GotoIf(__ TaggedIsSmi(object), &if_false);
|
||||
|
||||
// If the object is null then return true.
|
||||
__ GotoIf(__ WordEqual(object, __ NullConstant()), &if_true);
|
||||
|
||||
// Check if the object is a receiver type and is not undefined or callable.
|
||||
Node* map = __ LoadMap(object);
|
||||
__ GotoIfNot(__ IsJSReceiverMap(map), &if_false);
|
||||
Node* map_bitfield = __ LoadMapBitField(map);
|
||||
Node* callable_undetectable = __ Word32And(
|
||||
map_bitfield,
|
||||
__ Int32Constant(1 << Map::kIsUndetectable | 1 << Map::kIsCallable));
|
||||
__ Branch(__ Word32Equal(callable_undetectable, __ Int32Constant(0)),
|
||||
&if_true, &if_false);
|
||||
}
|
||||
__ Bind(&if_other);
|
||||
{
|
||||
// Typeof doesn't return any other string value.
|
||||
__ Goto(&if_false);
|
||||
}
|
||||
|
||||
__ Bind(&if_false);
|
||||
{
|
||||
__ SetAccumulator(__ BooleanConstant(false));
|
||||
__ Goto(&end);
|
||||
}
|
||||
__ Bind(&if_true);
|
||||
{
|
||||
__ SetAccumulator(__ BooleanConstant(true));
|
||||
__ Goto(&end);
|
||||
}
|
||||
__ Bind(&end);
|
||||
__ Dispatch();
|
||||
}
|
||||
|
||||
// Jump <imm>
|
||||
//
|
||||
// Jump by number of bytes represented by the immediate operand |imm|.
|
||||
|
@ -827,6 +827,49 @@ TEST(BytecodeGraphBuilderTypeOf) {
|
||||
}
|
||||
}
|
||||
|
||||
TEST(BytecodeGraphBuilderCompareTypeOf) {
|
||||
HandleAndZoneScope scope;
|
||||
Isolate* isolate = scope.main_isolate();
|
||||
Factory* factory = isolate->factory();
|
||||
|
||||
ExpectedSnippet<1> snippets[] = {
|
||||
{"return typeof p1 === 'number';",
|
||||
{factory->true_value(), factory->NewNumber(1.1)}},
|
||||
{"return typeof p1 === 'string';",
|
||||
{factory->false_value(), factory->NewNumber(1.1)}},
|
||||
{"return typeof p1 === 'string';",
|
||||
{factory->true_value(), factory->NewStringFromStaticChars("string")}},
|
||||
{"return typeof p1 === 'string';",
|
||||
{factory->false_value(), factory->undefined_value()}},
|
||||
{"return typeof p1 === 'undefined';",
|
||||
{factory->true_value(), factory->undefined_value()}},
|
||||
{"return typeof p1 === 'object';",
|
||||
{factory->true_value(), factory->null_value()}},
|
||||
{"return typeof p1 === 'object';",
|
||||
{factory->true_value(), BytecodeGraphTester::NewObject("({val : 10})")}},
|
||||
{"return typeof p1 === 'function';",
|
||||
{factory->false_value(),
|
||||
BytecodeGraphTester::NewObject("({val : 10})")}},
|
||||
{"return typeof p1 === 'symbol';",
|
||||
{factory->true_value(), factory->NewSymbol()}},
|
||||
{"return typeof p1 === 'symbol';",
|
||||
{factory->false_value(), factory->NewStringFromStaticChars("string")}},
|
||||
{"return typeof p1 === 'other';",
|
||||
{factory->false_value(), factory->NewNumber(1.1)}},
|
||||
};
|
||||
|
||||
for (size_t i = 0; i < arraysize(snippets); i++) {
|
||||
ScopedVector<char> script(1024);
|
||||
SNPrintF(script, "function %s(p1) { %s }\n%s({});", kFunctionName,
|
||||
snippets[i].code_snippet, kFunctionName);
|
||||
|
||||
BytecodeGraphTester tester(isolate, script.start());
|
||||
auto callable = tester.GetCallable<Handle<Object>>();
|
||||
Handle<Object> return_value =
|
||||
callable(snippets[i].parameter(0)).ToHandleChecked();
|
||||
CHECK(return_value->SameValue(*snippets[i].return_value()));
|
||||
}
|
||||
}
|
||||
|
||||
TEST(BytecodeGraphBuilderCountOperation) {
|
||||
HandleAndZoneScope scope;
|
||||
|
@ -0,0 +1,97 @@
|
||||
#
|
||||
# Autogenerated by generate-bytecode-expectations.
|
||||
#
|
||||
|
||||
---
|
||||
wrap: yes
|
||||
|
||||
---
|
||||
snippet: "
|
||||
return typeof(1) === 'number';
|
||||
"
|
||||
frame size: 0
|
||||
parameter count: 1
|
||||
bytecode array length: 6
|
||||
bytecodes: [
|
||||
/* 30 E> */ B(StackCheck),
|
||||
/* 34 S> */ B(LdaSmi), I8(1),
|
||||
/* 51 E> */ B(TestTypeOf), U8(0),
|
||||
/* 65 S> */ B(Return),
|
||||
]
|
||||
constant pool: [
|
||||
]
|
||||
handlers: [
|
||||
]
|
||||
|
||||
---
|
||||
snippet: "
|
||||
return 'string' === typeof('foo');
|
||||
"
|
||||
frame size: 0
|
||||
parameter count: 1
|
||||
bytecode array length: 6
|
||||
bytecodes: [
|
||||
/* 30 E> */ B(StackCheck),
|
||||
/* 34 S> */ B(LdaConstant), U8(0),
|
||||
/* 50 E> */ B(TestTypeOf), U8(1),
|
||||
/* 69 S> */ B(Return),
|
||||
]
|
||||
constant pool: [
|
||||
ONE_BYTE_INTERNALIZED_STRING_TYPE ["foo"],
|
||||
]
|
||||
handlers: [
|
||||
]
|
||||
|
||||
---
|
||||
snippet: "
|
||||
return typeof(true) == 'boolean';
|
||||
"
|
||||
frame size: 0
|
||||
parameter count: 1
|
||||
bytecode array length: 5
|
||||
bytecodes: [
|
||||
/* 30 E> */ B(StackCheck),
|
||||
/* 34 S> */ B(LdaTrue),
|
||||
/* 54 E> */ B(TestTypeOf), U8(3),
|
||||
/* 68 S> */ B(Return),
|
||||
]
|
||||
constant pool: [
|
||||
]
|
||||
handlers: [
|
||||
]
|
||||
|
||||
---
|
||||
snippet: "
|
||||
return 'string' === typeof(undefined);
|
||||
"
|
||||
frame size: 0
|
||||
parameter count: 1
|
||||
bytecode array length: 5
|
||||
bytecodes: [
|
||||
/* 30 E> */ B(StackCheck),
|
||||
/* 34 S> */ B(LdaUndefined),
|
||||
/* 50 E> */ B(TestTypeOf), U8(1),
|
||||
/* 73 S> */ B(Return),
|
||||
]
|
||||
constant pool: [
|
||||
]
|
||||
handlers: [
|
||||
]
|
||||
|
||||
---
|
||||
snippet: "
|
||||
return 'unknown' === typeof(undefined);
|
||||
"
|
||||
frame size: 0
|
||||
parameter count: 1
|
||||
bytecode array length: 3
|
||||
bytecodes: [
|
||||
/* 30 E> */ B(StackCheck),
|
||||
/* 34 S> */ B(LdaFalse),
|
||||
/* 74 S> */ B(Return),
|
||||
]
|
||||
constant pool: [
|
||||
]
|
||||
handlers: [
|
||||
]
|
||||
|
@ -16,7 +16,7 @@ snippet: "
|
||||
"
|
||||
frame size: 19
|
||||
parameter count: 1
|
||||
bytecode array length: 1052
|
||||
bytecode array length: 1046
|
||||
bytecodes: [
|
||||
B(Ldar), R(new_target),
|
||||
B(JumpIfUndefined), U8(42),
|
||||
@ -29,10 +29,10 @@ bytecodes: [
|
||||
B(JumpIfTrue), U8(134),
|
||||
B(LdaSmi), I8(1),
|
||||
B(TestEqualStrict), R(3), U8(0),
|
||||
B(JumpIfTrueConstant), U8(13),
|
||||
B(JumpIfTrueConstant), U8(12),
|
||||
B(LdaSmi), I8(2),
|
||||
B(TestEqualStrict), R(3), U8(0),
|
||||
B(JumpIfTrueConstant), U8(15),
|
||||
B(JumpIfTrueConstant), U8(14),
|
||||
B(LdaSmi), I8(78),
|
||||
B(Star), R(5),
|
||||
B(CallRuntime), U16(Runtime::kAbort), R(5), U8(1),
|
||||
@ -198,7 +198,7 @@ bytecodes: [
|
||||
B(Star), R(12),
|
||||
B(LdaZero),
|
||||
B(TestEqualStrict), R(12), U8(20),
|
||||
B(JumpIfTrueConstant), U8(17),
|
||||
B(JumpIfTrueConstant), U8(16),
|
||||
B(LdaContextSlot), R(1), U8(7), U8(0),
|
||||
B(Star), R(12),
|
||||
B(LdaNamedProperty), R(12), U8(10), U8(21),
|
||||
@ -207,22 +207,19 @@ bytecodes: [
|
||||
B(Star), R(12),
|
||||
B(TestUndetectable), R(12),
|
||||
B(JumpIfFalse), U8(4),
|
||||
B(JumpConstant), U8(16),
|
||||
B(JumpConstant), U8(15),
|
||||
B(LdaContextSlot), R(1), U8(9), U8(0),
|
||||
B(Star), R(12),
|
||||
B(LdaSmi), I8(1),
|
||||
B(TestEqualStrict), R(12), U8(24),
|
||||
B(JumpIfFalse), U8(186),
|
||||
B(JumpIfFalse), U8(180),
|
||||
B(LdaContextSlot), R(1), U8(13), U8(0),
|
||||
B(TypeOf),
|
||||
B(Star), R(12),
|
||||
B(LdaConstant), U8(11),
|
||||
B(TestEqualStrict), R(12), U8(25),
|
||||
B(TestTypeOf), U8(5),
|
||||
B(JumpIfFalse), U8(4),
|
||||
B(Jump), U8(18),
|
||||
B(Wide), B(LdaSmi), I16(130),
|
||||
B(Star), R(12),
|
||||
B(LdaConstant), U8(12),
|
||||
B(LdaConstant), U8(11),
|
||||
B(Star), R(13),
|
||||
B(CallRuntime), U16(Runtime::kNewTypeError), R(12), U8(2),
|
||||
B(Throw),
|
||||
@ -274,14 +271,14 @@ bytecodes: [
|
||||
B(Star), R(6),
|
||||
B(LdaZero),
|
||||
B(Star), R(5),
|
||||
B(JumpConstant), U8(19),
|
||||
B(JumpConstant), U8(18),
|
||||
B(Ldar), R(15),
|
||||
B(ReThrow),
|
||||
B(Ldar), R(15),
|
||||
B(Jump), U8(20),
|
||||
B(Star), R(13),
|
||||
B(Ldar), R(closure),
|
||||
B(CreateCatchContext), R(13), U8(8), U8(14),
|
||||
B(CreateCatchContext), R(13), U8(8), U8(13),
|
||||
B(Star), R(12),
|
||||
B(LdaTheHole),
|
||||
B(SetPendingMessage),
|
||||
@ -386,7 +383,7 @@ bytecodes: [
|
||||
B(Jump), U8(54),
|
||||
B(Star), R(9),
|
||||
B(Ldar), R(closure),
|
||||
B(CreateCatchContext), R(9), U8(8), U8(18),
|
||||
B(CreateCatchContext), R(9), U8(8), U8(17),
|
||||
B(Star), R(8),
|
||||
B(LdaTheHole),
|
||||
B(SetPendingMessage),
|
||||
@ -470,22 +467,21 @@ constant pool: [
|
||||
ONE_BYTE_INTERNALIZED_STRING_TYPE [".catch"],
|
||||
FIXED_ARRAY_TYPE,
|
||||
ONE_BYTE_INTERNALIZED_STRING_TYPE ["return"],
|
||||
ONE_BYTE_INTERNALIZED_STRING_TYPE ["function"],
|
||||
ONE_BYTE_INTERNALIZED_STRING_TYPE [""],
|
||||
Smi [569],
|
||||
Smi [563],
|
||||
FIXED_ARRAY_TYPE,
|
||||
Smi [711],
|
||||
Smi [356],
|
||||
Smi [382],
|
||||
Smi [705],
|
||||
Smi [350],
|
||||
Smi [376],
|
||||
FIXED_ARRAY_TYPE,
|
||||
Smi [320],
|
||||
]
|
||||
handlers: [
|
||||
[83, 959, 965],
|
||||
[86, 905, 907],
|
||||
[83, 953, 959],
|
||||
[86, 899, 901],
|
||||
[103, 429, 435],
|
||||
[106, 381, 383],
|
||||
[531, 658, 660],
|
||||
[525, 652, 654],
|
||||
]
|
||||
|
||||
---
|
||||
@ -497,7 +493,7 @@ snippet: "
|
||||
"
|
||||
frame size: 19
|
||||
parameter count: 1
|
||||
bytecode array length: 1112
|
||||
bytecode array length: 1106
|
||||
bytecodes: [
|
||||
B(Ldar), R(new_target),
|
||||
B(JumpIfUndefined), U8(42),
|
||||
@ -510,10 +506,10 @@ bytecodes: [
|
||||
B(JumpIfTrue), U8(134),
|
||||
B(LdaSmi), I8(1),
|
||||
B(TestEqualStrict), R(3), U8(0),
|
||||
B(JumpIfTrueConstant), U8(13),
|
||||
B(JumpIfTrueConstant), U8(12),
|
||||
B(LdaSmi), I8(2),
|
||||
B(TestEqualStrict), R(3), U8(0),
|
||||
B(JumpIfTrueConstant), U8(15),
|
||||
B(JumpIfTrueConstant), U8(14),
|
||||
B(LdaSmi), I8(78),
|
||||
B(Star), R(5),
|
||||
B(CallRuntime), U16(Runtime::kAbort), R(5), U8(1),
|
||||
@ -686,7 +682,7 @@ bytecodes: [
|
||||
B(Star), R(12),
|
||||
B(LdaZero),
|
||||
B(TestEqualStrict), R(12), U8(20),
|
||||
B(JumpIfTrueConstant), U8(17),
|
||||
B(JumpIfTrueConstant), U8(16),
|
||||
B(LdaContextSlot), R(1), U8(7), U8(0),
|
||||
B(Star), R(12),
|
||||
B(LdaNamedProperty), R(12), U8(10), U8(21),
|
||||
@ -695,22 +691,19 @@ bytecodes: [
|
||||
B(Star), R(12),
|
||||
B(TestUndetectable), R(12),
|
||||
B(JumpIfFalse), U8(4),
|
||||
B(JumpConstant), U8(16),
|
||||
B(JumpConstant), U8(15),
|
||||
B(LdaContextSlot), R(1), U8(9), U8(0),
|
||||
B(Star), R(12),
|
||||
B(LdaSmi), I8(1),
|
||||
B(TestEqualStrict), R(12), U8(24),
|
||||
B(JumpIfFalse), U8(186),
|
||||
B(JumpIfFalse), U8(180),
|
||||
B(LdaContextSlot), R(1), U8(13), U8(0),
|
||||
B(TypeOf),
|
||||
B(Star), R(12),
|
||||
B(LdaConstant), U8(11),
|
||||
B(TestEqualStrict), R(12), U8(25),
|
||||
B(TestTypeOf), U8(5),
|
||||
B(JumpIfFalse), U8(4),
|
||||
B(Jump), U8(18),
|
||||
B(Wide), B(LdaSmi), I16(130),
|
||||
B(Star), R(12),
|
||||
B(LdaConstant), U8(12),
|
||||
B(LdaConstant), U8(11),
|
||||
B(Star), R(13),
|
||||
B(CallRuntime), U16(Runtime::kNewTypeError), R(12), U8(2),
|
||||
B(Throw),
|
||||
@ -762,14 +755,14 @@ bytecodes: [
|
||||
B(Star), R(6),
|
||||
B(LdaZero),
|
||||
B(Star), R(5),
|
||||
B(JumpConstant), U8(19),
|
||||
B(JumpConstant), U8(18),
|
||||
B(Ldar), R(15),
|
||||
B(ReThrow),
|
||||
B(Ldar), R(15),
|
||||
B(Jump), U8(20),
|
||||
B(Star), R(13),
|
||||
B(Ldar), R(closure),
|
||||
B(CreateCatchContext), R(13), U8(8), U8(14),
|
||||
B(CreateCatchContext), R(13), U8(8), U8(13),
|
||||
B(Star), R(12),
|
||||
B(LdaTheHole),
|
||||
B(SetPendingMessage),
|
||||
@ -885,7 +878,7 @@ bytecodes: [
|
||||
B(Jump), U8(54),
|
||||
B(Star), R(9),
|
||||
B(Ldar), R(closure),
|
||||
B(CreateCatchContext), R(9), U8(8), U8(18),
|
||||
B(CreateCatchContext), R(9), U8(8), U8(17),
|
||||
B(Star), R(8),
|
||||
B(LdaTheHole),
|
||||
B(SetPendingMessage),
|
||||
@ -980,22 +973,21 @@ constant pool: [
|
||||
ONE_BYTE_INTERNALIZED_STRING_TYPE [".catch"],
|
||||
FIXED_ARRAY_TYPE,
|
||||
ONE_BYTE_INTERNALIZED_STRING_TYPE ["return"],
|
||||
ONE_BYTE_INTERNALIZED_STRING_TYPE ["function"],
|
||||
ONE_BYTE_INTERNALIZED_STRING_TYPE [""],
|
||||
Smi [581],
|
||||
Smi [575],
|
||||
FIXED_ARRAY_TYPE,
|
||||
Smi [723],
|
||||
Smi [356],
|
||||
Smi [382],
|
||||
Smi [717],
|
||||
Smi [350],
|
||||
Smi [376],
|
||||
FIXED_ARRAY_TYPE,
|
||||
Smi [344],
|
||||
]
|
||||
handlers: [
|
||||
[83, 995, 1001],
|
||||
[86, 941, 943],
|
||||
[83, 989, 995],
|
||||
[86, 935, 937],
|
||||
[103, 441, 447],
|
||||
[106, 393, 395],
|
||||
[543, 670, 672],
|
||||
[537, 664, 666],
|
||||
]
|
||||
|
||||
---
|
||||
@ -1010,7 +1002,7 @@ snippet: "
|
||||
"
|
||||
frame size: 19
|
||||
parameter count: 1
|
||||
bytecode array length: 1089
|
||||
bytecode array length: 1083
|
||||
bytecodes: [
|
||||
B(Ldar), R(new_target),
|
||||
B(JumpIfUndefined), U8(42),
|
||||
@ -1023,10 +1015,10 @@ bytecodes: [
|
||||
B(JumpIfTrue), U8(134),
|
||||
B(LdaSmi), I8(1),
|
||||
B(TestEqualStrict), R(3), U8(0),
|
||||
B(JumpIfTrueConstant), U8(13),
|
||||
B(JumpIfTrueConstant), U8(12),
|
||||
B(LdaSmi), I8(2),
|
||||
B(TestEqualStrict), R(3), U8(0),
|
||||
B(JumpIfTrueConstant), U8(15),
|
||||
B(JumpIfTrueConstant), U8(14),
|
||||
B(LdaSmi), I8(78),
|
||||
B(Star), R(5),
|
||||
B(CallRuntime), U16(Runtime::kAbort), R(5), U8(1),
|
||||
@ -1208,7 +1200,7 @@ bytecodes: [
|
||||
B(Star), R(12),
|
||||
B(LdaZero),
|
||||
B(TestEqualStrict), R(12), U8(22),
|
||||
B(JumpIfTrueConstant), U8(17),
|
||||
B(JumpIfTrueConstant), U8(16),
|
||||
B(LdaContextSlot), R(1), U8(7), U8(0),
|
||||
B(Star), R(12),
|
||||
B(LdaNamedProperty), R(12), U8(10), U8(23),
|
||||
@ -1217,22 +1209,19 @@ bytecodes: [
|
||||
B(Star), R(12),
|
||||
B(TestUndetectable), R(12),
|
||||
B(JumpIfFalse), U8(4),
|
||||
B(JumpConstant), U8(16),
|
||||
B(JumpConstant), U8(15),
|
||||
B(LdaContextSlot), R(1), U8(9), U8(0),
|
||||
B(Star), R(12),
|
||||
B(LdaSmi), I8(1),
|
||||
B(TestEqualStrict), R(12), U8(26),
|
||||
B(JumpIfFalse), U8(186),
|
||||
B(JumpIfFalse), U8(180),
|
||||
B(LdaContextSlot), R(1), U8(13), U8(0),
|
||||
B(TypeOf),
|
||||
B(Star), R(12),
|
||||
B(LdaConstant), U8(11),
|
||||
B(TestEqualStrict), R(12), U8(27),
|
||||
B(TestTypeOf), U8(5),
|
||||
B(JumpIfFalse), U8(4),
|
||||
B(Jump), U8(18),
|
||||
B(Wide), B(LdaSmi), I16(130),
|
||||
B(Star), R(12),
|
||||
B(LdaConstant), U8(12),
|
||||
B(LdaConstant), U8(11),
|
||||
B(Star), R(13),
|
||||
B(CallRuntime), U16(Runtime::kNewTypeError), R(12), U8(2),
|
||||
B(Throw),
|
||||
@ -1284,14 +1273,14 @@ bytecodes: [
|
||||
B(Star), R(6),
|
||||
B(LdaZero),
|
||||
B(Star), R(5),
|
||||
B(JumpConstant), U8(19),
|
||||
B(JumpConstant), U8(18),
|
||||
B(Ldar), R(15),
|
||||
B(ReThrow),
|
||||
B(Ldar), R(15),
|
||||
B(Jump), U8(20),
|
||||
B(Star), R(13),
|
||||
B(Ldar), R(closure),
|
||||
B(CreateCatchContext), R(13), U8(8), U8(14),
|
||||
B(CreateCatchContext), R(13), U8(8), U8(13),
|
||||
B(Star), R(12),
|
||||
B(LdaTheHole),
|
||||
B(SetPendingMessage),
|
||||
@ -1396,7 +1385,7 @@ bytecodes: [
|
||||
B(Jump), U8(54),
|
||||
B(Star), R(9),
|
||||
B(Ldar), R(closure),
|
||||
B(CreateCatchContext), R(9), U8(8), U8(18),
|
||||
B(CreateCatchContext), R(9), U8(8), U8(17),
|
||||
B(Star), R(8),
|
||||
B(LdaTheHole),
|
||||
B(SetPendingMessage),
|
||||
@ -1480,22 +1469,21 @@ constant pool: [
|
||||
ONE_BYTE_INTERNALIZED_STRING_TYPE [".catch"],
|
||||
FIXED_ARRAY_TYPE,
|
||||
ONE_BYTE_INTERNALIZED_STRING_TYPE ["return"],
|
||||
ONE_BYTE_INTERNALIZED_STRING_TYPE ["function"],
|
||||
ONE_BYTE_INTERNALIZED_STRING_TYPE [""],
|
||||
Smi [606],
|
||||
Smi [600],
|
||||
FIXED_ARRAY_TYPE,
|
||||
Smi [748],
|
||||
Smi [356],
|
||||
Smi [382],
|
||||
Smi [742],
|
||||
Smi [350],
|
||||
Smi [376],
|
||||
FIXED_ARRAY_TYPE,
|
||||
Smi [320],
|
||||
]
|
||||
handlers: [
|
||||
[83, 996, 1002],
|
||||
[86, 942, 944],
|
||||
[83, 990, 996],
|
||||
[86, 936, 938],
|
||||
[103, 466, 472],
|
||||
[106, 418, 420],
|
||||
[568, 695, 697],
|
||||
[562, 689, 691],
|
||||
]
|
||||
|
||||
---
|
||||
@ -1508,7 +1496,7 @@ snippet: "
|
||||
"
|
||||
frame size: 14
|
||||
parameter count: 1
|
||||
bytecode array length: 594
|
||||
bytecode array length: 588
|
||||
bytecodes: [
|
||||
B(Ldar), R(new_target),
|
||||
B(JumpIfUndefined), U8(22),
|
||||
@ -1620,7 +1608,7 @@ bytecodes: [
|
||||
B(Star), R(11),
|
||||
B(LdaZero),
|
||||
B(TestEqualStrict), R(11), U8(21),
|
||||
B(JumpIfTrue), U8(135),
|
||||
B(JumpIfTrue), U8(129),
|
||||
B(LdaCurrentContextSlot), U8(7),
|
||||
B(Star), R(11),
|
||||
B(LdaNamedProperty), R(11), U8(9), U8(22),
|
||||
@ -1629,22 +1617,19 @@ bytecodes: [
|
||||
B(Star), R(11),
|
||||
B(TestUndetectable), R(11),
|
||||
B(JumpIfFalse), U8(4),
|
||||
B(Jump), U8(115),
|
||||
B(Jump), U8(109),
|
||||
B(LdaCurrentContextSlot), U8(9),
|
||||
B(Star), R(11),
|
||||
B(LdaSmi), I8(1),
|
||||
B(TestEqualStrict), R(11), U8(25),
|
||||
B(JumpIfFalse), U8(69),
|
||||
B(JumpIfFalse), U8(63),
|
||||
B(LdaCurrentContextSlot), U8(11),
|
||||
B(TypeOf),
|
||||
B(Star), R(11),
|
||||
B(LdaConstant), U8(10),
|
||||
B(TestEqualStrict), R(11), U8(26),
|
||||
B(TestTypeOf), U8(5),
|
||||
B(JumpIfFalse), U8(4),
|
||||
B(Jump), U8(18),
|
||||
B(Wide), B(LdaSmi), I16(130),
|
||||
B(Star), R(11),
|
||||
B(LdaConstant), U8(11),
|
||||
B(LdaConstant), U8(10),
|
||||
B(Star), R(12),
|
||||
B(CallRuntime), U16(Runtime::kNewTypeError), R(11), U8(2),
|
||||
B(Throw),
|
||||
@ -1657,7 +1642,7 @@ bytecodes: [
|
||||
B(Jump), U8(20),
|
||||
B(Star), R(12),
|
||||
B(Ldar), R(closure),
|
||||
B(CreateCatchContext), R(12), U8(7), U8(12),
|
||||
B(CreateCatchContext), R(12), U8(7), U8(11),
|
||||
B(Star), R(11),
|
||||
B(LdaTheHole),
|
||||
B(SetPendingMessage),
|
||||
@ -1709,7 +1694,7 @@ bytecodes: [
|
||||
B(Jump), U8(54),
|
||||
B(Star), R(8),
|
||||
B(Ldar), R(closure),
|
||||
B(CreateCatchContext), R(8), U8(7), U8(13),
|
||||
B(CreateCatchContext), R(8), U8(7), U8(12),
|
||||
B(Star), R(7),
|
||||
B(LdaTheHole),
|
||||
B(SetPendingMessage),
|
||||
@ -1788,16 +1773,15 @@ constant pool: [
|
||||
ONE_BYTE_INTERNALIZED_STRING_TYPE [".catch"],
|
||||
FIXED_ARRAY_TYPE,
|
||||
ONE_BYTE_INTERNALIZED_STRING_TYPE ["return"],
|
||||
ONE_BYTE_INTERNALIZED_STRING_TYPE ["function"],
|
||||
ONE_BYTE_INTERNALIZED_STRING_TYPE [""],
|
||||
FIXED_ARRAY_TYPE,
|
||||
FIXED_ARRAY_TYPE,
|
||||
]
|
||||
handlers: [
|
||||
[63, 507, 513],
|
||||
[66, 453, 455],
|
||||
[63, 501, 507],
|
||||
[66, 447, 449],
|
||||
[81, 241, 247],
|
||||
[84, 193, 195],
|
||||
[331, 343, 345],
|
||||
[325, 337, 339],
|
||||
]
|
||||
|
||||
|
@ -11,7 +11,7 @@ snippet: "
|
||||
"
|
||||
frame size: 15
|
||||
parameter count: 1
|
||||
bytecode array length: 270
|
||||
bytecode array length: 264
|
||||
bytecodes: [
|
||||
/* 30 E> */ B(StackCheck),
|
||||
B(LdaZero),
|
||||
@ -72,25 +72,22 @@ bytecodes: [
|
||||
B(Star), R(11),
|
||||
B(LdaZero),
|
||||
B(TestEqualStrict), R(4), U8(16),
|
||||
B(JumpIfTrue), U8(111),
|
||||
B(JumpIfTrue), U8(105),
|
||||
B(LdaNamedProperty), R(2), U8(7), U8(17),
|
||||
B(Star), R(6),
|
||||
B(TestUndetectable), R(6),
|
||||
B(JumpIfFalse), U8(4),
|
||||
B(Jump), U8(99),
|
||||
B(Jump), U8(93),
|
||||
B(LdaSmi), I8(1),
|
||||
B(TestEqualStrict), R(4), U8(20),
|
||||
B(JumpIfFalse), U8(67),
|
||||
B(JumpIfFalse), U8(61),
|
||||
B(Ldar), R(6),
|
||||
B(TypeOf),
|
||||
B(Star), R(12),
|
||||
B(LdaConstant), U8(8),
|
||||
B(TestEqualStrict), R(12), U8(21),
|
||||
B(TestTypeOf), U8(5),
|
||||
B(JumpIfFalse), U8(4),
|
||||
B(Jump), U8(18),
|
||||
B(Wide), B(LdaSmi), I16(130),
|
||||
B(Star), R(12),
|
||||
B(LdaConstant), U8(9),
|
||||
B(LdaConstant), U8(8),
|
||||
B(Star), R(13),
|
||||
B(CallRuntime), U16(Runtime::kNewTypeError), R(12), U8(2),
|
||||
B(Throw),
|
||||
@ -101,7 +98,7 @@ bytecodes: [
|
||||
B(Jump), U8(20),
|
||||
B(Star), R(13),
|
||||
B(Ldar), R(closure),
|
||||
B(CreateCatchContext), R(13), U8(5), U8(10),
|
||||
B(CreateCatchContext), R(13), U8(5), U8(9),
|
||||
B(Star), R(12),
|
||||
B(LdaTheHole),
|
||||
B(SetPendingMessage),
|
||||
@ -137,14 +134,13 @@ constant pool: [
|
||||
ONE_BYTE_INTERNALIZED_STRING_TYPE [".catch"],
|
||||
FIXED_ARRAY_TYPE,
|
||||
ONE_BYTE_INTERNALIZED_STRING_TYPE ["return"],
|
||||
ONE_BYTE_INTERNALIZED_STRING_TYPE ["function"],
|
||||
ONE_BYTE_INTERNALIZED_STRING_TYPE [""],
|
||||
FIXED_ARRAY_TYPE,
|
||||
]
|
||||
handlers: [
|
||||
[7, 124, 130],
|
||||
[10, 88, 90],
|
||||
[197, 207, 209],
|
||||
[191, 201, 203],
|
||||
]
|
||||
|
||||
---
|
||||
@ -154,7 +150,7 @@ snippet: "
|
||||
"
|
||||
frame size: 16
|
||||
parameter count: 1
|
||||
bytecode array length: 284
|
||||
bytecode array length: 278
|
||||
bytecodes: [
|
||||
/* 30 E> */ B(StackCheck),
|
||||
/* 42 S> */ B(LdaConstant), U8(0),
|
||||
@ -217,25 +213,22 @@ bytecodes: [
|
||||
B(Star), R(12),
|
||||
B(LdaZero),
|
||||
B(TestEqualStrict), R(5), U8(15),
|
||||
B(JumpIfTrue), U8(111),
|
||||
B(JumpIfTrue), U8(105),
|
||||
B(LdaNamedProperty), R(3), U8(7), U8(16),
|
||||
B(Star), R(7),
|
||||
B(TestUndetectable), R(7),
|
||||
B(JumpIfFalse), U8(4),
|
||||
B(Jump), U8(99),
|
||||
B(Jump), U8(93),
|
||||
B(LdaSmi), I8(1),
|
||||
B(TestEqualStrict), R(5), U8(19),
|
||||
B(JumpIfFalse), U8(67),
|
||||
B(JumpIfFalse), U8(61),
|
||||
B(Ldar), R(7),
|
||||
B(TypeOf),
|
||||
B(Star), R(13),
|
||||
B(LdaConstant), U8(8),
|
||||
B(TestEqualStrict), R(13), U8(20),
|
||||
B(TestTypeOf), U8(5),
|
||||
B(JumpIfFalse), U8(4),
|
||||
B(Jump), U8(18),
|
||||
B(Wide), B(LdaSmi), I16(130),
|
||||
B(Star), R(13),
|
||||
B(LdaConstant), U8(9),
|
||||
B(LdaConstant), U8(8),
|
||||
B(Star), R(14),
|
||||
B(CallRuntime), U16(Runtime::kNewTypeError), R(13), U8(2),
|
||||
B(Throw),
|
||||
@ -246,7 +239,7 @@ bytecodes: [
|
||||
B(Jump), U8(20),
|
||||
B(Star), R(14),
|
||||
B(Ldar), R(closure),
|
||||
B(CreateCatchContext), R(14), U8(5), U8(10),
|
||||
B(CreateCatchContext), R(14), U8(5), U8(9),
|
||||
B(Star), R(13),
|
||||
B(LdaTheHole),
|
||||
B(SetPendingMessage),
|
||||
@ -287,14 +280,13 @@ constant pool: [
|
||||
ONE_BYTE_INTERNALIZED_STRING_TYPE [".catch"],
|
||||
FIXED_ARRAY_TYPE,
|
||||
ONE_BYTE_INTERNALIZED_STRING_TYPE ["return"],
|
||||
ONE_BYTE_INTERNALIZED_STRING_TYPE ["function"],
|
||||
ONE_BYTE_INTERNALIZED_STRING_TYPE [""],
|
||||
FIXED_ARRAY_TYPE,
|
||||
]
|
||||
handlers: [
|
||||
[11, 127, 133],
|
||||
[14, 91, 93],
|
||||
[201, 211, 213],
|
||||
[195, 205, 207],
|
||||
]
|
||||
|
||||
---
|
||||
@ -306,7 +298,7 @@ snippet: "
|
||||
"
|
||||
frame size: 15
|
||||
parameter count: 1
|
||||
bytecode array length: 288
|
||||
bytecode array length: 282
|
||||
bytecodes: [
|
||||
/* 30 E> */ B(StackCheck),
|
||||
B(LdaZero),
|
||||
@ -375,25 +367,22 @@ bytecodes: [
|
||||
B(Star), R(11),
|
||||
B(LdaZero),
|
||||
B(TestEqualStrict), R(4), U8(18),
|
||||
B(JumpIfTrue), U8(111),
|
||||
B(JumpIfTrue), U8(105),
|
||||
B(LdaNamedProperty), R(2), U8(7), U8(19),
|
||||
B(Star), R(6),
|
||||
B(TestUndetectable), R(6),
|
||||
B(JumpIfFalse), U8(4),
|
||||
B(Jump), U8(99),
|
||||
B(Jump), U8(93),
|
||||
B(LdaSmi), I8(1),
|
||||
B(TestEqualStrict), R(4), U8(22),
|
||||
B(JumpIfFalse), U8(67),
|
||||
B(JumpIfFalse), U8(61),
|
||||
B(Ldar), R(6),
|
||||
B(TypeOf),
|
||||
B(Star), R(12),
|
||||
B(LdaConstant), U8(8),
|
||||
B(TestEqualStrict), R(12), U8(23),
|
||||
B(TestTypeOf), U8(5),
|
||||
B(JumpIfFalse), U8(4),
|
||||
B(Jump), U8(18),
|
||||
B(Wide), B(LdaSmi), I16(130),
|
||||
B(Star), R(12),
|
||||
B(LdaConstant), U8(9),
|
||||
B(LdaConstant), U8(8),
|
||||
B(Star), R(13),
|
||||
B(CallRuntime), U16(Runtime::kNewTypeError), R(12), U8(2),
|
||||
B(Throw),
|
||||
@ -404,7 +393,7 @@ bytecodes: [
|
||||
B(Jump), U8(20),
|
||||
B(Star), R(13),
|
||||
B(Ldar), R(closure),
|
||||
B(CreateCatchContext), R(13), U8(5), U8(10),
|
||||
B(CreateCatchContext), R(13), U8(5), U8(9),
|
||||
B(Star), R(12),
|
||||
B(LdaTheHole),
|
||||
B(SetPendingMessage),
|
||||
@ -440,14 +429,13 @@ constant pool: [
|
||||
ONE_BYTE_INTERNALIZED_STRING_TYPE [".catch"],
|
||||
FIXED_ARRAY_TYPE,
|
||||
ONE_BYTE_INTERNALIZED_STRING_TYPE ["return"],
|
||||
ONE_BYTE_INTERNALIZED_STRING_TYPE ["function"],
|
||||
ONE_BYTE_INTERNALIZED_STRING_TYPE [""],
|
||||
FIXED_ARRAY_TYPE,
|
||||
]
|
||||
handlers: [
|
||||
[7, 142, 148],
|
||||
[10, 106, 108],
|
||||
[215, 225, 227],
|
||||
[209, 219, 221],
|
||||
]
|
||||
|
||||
---
|
||||
@ -457,7 +445,7 @@ snippet: "
|
||||
"
|
||||
frame size: 14
|
||||
parameter count: 1
|
||||
bytecode array length: 295
|
||||
bytecode array length: 289
|
||||
bytecodes: [
|
||||
/* 30 E> */ B(StackCheck),
|
||||
/* 42 S> */ B(CreateObjectLiteral), U8(0), U8(2), U8(1), R(8),
|
||||
@ -523,25 +511,22 @@ bytecodes: [
|
||||
B(Star), R(10),
|
||||
B(LdaZero),
|
||||
B(TestEqualStrict), R(3), U8(21),
|
||||
B(JumpIfTrue), U8(111),
|
||||
B(JumpIfTrue), U8(105),
|
||||
B(LdaNamedProperty), R(1), U8(9), U8(22),
|
||||
B(Star), R(5),
|
||||
B(TestUndetectable), R(5),
|
||||
B(JumpIfFalse), U8(4),
|
||||
B(Jump), U8(99),
|
||||
B(Jump), U8(93),
|
||||
B(LdaSmi), I8(1),
|
||||
B(TestEqualStrict), R(3), U8(25),
|
||||
B(JumpIfFalse), U8(67),
|
||||
B(JumpIfFalse), U8(61),
|
||||
B(Ldar), R(5),
|
||||
B(TypeOf),
|
||||
B(Star), R(11),
|
||||
B(LdaConstant), U8(10),
|
||||
B(TestEqualStrict), R(11), U8(26),
|
||||
B(TestTypeOf), U8(5),
|
||||
B(JumpIfFalse), U8(4),
|
||||
B(Jump), U8(18),
|
||||
B(Wide), B(LdaSmi), I16(130),
|
||||
B(Star), R(11),
|
||||
B(LdaConstant), U8(11),
|
||||
B(LdaConstant), U8(10),
|
||||
B(Star), R(12),
|
||||
B(CallRuntime), U16(Runtime::kNewTypeError), R(11), U8(2),
|
||||
B(Throw),
|
||||
@ -552,7 +537,7 @@ bytecodes: [
|
||||
B(Jump), U8(20),
|
||||
B(Star), R(12),
|
||||
B(Ldar), R(closure),
|
||||
B(CreateCatchContext), R(12), U8(7), U8(12),
|
||||
B(CreateCatchContext), R(12), U8(7), U8(11),
|
||||
B(Star), R(11),
|
||||
B(LdaTheHole),
|
||||
B(SetPendingMessage),
|
||||
@ -595,13 +580,12 @@ constant pool: [
|
||||
ONE_BYTE_INTERNALIZED_STRING_TYPE [".catch"],
|
||||
FIXED_ARRAY_TYPE,
|
||||
ONE_BYTE_INTERNALIZED_STRING_TYPE ["return"],
|
||||
ONE_BYTE_INTERNALIZED_STRING_TYPE ["function"],
|
||||
ONE_BYTE_INTERNALIZED_STRING_TYPE [""],
|
||||
FIXED_ARRAY_TYPE,
|
||||
]
|
||||
handlers: [
|
||||
[15, 138, 144],
|
||||
[18, 102, 104],
|
||||
[212, 222, 224],
|
||||
[206, 216, 218],
|
||||
]
|
||||
|
||||
|
@ -280,7 +280,7 @@ snippet: "
|
||||
"
|
||||
frame size: 18
|
||||
parameter count: 1
|
||||
bytecode array length: 773
|
||||
bytecode array length: 767
|
||||
bytecodes: [
|
||||
B(Ldar), R(new_target),
|
||||
B(JumpIfUndefined), U8(35),
|
||||
@ -337,7 +337,7 @@ bytecodes: [
|
||||
B(Star), R(6),
|
||||
B(LdaZero),
|
||||
B(Star), R(5),
|
||||
B(JumpConstant), U8(13),
|
||||
B(JumpConstant), U8(12),
|
||||
B(Ldar), R(10),
|
||||
/* 11 E> */ B(Throw),
|
||||
B(Ldar), R(closure),
|
||||
@ -474,7 +474,7 @@ bytecodes: [
|
||||
B(Star), R(11),
|
||||
B(LdaZero),
|
||||
B(TestEqualStrict), R(11), U8(16),
|
||||
B(JumpIfTrue), U8(159),
|
||||
B(JumpIfTrue), U8(153),
|
||||
B(LdaContextSlot), R(1), U8(7), U8(0),
|
||||
B(Star), R(11),
|
||||
B(LdaNamedProperty), R(11), U8(9), U8(17),
|
||||
@ -483,22 +483,19 @@ bytecodes: [
|
||||
B(Star), R(11),
|
||||
B(TestUndetectable), R(11),
|
||||
B(JumpIfFalse), U8(4),
|
||||
B(Jump), U8(133),
|
||||
B(Jump), U8(127),
|
||||
B(LdaContextSlot), R(1), U8(9), U8(0),
|
||||
B(Star), R(11),
|
||||
B(LdaSmi), I8(1),
|
||||
B(TestEqualStrict), R(11), U8(20),
|
||||
B(JumpIfFalse), U8(75),
|
||||
B(JumpIfFalse), U8(69),
|
||||
B(LdaContextSlot), R(1), U8(11), U8(0),
|
||||
B(TypeOf),
|
||||
B(Star), R(11),
|
||||
B(LdaConstant), U8(10),
|
||||
B(TestEqualStrict), R(11), U8(21),
|
||||
B(TestTypeOf), U8(5),
|
||||
B(JumpIfFalse), U8(4),
|
||||
B(Jump), U8(18),
|
||||
B(Wide), B(LdaSmi), I16(130),
|
||||
B(Star), R(11),
|
||||
B(LdaConstant), U8(11),
|
||||
B(LdaConstant), U8(10),
|
||||
B(Star), R(12),
|
||||
B(CallRuntime), U16(Runtime::kNewTypeError), R(11), U8(2),
|
||||
B(Throw),
|
||||
@ -511,7 +508,7 @@ bytecodes: [
|
||||
B(Jump), U8(20),
|
||||
B(Star), R(12),
|
||||
B(Ldar), R(closure),
|
||||
B(CreateCatchContext), R(12), U8(7), U8(12),
|
||||
B(CreateCatchContext), R(12), U8(7), U8(11),
|
||||
B(Star), R(11),
|
||||
B(LdaTheHole),
|
||||
B(SetPendingMessage),
|
||||
@ -618,15 +615,14 @@ constant pool: [
|
||||
ONE_BYTE_INTERNALIZED_STRING_TYPE [".catch"],
|
||||
FIXED_ARRAY_TYPE,
|
||||
ONE_BYTE_INTERNALIZED_STRING_TYPE ["return"],
|
||||
ONE_BYTE_INTERNALIZED_STRING_TYPE ["function"],
|
||||
ONE_BYTE_INTERNALIZED_STRING_TYPE [""],
|
||||
FIXED_ARRAY_TYPE,
|
||||
Smi [577],
|
||||
Smi [571],
|
||||
]
|
||||
handlers: [
|
||||
[53, 692, 698],
|
||||
[53, 686, 692],
|
||||
[149, 443, 449],
|
||||
[152, 399, 401],
|
||||
[545, 561, 563],
|
||||
[539, 555, 557],
|
||||
]
|
||||
|
||||
|
@ -1007,6 +1007,26 @@ TEST(Typeof) {
|
||||
LoadGolden("Typeof.golden")));
|
||||
}
|
||||
|
||||
TEST(CompareTypeOf) {
|
||||
InitializedIgnitionHandleScope scope;
|
||||
BytecodeExpectationsPrinter printer(CcTest::isolate());
|
||||
|
||||
const char* snippets[] = {
|
||||
"return typeof(1) === 'number';\n",
|
||||
|
||||
"return 'string' === typeof('foo');\n",
|
||||
|
||||
"return typeof(true) == 'boolean';\n",
|
||||
|
||||
"return 'string' === typeof(undefined);\n",
|
||||
|
||||
"return 'unknown' === typeof(undefined);\n",
|
||||
};
|
||||
|
||||
CHECK(CompareTexts(BuildActual(printer, snippets),
|
||||
LoadGolden("CompareTypeOf.golden")));
|
||||
}
|
||||
|
||||
TEST(Delete) {
|
||||
InitializedIgnitionHandleScope scope;
|
||||
BytecodeExpectationsPrinter printer(CcTest::isolate());
|
||||
|
@ -10,6 +10,7 @@
|
||||
#include "src/handles.h"
|
||||
#include "src/interpreter/bytecode-array-builder.h"
|
||||
#include "src/interpreter/bytecode-array-iterator.h"
|
||||
#include "src/interpreter/bytecode-flags.h"
|
||||
#include "src/interpreter/bytecode-label.h"
|
||||
#include "src/interpreter/interpreter.h"
|
||||
#include "src/objects-inl.h"
|
||||
@ -2073,6 +2074,58 @@ TEST(InterpreterStrictNotEqual) {
|
||||
}
|
||||
}
|
||||
|
||||
TEST(InterpreterCompareTypeOf) {
|
||||
typedef TestTypeOfFlags::LiteralFlag LiteralFlag;
|
||||
HandleAndZoneScope handles;
|
||||
Isolate* isolate = handles.main_isolate();
|
||||
Factory* factory = isolate->factory();
|
||||
Zone* zone = handles.main_zone();
|
||||
std::pair<Handle<Object>, LiteralFlag> inputs[] = {
|
||||
{handle(Smi::FromInt(24), isolate), LiteralFlag::kNumber},
|
||||
{factory->NewNumber(2.5), LiteralFlag::kNumber},
|
||||
{factory->NewStringFromAsciiChecked("foo"), LiteralFlag::kString},
|
||||
{factory
|
||||
->NewConsString(factory->NewStringFromAsciiChecked("foo"),
|
||||
factory->NewStringFromAsciiChecked("bar"))
|
||||
.ToHandleChecked(),
|
||||
LiteralFlag::kString},
|
||||
{factory->prototype_string(), LiteralFlag::kString},
|
||||
{factory->NewSymbol(), LiteralFlag::kSymbol},
|
||||
{factory->true_value(), LiteralFlag::kBoolean},
|
||||
{factory->false_value(), LiteralFlag::kBoolean},
|
||||
{factory->undefined_value(), LiteralFlag::kUndefined},
|
||||
{InterpreterTester::NewObject(
|
||||
"(function() { return function() {}; })();"),
|
||||
LiteralFlag::kFunction},
|
||||
{InterpreterTester::NewObject("new Object();"), LiteralFlag::kObject},
|
||||
{factory->null_value(), LiteralFlag::kObject},
|
||||
};
|
||||
const LiteralFlag kLiterals[] = {
|
||||
#define LITERAL_FLAG(name, _) LiteralFlag::k##name,
|
||||
TYPEOF_LITERAL_LIST(LITERAL_FLAG)
|
||||
#undef LITERAL_FLAG
|
||||
};
|
||||
|
||||
for (size_t l = 0; l < arraysize(kLiterals); l++) {
|
||||
LiteralFlag literal_flag = kLiterals[l];
|
||||
if (literal_flag == LiteralFlag::kOther) continue;
|
||||
|
||||
BytecodeArrayBuilder builder(isolate, zone, 1, 0, 0);
|
||||
builder.LoadAccumulatorWithRegister(builder.Parameter(0))
|
||||
.CompareTypeOf(kLiterals[l])
|
||||
.Return();
|
||||
Handle<BytecodeArray> bytecode_array = builder.ToBytecodeArray(isolate);
|
||||
InterpreterTester tester(isolate, bytecode_array);
|
||||
auto callable = tester.GetCallable<Handle<Object>>();
|
||||
|
||||
for (size_t i = 0; i < arraysize(inputs); i++) {
|
||||
Handle<Object> return_value = callable(inputs[i].first).ToHandleChecked();
|
||||
CHECK(return_value->IsBoolean());
|
||||
CHECK_EQ(return_value->BooleanValue(), inputs[i].second == literal_flag);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
TEST(InterpreterInstanceOf) {
|
||||
HandleAndZoneScope handles;
|
||||
Isolate* isolate = handles.main_isolate();
|
||||
|
@ -213,7 +213,8 @@ TEST_F(BytecodeArrayBuilderTest, AllBytecodesGenerated) {
|
||||
.CompareOperation(Token::Value::LTE, reg, 5)
|
||||
.CompareOperation(Token::Value::GTE, reg, 6)
|
||||
.CompareOperation(Token::Value::INSTANCEOF, reg, 7)
|
||||
.CompareOperation(Token::Value::IN, reg, 8);
|
||||
.CompareOperation(Token::Value::IN, reg, 8)
|
||||
.CompareTypeOf(TestTypeOfFlags::LiteralFlag::kNumber);
|
||||
|
||||
// Emit peephole optimizations of equality with Null or Undefined.
|
||||
builder.LoadUndefined()
|
||||
|
Loading…
Reference in New Issue
Block a user