Revert "Revert "Upgrade to 5.0.71.48"" DO NOT MERGE
This reverts commit f2e3994fa5148cc3d9946666f0b0596290192b0e,
and updates the x64 makefile properly so it doesn't break that
build.
FPIIM-449
Change-Id: Ib83e35bfbae6af627451c926a9650ec57c045605
(cherry picked from commit 109988c7ccb6f3fd1a58574fa3dfb88beaef6632)
diff --git a/test/cctest/interpreter/bytecode-expectations-printer.cc b/test/cctest/interpreter/bytecode-expectations-printer.cc
new file mode 100644
index 0000000..d5e0456
--- /dev/null
+++ b/test/cctest/interpreter/bytecode-expectations-printer.cc
@@ -0,0 +1,301 @@
+// Copyright 2016 the V8 project authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "test/cctest/interpreter/bytecode-expectations-printer.h"
+
+#include <iostream>
+#include <vector>
+
+#include "include/libplatform/libplatform.h"
+#include "include/v8.h"
+
+#include "src/base/logging.h"
+#include "src/base/smart-pointers.h"
+#include "src/compiler.h"
+
+#include "src/interpreter/bytecode-array-iterator.h"
+#include "src/interpreter/bytecode-generator.h"
+#include "src/interpreter/bytecodes.h"
+#include "src/interpreter/interpreter.h"
+
+namespace v8 {
+namespace internal {
+namespace interpreter {
+
+// static
+const char* const BytecodeExpectationsPrinter::kDefaultTopFunctionName =
+ "__genbckexp_wrapper__";
+
+v8::Local<v8::String> BytecodeExpectationsPrinter::V8StringFromUTF8(
+ const char* data) const {
+ return v8::String::NewFromUtf8(isolate_, data, v8::NewStringType::kNormal)
+ .ToLocalChecked();
+}
+
+std::string BytecodeExpectationsPrinter::WrapCodeInFunction(
+ const char* function_name, const std::string& function_body) const {
+ std::ostringstream program_stream;
+ program_stream << "function " << function_name << "() {" << function_body
+ << "}\n"
+ << function_name << "();";
+
+ return program_stream.str();
+}
+
+v8::Local<v8::Script> BytecodeExpectationsPrinter::Compile(
+ const char* program) const {
+ v8::Local<v8::String> source = V8StringFromUTF8(program);
+ return v8::Script::Compile(isolate_->GetCurrentContext(), source)
+ .ToLocalChecked();
+}
+
+void BytecodeExpectationsPrinter::Run(v8::Local<v8::Script> script) const {
+ (void)script->Run(isolate_->GetCurrentContext());
+}
+
+i::Handle<v8::internal::BytecodeArray>
+BytecodeExpectationsPrinter::GetBytecodeArrayForGlobal(
+ const char* global_name) const {
+ const v8::Local<v8::Context>& context = isolate_->GetCurrentContext();
+ v8::Local<v8::String> v8_global_name = V8StringFromUTF8(global_name);
+ v8::Local<v8::Function> function = v8::Local<v8::Function>::Cast(
+ context->Global()->Get(context, v8_global_name).ToLocalChecked());
+ i::Handle<i::JSFunction> js_function =
+ i::Handle<i::JSFunction>::cast(v8::Utils::OpenHandle(*function));
+
+ i::Handle<i::BytecodeArray> bytecodes =
+ i::handle(js_function->shared()->bytecode_array(), i_isolate());
+
+ return bytecodes;
+}
+
+i::Handle<i::BytecodeArray>
+BytecodeExpectationsPrinter::GetBytecodeArrayForScript(
+ v8::Local<v8::Script> script) const {
+ i::Handle<i::JSFunction> js_function = v8::Utils::OpenHandle(*script);
+ return i::handle(js_function->shared()->bytecode_array(), i_isolate());
+}
+
+void BytecodeExpectationsPrinter::PrintEscapedString(
+ std::ostream& stream, const std::string& string) const {
+ for (char c : string) {
+ switch (c) {
+ case '"':
+ stream << "\\\"";
+ break;
+ case '\\':
+ stream << "\\\\";
+ break;
+ default:
+ stream << c;
+ break;
+ }
+ }
+}
+
+void BytecodeExpectationsPrinter::PrintBytecodeOperand(
+ std::ostream& stream, const BytecodeArrayIterator& bytecode_iter,
+ const Bytecode& bytecode, int op_index, int parameter_count) const {
+ OperandType op_type = Bytecodes::GetOperandType(bytecode, op_index);
+ OperandSize op_size = Bytecodes::GetOperandSize(bytecode, op_index);
+
+ const char* size_tag;
+ switch (op_size) {
+ case OperandSize::kByte:
+ size_tag = "8";
+ break;
+ case OperandSize::kShort:
+ size_tag = "16";
+ break;
+ default:
+ UNREACHABLE();
+ return;
+ }
+
+ if (Bytecodes::IsRegisterOperandType(op_type)) {
+ Register register_value = bytecode_iter.GetRegisterOperand(op_index);
+ stream << 'R';
+ if (op_size != OperandSize::kByte) stream << size_tag;
+ if (register_value.is_new_target()) {
+ stream << "(new_target)";
+ } else if (register_value.is_current_context()) {
+ stream << "(context)";
+ } else if (register_value.is_function_closure()) {
+ stream << "(closure)";
+ } else if (register_value.is_parameter()) {
+ int parameter_index = register_value.ToParameterIndex(parameter_count);
+ if (parameter_index == 0) {
+ stream << "(this)";
+ } else {
+ stream << "(arg" << (parameter_index - 1) << ')';
+ }
+ } else {
+ stream << '(' << register_value.index() << ')';
+ }
+ } else {
+ stream << 'U' << size_tag << '(';
+
+ if (Bytecodes::IsImmediateOperandType(op_type)) {
+ // We need a cast, otherwise the result is printed as char.
+ stream << static_cast<int>(bytecode_iter.GetImmediateOperand(op_index));
+ } else if (Bytecodes::IsRegisterCountOperandType(op_type)) {
+ stream << bytecode_iter.GetRegisterCountOperand(op_index);
+ } else if (Bytecodes::IsIndexOperandType(op_type)) {
+ stream << bytecode_iter.GetIndexOperand(op_index);
+ } else {
+ UNREACHABLE();
+ }
+
+ stream << ')';
+ }
+}
+
+void BytecodeExpectationsPrinter::PrintBytecode(
+ std::ostream& stream, const BytecodeArrayIterator& bytecode_iter,
+ int parameter_count) const {
+ Bytecode bytecode = bytecode_iter.current_bytecode();
+
+ stream << "B(" << Bytecodes::ToString(bytecode) << ')';
+
+ int operands_count = Bytecodes::NumberOfOperands(bytecode);
+ for (int op_index = 0; op_index < operands_count; ++op_index) {
+ stream << ", ";
+ PrintBytecodeOperand(stream, bytecode_iter, bytecode, op_index,
+ parameter_count);
+ }
+}
+
+void BytecodeExpectationsPrinter::PrintV8String(std::ostream& stream,
+ i::String* string) const {
+ stream << '"';
+ for (int i = 0, length = string->length(); i < length; ++i) {
+ stream << i::AsEscapedUC16ForJSON(string->Get(i));
+ }
+ stream << '"';
+}
+
+void BytecodeExpectationsPrinter::PrintConstant(
+ std::ostream& stream, i::Handle<i::Object> constant) const {
+ switch (const_pool_type_) {
+ case ConstantPoolType::kString:
+ CHECK(constant->IsString());
+ PrintV8String(stream, i::String::cast(*constant));
+ break;
+ case ConstantPoolType::kNumber:
+ if (constant->IsSmi()) {
+ i::Smi::cast(*constant)->SmiPrint(stream);
+ } else if (constant->IsHeapNumber()) {
+ i::HeapNumber::cast(*constant)->HeapNumberPrint(stream);
+ } else {
+ UNREACHABLE();
+ }
+ break;
+ case ConstantPoolType::kMixed:
+ if (constant->IsSmi()) {
+ stream << "kInstanceTypeDontCare";
+ } else {
+ stream << "InstanceType::"
+ << i::HeapObject::cast(*constant)->map()->instance_type();
+ }
+ break;
+ case ConstantPoolType::kUnknown:
+ default:
+ UNREACHABLE();
+ return;
+ }
+}
+
+void BytecodeExpectationsPrinter::PrintFrameSize(
+ std::ostream& stream, i::Handle<i::BytecodeArray> bytecode_array) const {
+ const int kPointerSize = sizeof(void*);
+ int frame_size = bytecode_array->frame_size();
+
+ DCHECK_EQ(frame_size % kPointerSize, 0);
+ stream << "frame size: " << frame_size / kPointerSize;
+ if (frame_size > 0) stream << " # in multiples of sizeof(void*)";
+ stream << "\nparameter count: " << bytecode_array->parameter_count() << '\n';
+}
+
+void BytecodeExpectationsPrinter::PrintBytecodeSequence(
+ std::ostream& stream, i::Handle<i::BytecodeArray> bytecode_array) const {
+ stream << "bytecodes: [\n";
+ BytecodeArrayIterator bytecode_iter(bytecode_array);
+ for (; !bytecode_iter.done(); bytecode_iter.Advance()) {
+ stream << " ";
+ PrintBytecode(stream, bytecode_iter, bytecode_array->parameter_count());
+ stream << ",\n";
+ }
+ stream << "]\n";
+}
+
+void BytecodeExpectationsPrinter::PrintConstantPool(
+ std::ostream& stream, i::FixedArray* constant_pool) const {
+ stream << "constant pool: [\n";
+ int num_constants = constant_pool->length();
+ if (num_constants > 0) {
+ for (int i = 0; i < num_constants; ++i) {
+ stream << " ";
+ PrintConstant(stream, i::FixedArray::get(constant_pool, i, i_isolate()));
+ stream << ",\n";
+ }
+ }
+ stream << "]\n";
+}
+
+void BytecodeExpectationsPrinter::PrintCodeSnippet(
+ std::ostream& stream, const std::string& body) const {
+ stream << "snippet: \"\n";
+ std::stringstream body_stream(body);
+ std::string body_line;
+ while (std::getline(body_stream, body_line)) {
+ stream << " ";
+ PrintEscapedString(stream, body_line);
+ stream << '\n';
+ }
+ stream << "\"\n";
+}
+
+void BytecodeExpectationsPrinter::PrintHandlers(
+ std::ostream& stream, i::Handle<i::BytecodeArray> bytecode_array) const {
+ stream << "handlers: [\n";
+ HandlerTable* table = HandlerTable::cast(bytecode_array->handler_table());
+ for (int i = 0, num_entries = table->NumberOfRangeEntries(); i < num_entries;
+ ++i) {
+ stream << " [" << table->GetRangeStart(i) << ", " << table->GetRangeEnd(i)
+ << ", " << table->GetRangeHandler(i) << "],\n";
+ }
+ stream << "]\n";
+}
+
+void BytecodeExpectationsPrinter::PrintBytecodeArray(
+ std::ostream& stream, i::Handle<i::BytecodeArray> bytecode_array) const {
+ PrintFrameSize(stream, bytecode_array);
+ PrintBytecodeSequence(stream, bytecode_array);
+ PrintConstantPool(stream, bytecode_array->constant_pool());
+ PrintHandlers(stream, bytecode_array);
+}
+
+void BytecodeExpectationsPrinter::PrintExpectation(
+ std::ostream& stream, const std::string& snippet) const {
+ std::string source_code =
+ wrap_ ? WrapCodeInFunction(test_function_name_.c_str(), snippet)
+ : snippet;
+
+ v8::Local<v8::Script> script = Compile(source_code.c_str());
+
+ if (execute_) Run(script);
+
+ i::Handle<i::BytecodeArray> bytecode_array =
+ top_level_ ? GetBytecodeArrayForScript(script)
+ : GetBytecodeArrayForGlobal(test_function_name_.c_str());
+
+ stream << "---\n";
+ PrintCodeSnippet(stream, snippet);
+ PrintBytecodeArray(stream, bytecode_array);
+ stream << '\n';
+}
+
+} // namespace interpreter
+} // namespace internal
+} // namespace v8
diff --git a/test/cctest/interpreter/bytecode-expectations-printer.h b/test/cctest/interpreter/bytecode-expectations-printer.h
new file mode 100644
index 0000000..236a7d4
--- /dev/null
+++ b/test/cctest/interpreter/bytecode-expectations-printer.h
@@ -0,0 +1,119 @@
+// Copyright 2016 the V8 project authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef TEST_CCTEST_INTERPRETER_BYTECODE_EXPECTATIONS_PRINTER_H_
+#define TEST_CCTEST_INTERPRETER_BYTECODE_EXPECTATIONS_PRINTER_H_
+
+#include <iostream>
+#include <string>
+#include <vector>
+
+#include "src/interpreter/bytecodes.h"
+#include "src/objects.h"
+
+namespace v8 {
+
+class Isolate;
+
+namespace internal {
+namespace interpreter {
+
+class BytecodeArrayIterator;
+
+class BytecodeExpectationsPrinter final {
+ public:
+ enum class ConstantPoolType {
+ kUnknown,
+ kString,
+ kNumber,
+ kMixed,
+ };
+
+ BytecodeExpectationsPrinter(v8::Isolate* i,
+ ConstantPoolType t = ConstantPoolType::kMixed)
+ : isolate_(i),
+ const_pool_type_(t),
+ execute_(true),
+ wrap_(true),
+ test_function_name_(kDefaultTopFunctionName) {}
+
+ void PrintExpectation(std::ostream& stream, // NOLINT
+ const std::string& snippet) const;
+
+ void set_constant_pool_type(ConstantPoolType const_pool_type) {
+ const_pool_type_ = const_pool_type;
+ }
+ ConstantPoolType const_pool_type() const { return const_pool_type_; }
+
+ void set_execute(bool execute) { execute_ = execute; }
+ bool execute() const { return execute_; }
+
+ void set_wrap(bool wrap) { wrap_ = wrap; }
+ bool wrap() const { return wrap_; }
+
+ void set_top_level(bool top_level) { top_level_ = top_level; }
+ bool top_level() const { return top_level_; }
+
+ void set_test_function_name(const std::string& test_function_name) {
+ test_function_name_ = test_function_name;
+ }
+ std::string test_function_name() const { return test_function_name_; }
+
+ private:
+ void PrintEscapedString(std::ostream& stream, // NOLINT
+ const std::string& string) const;
+ void PrintBytecodeOperand(std::ostream& stream, // NOLINT
+ const BytecodeArrayIterator& bytecode_iter,
+ const Bytecode& bytecode, int op_index,
+ int parameter_count) const;
+ void PrintBytecode(std::ostream& stream, // NOLINT
+ const BytecodeArrayIterator& bytecode_iter,
+ int parameter_count) const;
+ void PrintV8String(std::ostream& stream, // NOLINT
+ i::String* string) const;
+ void PrintConstant(std::ostream& stream, // NOLINT
+ i::Handle<i::Object> constant) const;
+ void PrintFrameSize(std::ostream& stream, // NOLINT
+ i::Handle<i::BytecodeArray> bytecode_array) const;
+ void PrintBytecodeSequence(std::ostream& stream, // NOLINT
+ i::Handle<i::BytecodeArray> bytecode_array) const;
+ void PrintConstantPool(std::ostream& stream, // NOLINT
+ i::FixedArray* constant_pool) const;
+ void PrintCodeSnippet(std::ostream& stream, // NOLINT
+ const std::string& body) const;
+ void PrintBytecodeArray(std::ostream& stream, // NOLINT
+ i::Handle<i::BytecodeArray> bytecode_array) const;
+ void PrintHandlers(std::ostream& stream, // NOLINT
+ i::Handle<i::BytecodeArray> bytecode_array) const;
+
+ v8::Local<v8::String> V8StringFromUTF8(const char* data) const;
+ std::string WrapCodeInFunction(const char* function_name,
+ const std::string& function_body) const;
+
+ v8::Local<v8::Script> Compile(const char* program) const;
+ void Run(v8::Local<v8::Script> script) const;
+ i::Handle<i::BytecodeArray> GetBytecodeArrayForGlobal(
+ const char* global_name) const;
+ i::Handle<v8::internal::BytecodeArray> GetBytecodeArrayForScript(
+ v8::Local<v8::Script> script) const;
+
+ i::Isolate* i_isolate() const {
+ return reinterpret_cast<i::Isolate*>(isolate_);
+ }
+
+ v8::Isolate* isolate_;
+ ConstantPoolType const_pool_type_;
+ bool execute_;
+ bool wrap_;
+ bool top_level_;
+ std::string test_function_name_;
+
+ static const char* const kDefaultTopFunctionName;
+};
+
+} // namespace interpreter
+} // namespace internal
+} // namespace v8
+
+#endif // TEST_CCTEST_INTERPRETER_BYTECODE_EXPECTATIONS_PRINTER_H_
diff --git a/test/cctest/interpreter/generate-bytecode-expectations.cc b/test/cctest/interpreter/generate-bytecode-expectations.cc
new file mode 100644
index 0000000..567aa41
--- /dev/null
+++ b/test/cctest/interpreter/generate-bytecode-expectations.cc
@@ -0,0 +1,469 @@
+// Copyright 2016 the V8 project authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include <cstring>
+#include <fstream>
+
+#include "test/cctest/interpreter/bytecode-expectations-printer.h"
+
+#include "include/libplatform/libplatform.h"
+#include "include/v8.h"
+
+#include "src/base/logging.h"
+#include "src/base/smart-pointers.h"
+#include "src/compiler.h"
+#include "src/interpreter/interpreter.h"
+
+using v8::internal::interpreter::BytecodeExpectationsPrinter;
+
+namespace {
+
+class ProgramOptions final {
+ public:
+ static ProgramOptions FromCommandLine(int argc, char** argv);
+
+ ProgramOptions()
+ : parsing_failed_(false),
+ print_help_(false),
+ read_raw_js_snippet_(false),
+ read_from_stdin_(false),
+ rebaseline_(false),
+ wrap_(true),
+ execute_(true),
+ top_level_(false),
+ legacy_const_(false),
+ do_expressions_(false),
+ const_pool_type_(
+ BytecodeExpectationsPrinter::ConstantPoolType::kMixed) {}
+
+ bool Validate() const;
+ void UpdateFromHeader(std::istream& stream); // NOLINT
+ void PrintHeader(std::ostream& stream) const; // NOLINT
+
+ bool parsing_failed() const { return parsing_failed_; }
+ bool print_help() const { return print_help_; }
+ bool read_raw_js_snippet() const { return read_raw_js_snippet_; }
+ bool read_from_stdin() const { return read_from_stdin_; }
+ bool write_to_stdout() const {
+ return output_filename_.empty() && !rebaseline_;
+ }
+ bool rebaseline() const { return rebaseline_; }
+ bool wrap() const { return wrap_; }
+ bool execute() const { return execute_; }
+ bool top_level() const { return top_level_; }
+ bool legacy_const() const { return legacy_const_; }
+ bool do_expressions() const { return do_expressions_; }
+ BytecodeExpectationsPrinter::ConstantPoolType const_pool_type() const {
+ return const_pool_type_;
+ }
+ std::string input_filename() const { return input_filename_; }
+ std::string output_filename() const { return output_filename_; }
+ std::string test_function_name() const { return test_function_name_; }
+
+ private:
+ bool parsing_failed_;
+ bool print_help_;
+ bool read_raw_js_snippet_;
+ bool read_from_stdin_;
+ bool rebaseline_;
+ bool wrap_;
+ bool execute_;
+ bool top_level_;
+ bool legacy_const_;
+ bool do_expressions_;
+ BytecodeExpectationsPrinter::ConstantPoolType const_pool_type_;
+ std::string input_filename_;
+ std::string output_filename_;
+ std::string test_function_name_;
+};
+
+class ArrayBufferAllocator final : public v8::ArrayBuffer::Allocator {
+ public:
+ void* Allocate(size_t length) override {
+ void* data = AllocateUninitialized(length);
+ if (data != nullptr) memset(data, 0, length);
+ return data;
+ }
+ void* AllocateUninitialized(size_t length) override { return malloc(length); }
+ void Free(void* data, size_t) override { free(data); }
+};
+
+class V8InitializationScope final {
+ public:
+ explicit V8InitializationScope(const char* exec_path);
+ ~V8InitializationScope();
+
+ v8::Platform* platform() const { return platform_.get(); }
+ v8::Isolate* isolate() const { return isolate_; }
+
+ private:
+ v8::base::SmartPointer<v8::Platform> platform_;
+ v8::Isolate* isolate_;
+
+ DISALLOW_COPY_AND_ASSIGN(V8InitializationScope);
+};
+
+BytecodeExpectationsPrinter::ConstantPoolType ParseConstantPoolType(
+ const char* type_string) {
+ if (strcmp(type_string, "number") == 0) {
+ return BytecodeExpectationsPrinter::ConstantPoolType::kNumber;
+ } else if (strcmp(type_string, "string") == 0) {
+ return BytecodeExpectationsPrinter::ConstantPoolType::kString;
+ } else if (strcmp(type_string, "mixed") == 0) {
+ return BytecodeExpectationsPrinter::ConstantPoolType::kMixed;
+ }
+ return BytecodeExpectationsPrinter::ConstantPoolType::kUnknown;
+}
+
+const char* ConstantPoolTypeToString(
+ BytecodeExpectationsPrinter::ConstantPoolType type) {
+ switch (type) {
+ case BytecodeExpectationsPrinter::ConstantPoolType::kNumber:
+ return "number";
+ case BytecodeExpectationsPrinter::ConstantPoolType::kMixed:
+ return "mixed";
+ case BytecodeExpectationsPrinter::ConstantPoolType::kString:
+ return "string";
+ default:
+ UNREACHABLE();
+ return nullptr;
+ }
+}
+
+bool ParseBoolean(const char* string) {
+ if (strcmp(string, "yes") == 0) {
+ return true;
+ } else if (strcmp(string, "no") == 0) {
+ return false;
+ } else {
+ UNREACHABLE();
+ return false;
+ }
+}
+
+const char* BooleanToString(bool value) { return value ? "yes" : "no"; }
+
+// static
+ProgramOptions ProgramOptions::FromCommandLine(int argc, char** argv) {
+ ProgramOptions options;
+
+ for (int i = 1; i < argc; ++i) {
+ if (strcmp(argv[i], "--help") == 0) {
+ options.print_help_ = true;
+ } else if (strcmp(argv[i], "--raw-js") == 0) {
+ options.read_raw_js_snippet_ = true;
+ } else if (strncmp(argv[i], "--pool-type=", 12) == 0) {
+ options.const_pool_type_ = ParseConstantPoolType(argv[i] + 12);
+ } else if (strcmp(argv[i], "--stdin") == 0) {
+ options.read_from_stdin_ = true;
+ } else if (strcmp(argv[i], "--rebaseline") == 0) {
+ options.rebaseline_ = true;
+ } else if (strcmp(argv[i], "--no-wrap") == 0) {
+ options.wrap_ = false;
+ } else if (strcmp(argv[i], "--no-execute") == 0) {
+ options.execute_ = false;
+ } else if (strcmp(argv[i], "--top-level") == 0) {
+ options.top_level_ = true;
+ } else if (strcmp(argv[i], "--legacy-const") == 0) {
+ options.legacy_const_ = true;
+ } else if (strcmp(argv[i], "--do-expressions") == 0) {
+ options.do_expressions_ = true;
+ } else if (strncmp(argv[i], "--output=", 9) == 0) {
+ options.output_filename_ = argv[i] + 9;
+ } else if (strncmp(argv[i], "--test-function-name=", 21) == 0) {
+ options.test_function_name_ = argv[i] + 21;
+ } else if (strncmp(argv[i], "--", 2) != 0) { // It doesn't start with --
+ if (!options.input_filename_.empty()) {
+ std::cerr << "ERROR: More than one input file specified\n";
+ options.parsing_failed_ = true;
+ break;
+ }
+ options.input_filename_ = argv[i];
+ } else {
+ std::cerr << "ERROR: Unknonwn option " << argv[i] << "\n";
+ options.parsing_failed_ = true;
+ break;
+ }
+ }
+
+ return options;
+}
+
+bool ProgramOptions::Validate() const {
+ if (parsing_failed_) return false;
+ if (print_help_) return true;
+
+ if (const_pool_type_ ==
+ BytecodeExpectationsPrinter::ConstantPoolType::kUnknown) {
+ std::cerr << "ERROR: Unknown constant pool type.\n";
+ return false;
+ }
+
+ if (!read_from_stdin_ && input_filename_.empty()) {
+ std::cerr << "ERROR: No input file specified.\n";
+ return false;
+ }
+
+ if (read_from_stdin_ && !input_filename_.empty()) {
+ std::cerr << "ERROR: Reading from stdin, but input files supplied.\n";
+ return false;
+ }
+
+ if (rebaseline_ && read_raw_js_snippet_) {
+ std::cerr << "ERROR: Cannot use --rebaseline on a raw JS snippet.\n";
+ return false;
+ }
+
+ if (top_level_ && !test_function_name_.empty()) {
+ std::cerr << "ERROR: test function name specified while processing "
+ "top level code.\n";
+ return false;
+ }
+
+ return true;
+}
+
+void ProgramOptions::UpdateFromHeader(std::istream& stream) {
+ std::string line;
+
+ // Skip to the beginning of the options header
+ while (std::getline(stream, line)) {
+ if (line == "---") break;
+ }
+
+ while (std::getline(stream, line)) {
+ if (line.compare(0, 11, "pool type: ") == 0) {
+ const_pool_type_ = ParseConstantPoolType(line.c_str() + 11);
+ } else if (line.compare(0, 9, "execute: ") == 0) {
+ execute_ = ParseBoolean(line.c_str() + 9);
+ } else if (line.compare(0, 6, "wrap: ") == 0) {
+ wrap_ = ParseBoolean(line.c_str() + 6);
+ } else if (line.compare(0, 20, "test function name: ") == 0) {
+ test_function_name_ = line.c_str() + 20;
+ } else if (line.compare(0, 11, "top level: ") == 0) {
+ top_level_ = ParseBoolean(line.c_str() + 11);
+ } else if (line.compare(0, 14, "legacy const: ") == 0) {
+ legacy_const_ = ParseBoolean(line.c_str() + 14);
+ } else if (line.compare(0, 16, "do expressions: ") == 0) {
+ do_expressions_ = ParseBoolean(line.c_str() + 16);
+ } else if (line == "---") {
+ break;
+ } else if (line.empty()) {
+ continue;
+ } else {
+ UNREACHABLE();
+ return;
+ }
+ }
+}
+
+void ProgramOptions::PrintHeader(std::ostream& stream) const { // NOLINT
+ stream << "---"
+ "\npool type: "
+ << ConstantPoolTypeToString(const_pool_type_)
+ << "\nexecute: " << BooleanToString(execute_)
+ << "\nwrap: " << BooleanToString(wrap_);
+
+ if (!test_function_name_.empty()) {
+ stream << "\ntest function name: " << test_function_name_;
+ }
+
+ if (top_level_) stream << "\ntop level: yes";
+ if (legacy_const_) stream << "\nlegacy const: yes";
+ if (do_expressions_) stream << "\ndo expressions: yes";
+
+ stream << "\n\n";
+}
+
+V8InitializationScope::V8InitializationScope(const char* exec_path)
+ : platform_(v8::platform::CreateDefaultPlatform()) {
+ i::FLAG_ignition = true;
+ i::FLAG_always_opt = false;
+ i::FLAG_allow_natives_syntax = true;
+
+ v8::V8::InitializeICU();
+ v8::V8::InitializeExternalStartupData(exec_path);
+ v8::V8::InitializePlatform(platform_.get());
+ v8::V8::Initialize();
+
+ ArrayBufferAllocator allocator;
+ v8::Isolate::CreateParams create_params;
+ create_params.array_buffer_allocator = &allocator;
+
+ isolate_ = v8::Isolate::New(create_params);
+}
+
+V8InitializationScope::~V8InitializationScope() {
+ isolate_->Dispose();
+ v8::V8::Dispose();
+ v8::V8::ShutdownPlatform();
+}
+
+std::string ReadRawJSSnippet(std::istream& stream) { // NOLINT
+ std::stringstream body_buffer;
+ CHECK(body_buffer << stream.rdbuf());
+ return body_buffer.str();
+}
+
+bool ReadNextSnippet(std::istream& stream, std::string* string_out) { // NOLINT
+ std::string line;
+ bool found_begin_snippet = false;
+ string_out->clear();
+ while (std::getline(stream, line)) {
+ if (line == "snippet: \"") {
+ found_begin_snippet = true;
+ continue;
+ }
+ if (!found_begin_snippet) continue;
+ if (line == "\"") return true;
+ CHECK_GE(line.size(), 2u); // We should have the indent
+ string_out->append(line.begin() + 2, line.end());
+ *string_out += '\n';
+ }
+ return false;
+}
+
+std::string UnescapeString(const std::string& escaped_string) {
+ std::string unescaped_string;
+ bool previous_was_backslash = false;
+ for (char c : escaped_string) {
+ if (previous_was_backslash) {
+ // If it was not an escape sequence, emit the previous backslash
+ if (c != '\\' && c != '"') unescaped_string += '\\';
+ unescaped_string += c;
+ previous_was_backslash = false;
+ } else {
+ if (c == '\\') {
+ previous_was_backslash = true;
+ // Defer emission to the point where we can check if it was an escape.
+ } else {
+ unescaped_string += c;
+ }
+ }
+ }
+ return unescaped_string;
+}
+
+void ExtractSnippets(std::vector<std::string>* snippet_list,
+ std::istream& body_stream, // NOLINT
+ bool read_raw_js_snippet) {
+ if (read_raw_js_snippet) {
+ snippet_list->push_back(ReadRawJSSnippet(body_stream));
+ } else {
+ std::string snippet;
+ while (ReadNextSnippet(body_stream, &snippet)) {
+ snippet_list->push_back(UnescapeString(snippet));
+ }
+ }
+}
+
+void GenerateExpectationsFile(std::ostream& stream, // NOLINT
+ const std::vector<std::string>& snippet_list,
+ const ProgramOptions& options,
+ const char* exec_path) {
+ V8InitializationScope platform(exec_path);
+ {
+ v8::Isolate::Scope isolate_scope(platform.isolate());
+ v8::HandleScope handle_scope(platform.isolate());
+ v8::Local<v8::Context> context = v8::Context::New(platform.isolate());
+ v8::Context::Scope context_scope(context);
+
+ BytecodeExpectationsPrinter printer(platform.isolate(),
+ options.const_pool_type());
+ printer.set_wrap(options.wrap());
+ printer.set_execute(options.execute());
+ printer.set_top_level(options.top_level());
+ if (!options.test_function_name().empty()) {
+ printer.set_test_function_name(options.test_function_name());
+ }
+
+ if (options.legacy_const()) i::FLAG_legacy_const = true;
+ if (options.do_expressions()) i::FLAG_harmony_do_expressions = true;
+
+ stream << "#\n# Autogenerated by generate-bytecode-expectations\n#\n\n";
+ options.PrintHeader(stream);
+ for (const std::string& snippet : snippet_list) {
+ printer.PrintExpectation(stream, snippet);
+ }
+ }
+}
+
+void PrintUsage(const char* exec_path) {
+ std::cerr
+ << "\nUsage: " << exec_path
+ << " [OPTIONS]... [INPUT FILE]\n\n"
+ "Options:\n"
+ " --help Print this help message.\n"
+ " --raw-js Read raw JavaScript, instead of the output format.\n"
+ " --stdin Read from standard input instead of file.\n"
+ " --rebaseline Rebaseline input snippet file.\n"
+ " --no-wrap Do not wrap the snippet in a function.\n"
+ " --no-execute Do not execute after compilation.\n"
+ " --test-function-name=foo "
+ "Specify the name of the test function.\n"
+ " --top-level Process top level code, not the top-level function."
+ " --legacy-const Enable legacy_const flag.\n"
+ " --do-expressions Enable harmony_do_expressions flag.\n"
+ " --output=file.name\n"
+ " Specify the output file. If not specified, output goes to "
+ "stdout.\n"
+ " --pool-type=(number|string|mixed)\n"
+ " Specify the type of the entries in the constant pool "
+ "(default: mixed).\n"
+ "\n"
+ "When using --rebaseline, flags --no-wrap, --no-execute, "
+ "--test-function-name\nand --pool-type will be overridden by the "
+ "options specified in the input file\nheader.\n\n"
+ "Each raw JavaScript file is interpreted as a single snippet.\n\n"
+ "This tool is intended as a help in writing tests.\n"
+ "Please, DO NOT blindly copy and paste the output "
+ "into the test suite.\n";
+}
+
+} // namespace
+
+int main(int argc, char** argv) {
+ ProgramOptions options = ProgramOptions::FromCommandLine(argc, argv);
+
+ if (!options.Validate() || options.print_help()) {
+ PrintUsage(argv[0]);
+ return options.print_help() ? 0 : 1;
+ }
+
+ std::ifstream input_file_handle;
+ if (!options.read_from_stdin()) {
+ input_file_handle.open(options.input_filename().c_str());
+ if (!input_file_handle.is_open()) {
+ std::cerr << "ERROR: Could not open '" << options.input_filename()
+ << "' for reading.\n";
+ return 2;
+ }
+ }
+ std::istream& input_stream =
+ options.read_from_stdin() ? std::cin : input_file_handle;
+
+ if (options.rebaseline()) {
+ options.UpdateFromHeader(input_stream);
+ CHECK(options.Validate());
+ }
+
+ std::vector<std::string> snippet_list;
+ ExtractSnippets(&snippet_list, input_stream, options.read_raw_js_snippet());
+
+ std::ofstream output_file_handle;
+ if (!options.write_to_stdout()) {
+ output_file_handle.open(options.rebaseline()
+ ? options.input_filename().c_str()
+ : options.output_filename().c_str());
+ if (!output_file_handle.is_open()) {
+ std::cerr << "ERROR: Could not open '" << options.output_filename()
+ << "' for writing.\n";
+ return 3;
+ }
+ }
+ std::ostream& output_stream =
+ options.write_to_stdout() ? std::cout : output_file_handle;
+
+ GenerateExpectationsFile(output_stream, snippet_list, options, argv[0]);
+}
diff --git a/test/cctest/interpreter/test-bytecode-generator.cc b/test/cctest/interpreter/test-bytecode-generator.cc
index 2c06da2..73767eb 100644
--- a/test/cctest/interpreter/test-bytecode-generator.cc
+++ b/test/cctest/interpreter/test-bytecode-generator.cc
@@ -15,6 +15,8 @@
namespace internal {
namespace interpreter {
+static const InstanceType kInstanceTypeDontCare = static_cast<InstanceType>(-1);
+
class BytecodeGeneratorHelper {
public:
const char* kFunctionName = "f";
@@ -24,12 +26,9 @@
BytecodeGeneratorHelper() {
i::FLAG_ignition = true;
- i::FLAG_ignition_fake_try_catch = true;
- i::FLAG_ignition_fallback_on_eval_and_catch = false;
i::FLAG_ignition_filter = StrDup(kFunctionName);
i::FLAG_always_opt = false;
i::FLAG_allow_natives_syntax = true;
- i::FLAG_legacy_const = true;
CcTest::i_isolate()->interpreter()->Initialize();
}
@@ -94,6 +93,7 @@
#define B(x) static_cast<uint8_t>(Bytecode::k##x)
#define U8(x) static_cast<uint8_t>((x) & 0xff)
#define R(x) static_cast<uint8_t>(-(x) & 0xff)
+#define R16(x) U16(-(x))
#define A(x, n) R(helper.kLastParamIndex - (n) + 1 + (x))
#define THIS(n) A(0, n)
#if defined(V8_TARGET_LITTLE_ENDIAN)
@@ -160,6 +160,12 @@
const uint8_t bytecode[2048];
int constant_count;
T constants[C];
+ int handler_count;
+ struct {
+ int start;
+ int end;
+ int handler;
+ } handlers[C];
};
@@ -186,7 +192,9 @@
static void CheckConstant(InstanceType expected, Object* actual) {
- CHECK_EQ(expected, HeapObject::cast(actual)->map()->instance_type());
+ if (expected != kInstanceTypeDontCare) {
+ CHECK_EQ(expected, HeapObject::cast(actual)->map()->instance_type());
+ }
}
@@ -204,6 +212,17 @@
CheckConstant(expected.constants[i], actual->constant_pool()->get(i));
}
}
+ if (expected.handler_count == 0) {
+ CHECK_EQ(CcTest::heap()->empty_fixed_array(), actual->handler_table());
+ } else {
+ HandlerTable* table = HandlerTable::cast(actual->handler_table());
+ CHECK_EQ(expected.handler_count, table->NumberOfRangeEntries());
+ for (int i = 0; i < expected.handler_count; i++) {
+ CHECK_EQ(expected.handlers[i].start, table->GetRangeStart(i));
+ CHECK_EQ(expected.handlers[i].end, table->GetRangeEnd(i));
+ CHECK_EQ(expected.handlers[i].handler, table->GetRangeHandler(i));
+ }
+ }
BytecodeArrayIterator iterator(actual);
int i = 0;
@@ -258,18 +277,110 @@
InitializedHandleScope handle_scope;
BytecodeGeneratorHelper helper;
+ // clang-format off
ExpectedSnippet<int> snippets[] = {
- {"", 0, 1, 2, {B(LdaUndefined), B(Return)}, 0},
- {"return;", 0, 1, 2, {B(LdaUndefined), B(Return)}, 0},
- {"return null;", 0, 1, 2, {B(LdaNull), B(Return)}, 0},
- {"return true;", 0, 1, 2, {B(LdaTrue), B(Return)}, 0},
- {"return false;", 0, 1, 2, {B(LdaFalse), B(Return)}, 0},
- {"return 0;", 0, 1, 2, {B(LdaZero), B(Return)}, 0},
- {"return +1;", 0, 1, 3, {B(LdaSmi8), U8(1), B(Return)}, 0},
- {"return -1;", 0, 1, 3, {B(LdaSmi8), U8(-1), B(Return)}, 0},
- {"return +127;", 0, 1, 3, {B(LdaSmi8), U8(127), B(Return)}, 0},
- {"return -128;", 0, 1, 3, {B(LdaSmi8), U8(-128), B(Return)}, 0},
+ {"",
+ 0,
+ 1,
+ 3,
+ {
+ B(StackCheck), //
+ B(LdaUndefined), //
+ B(Return) //
+ },
+ 0},
+ {"return;",
+ 0,
+ 1,
+ 3,
+ {
+ B(StackCheck), //
+ B(LdaUndefined), //
+ B(Return) //
+ },
+ 0},
+ {"return null;",
+ 0,
+ 1,
+ 3,
+ {
+ B(StackCheck), //
+ B(LdaNull), //
+ B(Return) //
+ },
+ 0},
+ {"return true;",
+ 0,
+ 1,
+ 3,
+ {
+ B(StackCheck), //
+ B(LdaTrue), //
+ B(Return) //
+ },
+ 0},
+ {"return false;",
+ 0,
+ 1,
+ 3,
+ {
+ B(StackCheck), //
+ B(LdaFalse), //
+ B(Return) //
+ },
+ 0},
+ {"return 0;",
+ 0,
+ 1,
+ 3,
+ {
+ B(StackCheck), //
+ B(LdaZero), //
+ B(Return) //
+ },
+ 0},
+ {"return +1;",
+ 0,
+ 1,
+ 4,
+ {
+ B(StackCheck), //
+ B(LdaSmi8), U8(1), //
+ B(Return) //
+ },
+ 0},
+ {"return -1;",
+ 0,
+ 1,
+ 4,
+ {
+ B(StackCheck), //
+ B(LdaSmi8), U8(-1), //
+ B(Return) //
+ },
+ 0},
+ {"return +127;",
+ 0,
+ 1,
+ 4,
+ {
+ B(StackCheck), //
+ B(LdaSmi8), U8(127), //
+ B(Return) //
+ },
+ 0},
+ {"return -128;",
+ 0,
+ 1,
+ 4,
+ {
+ B(StackCheck), //
+ B(LdaSmi8), U8(-128), //
+ B(Return) //
+ },
+ 0},
};
+ // clang-format on
for (size_t i = 0; i < arraysize(snippets); i++) {
Handle<BytecodeArray> bytecode_array =
@@ -283,20 +394,23 @@
InitializedHandleScope handle_scope;
BytecodeGeneratorHelper helper;
+ // clang-format off
ExpectedSnippet<int> snippets[] = {
{"var x = 0; return x;",
kPointerSize,
1,
- 4,
- {B(LdaZero), //
+ 5,
+ {B(StackCheck), //
+ B(LdaZero), //
B(Star), R(0), //
B(Return)},
0},
{"var x = 0; return x + 3;",
2 * kPointerSize,
1,
- 10,
- {B(LdaZero), //
+ 11,
+ {B(StackCheck), //
+ B(LdaZero), //
B(Star), R(0), //
B(Star), R(1), //
B(LdaSmi8), U8(3), //
@@ -306,8 +420,9 @@
{"var x = 0; return x - 3;",
2 * kPointerSize,
1,
- 10,
- {B(LdaZero), //
+ 11,
+ {B(StackCheck), //
+ B(LdaZero), //
B(Star), R(0), //
B(Star), R(1), //
B(LdaSmi8), U8(3), //
@@ -317,8 +432,9 @@
{"var x = 4; return x * 3;",
2 * kPointerSize,
1,
- 11,
- {B(LdaSmi8), U8(4), //
+ 12,
+ {B(StackCheck), //
+ B(LdaSmi8), U8(4), //
B(Star), R(0), //
B(Star), R(1), //
B(LdaSmi8), U8(3), //
@@ -328,8 +444,9 @@
{"var x = 4; return x / 3;",
2 * kPointerSize,
1,
- 11,
- {B(LdaSmi8), U8(4), //
+ 12,
+ {B(StackCheck), //
+ B(LdaSmi8), U8(4), //
B(Star), R(0), //
B(Star), R(1), //
B(LdaSmi8), U8(3), //
@@ -339,8 +456,9 @@
{"var x = 4; return x % 3;",
2 * kPointerSize,
1,
- 11,
- {B(LdaSmi8), U8(4), //
+ 12,
+ {B(StackCheck), //
+ B(LdaSmi8), U8(4), //
B(Star), R(0), //
B(Star), R(1), //
B(LdaSmi8), U8(3), //
@@ -350,8 +468,9 @@
{"var x = 1; return x | 2;",
2 * kPointerSize,
1,
- 11,
- {B(LdaSmi8), U8(1), //
+ 12,
+ {B(StackCheck), //
+ B(LdaSmi8), U8(1), //
B(Star), R(0), //
B(Star), R(1), //
B(LdaSmi8), U8(2), //
@@ -361,8 +480,9 @@
{"var x = 1; return x ^ 2;",
2 * kPointerSize,
1,
- 11,
- {B(LdaSmi8), U8(1), //
+ 12,
+ {B(StackCheck), //
+ B(LdaSmi8), U8(1), //
B(Star), R(0), //
B(Star), R(1), //
B(LdaSmi8), U8(2), //
@@ -372,8 +492,9 @@
{"var x = 1; return x & 2;",
2 * kPointerSize,
1,
- 11,
- {B(LdaSmi8), U8(1), //
+ 12,
+ {B(StackCheck), //
+ B(LdaSmi8), U8(1), //
B(Star), R(0), //
B(Star), R(1), //
B(LdaSmi8), U8(2), //
@@ -383,8 +504,9 @@
{"var x = 10; return x << 3;",
2 * kPointerSize,
1,
- 11,
- {B(LdaSmi8), U8(10), //
+ 12,
+ {B(StackCheck), //
+ B(LdaSmi8), U8(10), //
B(Star), R(0), //
B(Star), R(1), //
B(LdaSmi8), U8(3), //
@@ -394,8 +516,9 @@
{"var x = 10; return x >> 3;",
2 * kPointerSize,
1,
- 11,
- {B(LdaSmi8), U8(10), //
+ 12,
+ {B(StackCheck), //
+ B(LdaSmi8), U8(10), //
B(Star), R(0), //
B(Star), R(1), //
B(LdaSmi8), U8(3), //
@@ -405,8 +528,9 @@
{"var x = 10; return x >>> 3;",
2 * kPointerSize,
1,
- 11,
- {B(LdaSmi8), U8(10), //
+ 12,
+ {B(StackCheck), //
+ B(LdaSmi8), U8(10), //
B(Star), R(0), //
B(Star), R(1), //
B(LdaSmi8), U8(3), //
@@ -416,12 +540,15 @@
{"var x = 0; return (x, 3);",
1 * kPointerSize,
1,
- 6,
- {B(LdaZero), //
+ 7,
+ {B(StackCheck), //
+ B(LdaZero), //
B(Star), R(0), //
B(LdaSmi8), U8(3), //
B(Return)},
- 0}};
+ 0},
+ };
+ // clang-format on
for (size_t i = 0; i < arraysize(snippets); i++) {
Handle<BytecodeArray> bytecode_array =
@@ -435,12 +562,14 @@
InitializedHandleScope handle_scope;
BytecodeGeneratorHelper helper;
+ // clang-format off
ExpectedSnippet<int> snippets[] = {
{"var x = 0; return x || 3;",
1 * kPointerSize,
1,
- 8,
- {B(LdaZero), //
+ 9,
+ {B(StackCheck), //
+ B(LdaZero), //
B(Star), R(0), //
B(JumpIfToBooleanTrue), U8(4), //
B(LdaSmi8), U8(3), //
@@ -449,8 +578,9 @@
{"var x = 0; return (x == 1) || 3;",
2 * kPointerSize,
1,
- 14,
- {B(LdaZero), //
+ 15,
+ {B(StackCheck), //
+ B(LdaZero), //
B(Star), R(0), //
B(Star), R(1), //
B(LdaSmi8), U8(1), //
@@ -462,8 +592,9 @@
{"var x = 0; return x && 3;",
1 * kPointerSize,
1,
- 8,
- {B(LdaZero), //
+ 9,
+ {B(StackCheck), //
+ B(LdaZero), //
B(Star), R(0), //
B(JumpIfToBooleanFalse), U8(4), //
B(LdaSmi8), U8(3), //
@@ -472,8 +603,9 @@
{"var x = 0; return (x == 0) && 3;",
2 * kPointerSize,
1,
- 13,
- {B(LdaZero), //
+ 14,
+ {B(StackCheck), //
+ B(LdaZero), //
B(Star), R(0), //
B(Star), R(1), //
B(LdaZero), //
@@ -485,8 +617,9 @@
{"var x = 0; return x || (1, 2, 3);",
1 * kPointerSize,
1,
- 8,
- {B(LdaZero), //
+ 9,
+ {B(StackCheck), //
+ B(LdaZero), //
B(Star), R(0), //
B(JumpIfToBooleanTrue), U8(4), //
B(LdaSmi8), U8(3), //
@@ -495,8 +628,9 @@
{"var a = 2, b = 3, c = 4; return a || (a, b, a, b, c = 5, 3);",
3 * kPointerSize,
1,
- 31,
- {B(LdaSmi8), U8(2), //
+ 32,
+ {B(StackCheck), //
+ B(LdaSmi8), U8(2), //
B(Star), R(0), //
B(LdaSmi8), U8(3), //
B(Star), R(1), //
@@ -518,8 +652,9 @@
"3);",
3 * kPointerSize,
1,
- 275,
- {B(LdaSmi8), U8(1), //
+ 276,
+ {B(StackCheck), //
+ B(LdaSmi8), U8(1), //
B(Star), R(0), //
B(LdaSmi8), U8(2), //
B(Star), R(1), //
@@ -541,8 +676,9 @@
"3);",
3 * kPointerSize,
1,
- 274,
- {B(LdaZero), //
+ 275,
+ {B(StackCheck), //
+ B(LdaZero), //
B(Star), R(0), //
B(LdaSmi8), U8(2), //
B(Star), R(1), //
@@ -564,8 +700,9 @@
"3);",
4 * kPointerSize,
1,
- 281,
- {B(LdaSmi8), U8(1), //
+ 282,
+ {B(StackCheck), //
+ B(LdaSmi8), U8(1), //
B(Star), R(0), //
B(LdaSmi8), U8(2), //
B(Star), R(1), //
@@ -590,8 +727,9 @@
"3);",
4 * kPointerSize,
1,
- 280,
- {B(LdaZero), //
+ 281,
+ {B(StackCheck), //
+ B(LdaZero), //
B(Star), R(0), //
B(LdaSmi8), U8(2), //
B(Star), R(1), //
@@ -614,22 +752,25 @@
{"return 0 && 3;",
0 * kPointerSize,
1,
- 2,
- {B(LdaZero), //
+ 3,
+ {B(StackCheck), //
+ B(LdaZero), //
B(Return)},
0},
{"return 1 || 3;",
0 * kPointerSize,
1,
- 3,
- {B(LdaSmi8), U8(1), //
+ 4,
+ {B(StackCheck), //
+ B(LdaSmi8), U8(1), //
B(Return)},
0},
{"var x = 1; return x && 3 || 0, 1;",
1 * kPointerSize,
1,
- 14,
- {B(LdaSmi8), U8(1), //
+ 15,
+ {B(StackCheck), //
+ B(LdaSmi8), U8(1), //
B(Star), R(0), //
B(JumpIfToBooleanFalse), U8(4), //
B(LdaSmi8), U8(3), //
@@ -637,7 +778,9 @@
B(LdaZero), //
B(LdaSmi8), U8(1), //
B(Return)},
- 0}};
+ 0}
+ };
+ // clang-format on
for (size_t i = 0; i < arraysize(snippets); i++) {
Handle<BytecodeArray> bytecode_array =
@@ -651,42 +794,54 @@
InitializedHandleScope handle_scope;
BytecodeGeneratorHelper helper;
+ // clang-format off
ExpectedSnippet<int> snippets[] = {
{"function f() { return this; }",
0,
1,
- 3,
- {B(Ldar), THIS(1), B(Return)},
+ 4,
+ {B(StackCheck), //
+ B(Ldar), THIS(1), //
+ B(Return)},
0},
{"function f(arg1) { return arg1; }",
0,
2,
- 3,
- {B(Ldar), A(1, 2), B(Return)},
+ 4,
+ {B(StackCheck), //
+ B(Ldar), A(1, 2), //
+ B(Return)},
0},
{"function f(arg1) { return this; }",
0,
2,
- 3,
- {B(Ldar), THIS(2), B(Return)},
+ 4,
+ {B(StackCheck), //
+ B(Ldar), THIS(2), //
+ B(Return)},
0},
{"function f(arg1, arg2, arg3, arg4, arg5, arg6, arg7) { return arg4; }",
0,
8,
- 3,
- {B(Ldar), A(4, 8), B(Return)},
+ 4,
+ {B(StackCheck), //
+ B(Ldar), A(4, 8), //
+ B(Return)},
0},
{"function f(arg1, arg2, arg3, arg4, arg5, arg6, arg7) { return this; }",
0,
8,
- 3,
- {B(Ldar), THIS(8), B(Return)},
+ 4,
+ {B(StackCheck), //
+ B(Ldar), THIS(8), //
+ B(Return)},
0},
{"function f(arg1) { arg1 = 1; }",
0,
2,
- 6,
- {B(LdaSmi8), U8(1), //
+ 7,
+ {B(StackCheck), //
+ B(LdaSmi8), U8(1), //
B(Star), A(1, 2), //
B(LdaUndefined), //
B(Return)},
@@ -694,13 +849,15 @@
{"function f(arg1, arg2, arg3, arg4) { arg2 = 1; }",
0,
5,
- 6,
- {B(LdaSmi8), U8(1), //
+ 7,
+ {B(StackCheck), //
+ B(LdaSmi8), U8(1), //
B(Star), A(2, 5), //
B(LdaUndefined), //
B(Return)},
0},
};
+ // clang-format on
for (size_t i = 0; i < arraysize(snippets); i++) {
Handle<BytecodeArray> bytecode_array =
@@ -714,12 +871,14 @@
InitializedHandleScope handle_scope;
BytecodeGeneratorHelper helper;
+ // clang-format off
ExpectedSnippet<int> snippets[] = {
{"return 12345678;",
0,
1,
- 3,
+ 4,
{
+ B(StackCheck), //
B(LdaConstant), U8(0), //
B(Return) //
},
@@ -728,8 +887,9 @@
{"var a = 1234; return 5678;",
1 * kPointerSize,
1,
- 7,
+ 8,
{
+ B(StackCheck), //
B(LdaConstant), U8(0), //
B(Star), R(0), //
B(LdaConstant), U8(1), //
@@ -740,15 +900,18 @@
{"var a = 1234; return 1234;",
1 * kPointerSize,
1,
- 7,
+ 8,
{
+ B(StackCheck), //
B(LdaConstant), U8(0), //
B(Star), R(0), //
B(LdaConstant), U8(0), //
B(Return) //
},
1,
- {1234}}};
+ {1234}}
+ };
+ // clang-format on
for (size_t i = 0; i < arraysize(snippets); i++) {
Handle<BytecodeArray> bytecode_array =
@@ -764,12 +927,14 @@
int wide_idx = 0;
+ // clang-format off
ExpectedSnippet<double, 257> snippets[] = {
{"return 1.2;",
0,
1,
- 3,
+ 4,
{
+ B(StackCheck), //
B(LdaConstant), U8(0), //
B(Return) //
},
@@ -778,8 +943,9 @@
{"var a = 1.2; return 2.6;",
1 * kPointerSize,
1,
- 7,
+ 8,
{
+ B(StackCheck), //
B(LdaConstant), U8(0), //
B(Star), R(0), //
B(LdaConstant), U8(1), //
@@ -790,8 +956,9 @@
{"var a = 3.14; return 3.14;",
1 * kPointerSize,
1,
- 7,
+ 8,
{
+ B(StackCheck), //
B(LdaConstant), U8(0), //
B(Star), R(0), //
B(LdaConstant), U8(1), //
@@ -804,8 +971,9 @@
" a = 3.14;",
1 * kPointerSize,
1,
- 1031,
+ 1032,
{
+ B(StackCheck), //
REPEAT_256(COMMA, //
B(LdaConstant), U8(wide_idx++), //
B(Star), R(0)), //
@@ -818,6 +986,8 @@
{REPEAT_256(COMMA, 1.414),
3.14}}
};
+ // clang-format on
+
for (size_t i = 0; i < arraysize(snippets); i++) {
Handle<BytecodeArray> bytecode_array =
helper.MakeBytecodeForFunctionBody(snippets[i].code_snippet);
@@ -830,12 +1000,14 @@
InitializedHandleScope handle_scope;
BytecodeGeneratorHelper helper;
+ // clang-format off
ExpectedSnippet<const char*> snippets[] = {
{"return \"This is a string\";",
0,
1,
- 3,
+ 4,
{
+ B(StackCheck), //
B(LdaConstant), U8(0), //
B(Return) //
},
@@ -844,8 +1016,9 @@
{"var a = \"First string\"; return \"Second string\";",
1 * kPointerSize,
1,
- 7,
+ 8,
{
+ B(StackCheck), //
B(LdaConstant), U8(0), //
B(Star), R(0), //
B(LdaConstant), U8(1), //
@@ -856,15 +1029,18 @@
{"var a = \"Same string\"; return \"Same string\";",
1 * kPointerSize,
1,
- 7,
+ 8,
{
+ B(StackCheck), //
B(LdaConstant), U8(0), //
B(Star), R(0), //
B(LdaConstant), U8(0), //
B(Return) //
},
1,
- {"Same string"}}};
+ {"Same string"}}
+ };
+ // clang-format on
for (size_t i = 0; i < arraysize(snippets); i++) {
Handle<BytecodeArray> bytecode_array =
@@ -889,18 +1065,18 @@
// These are a hack used by the LoadICXXXWide tests below.
int wide_idx_1 = vector->GetIndex(slot1) - 2;
int wide_idx_2 = vector->GetIndex(slot1) - 2;
- int wide_idx_3 = vector->GetIndex(slot1) - 2;
- int wide_idx_4 = vector->GetIndex(slot1) - 2;
+ // clang-format off
ExpectedSnippet<const char*> snippets[] = {
{"function f(a) { return a.name; }\nf({name : \"test\"})",
1 * kPointerSize,
2,
- 9,
+ 10,
{
+ B(StackCheck), //
B(Ldar), A(1, 2), //
B(Star), R(0), //
- B(LoadICSloppy), R(0), U8(0), U8(vector->GetIndex(slot1)), //
+ B(LoadIC), R(0), U8(0), U8(vector->GetIndex(slot1)), //
B(Return), //
},
1,
@@ -908,11 +1084,12 @@
{"function f(a) { return a[\"key\"]; }\nf({key : \"test\"})",
1 * kPointerSize,
2,
- 9,
+ 10,
{
+ B(StackCheck), //
B(Ldar), A(1, 2), //
B(Star), R(0), //
- B(LoadICSloppy), R(0), U8(0), U8(vector->GetIndex(slot1)), //
+ B(LoadIC), R(0), U8(0), U8(vector->GetIndex(slot1)), //
B(Return) //
},
1,
@@ -920,24 +1097,26 @@
{"function f(a) { return a[100]; }\nf({100 : \"test\"})",
1 * kPointerSize,
2,
- 10,
+ 11,
{
+ B(StackCheck), //
B(Ldar), A(1, 2), //
B(Star), R(0), //
B(LdaSmi8), U8(100), //
- B(KeyedLoadICSloppy), R(0), U8(vector->GetIndex(slot1)), //
+ B(KeyedLoadIC), R(0), U8(vector->GetIndex(slot1)), //
B(Return) //
},
0},
{"function f(a, b) { return a[b]; }\nf({arg : \"test\"}, \"arg\")",
1 * kPointerSize,
3,
- 10,
+ 11,
{
+ B(StackCheck), //
B(Ldar), A(1, 3), //
B(Star), R(0), //
B(Ldar), A(1, 2), //
- B(KeyedLoadICSloppy), R(0), U8(vector->GetIndex(slot1)), //
+ B(KeyedLoadIC), R(0), U8(vector->GetIndex(slot1)), //
B(Return) //
},
0},
@@ -945,45 +1124,21 @@
"f({\"-124\" : \"test\", name : 123 })",
2 * kPointerSize,
2,
- 20,
+ 21,
{
+ B(StackCheck), //
B(Ldar), A(1, 2), //
B(Star), R(1), //
- B(LoadICSloppy), R(1), U8(0), U8(vector->GetIndex(slot1)), //
+ B(LoadIC), R(1), U8(0), U8(vector->GetIndex(slot1)), //
B(Star), R(0), //
B(Ldar), A(1, 2), //
B(Star), R(1), //
B(LdaSmi8), U8(-124), //
- B(KeyedLoadICSloppy), R(1), U8(vector->GetIndex(slot2)), //
+ B(KeyedLoadIC), R(1), U8(vector->GetIndex(slot2)), //
B(Return), //
},
1,
{"name"}},
- {"function f(a) { \"use strict\"; return a.name; }\nf({name : \"test\"})",
- 1 * kPointerSize,
- 2,
- 9,
- {
- B(Ldar), A(1, 2), //
- B(Star), R(0), //
- B(LoadICStrict), R(0), U8(0), U8(vector->GetIndex(slot1)), //
- B(Return), //
- },
- 1,
- {"name"}},
- {"function f(a, b) { \"use strict\"; return a[b]; }\n"
- "f({arg : \"test\"}, \"arg\")",
- 1 * kPointerSize,
- 3,
- 10,
- {
- B(Ldar), A(1, 3), //
- B(Star), R(0), //
- B(Ldar), A(2, 3), //
- B(KeyedLoadICStrict), R(0), U8(vector->GetIndex(slot1)), //
- B(Return), //
- },
- 0},
{"function f(a) {\n"
" var b;\n"
"b = a.name;"
@@ -992,48 +1147,22 @@
"f({name : \"test\"})\n",
2 * kPointerSize,
2,
- 1291,
+ 1292,
{
+ B(StackCheck), //
B(Ldar), A(1, 2), //
B(Star), R(1), //
- B(LoadICSloppy), R(1), U8(0), U8(wide_idx_1 += 2), //
+ B(LoadIC), R(1), U8(0), U8(wide_idx_1 += 2), //
B(Star), R(0), //
REPEAT_127(COMMA, //
B(Ldar), A(1, 2), //
B(Star), R(1), //
- B(LoadICSloppy), R(1), U8(0), //
+ B(LoadIC), R(1), U8(0), //
U8((wide_idx_1 += 2)), //
B(Star), R(0)), //
B(Ldar), A(1, 2), //
B(Star), R(1), //
- B(LoadICSloppyWide), R(1), U16(0), U16(wide_idx_1 + 2), //
- B(Return), //
- },
- 1,
- {"name"}},
- {"function f(a) {\n"
- " 'use strict'; var b;\n"
- " b = a.name;\n"
- REPEAT_127(SPACE, " b = a.name; ")
- " return a.name; }\n"
- "f({name : \"test\"})\n",
- 2 * kPointerSize,
- 2,
- 1291,
- {
- B(Ldar), A(1, 2), //
- B(Star), R(1), //
- B(LoadICStrict), R(1), U8(0), U8((wide_idx_2 += 2)), //
- B(Star), R(0), //
- REPEAT_127(COMMA, //
- B(Ldar), A(1, 2), //
- B(Star), R(1), //
- B(LoadICStrict), R(1), U8(0), //
- U8((wide_idx_2 += 2)), //
- B(Star), R(0)), //
- B(Ldar), A(1, 2), //
- B(Star), R(1), //
- B(LoadICStrictWide), R(1), U16(0), U16(wide_idx_2 + 2), //
+ B(LoadICWide), R(1), U16(0), U16(wide_idx_1 + 2), //
B(Return), //
},
1,
@@ -1046,53 +1175,29 @@
"f({name : \"test\"}, \"name\")\n",
2 * kPointerSize,
3,
- 1419,
+ 1420,
{
+ B(StackCheck), //
B(Ldar), A(1, 3), //
B(Star), R(1), //
B(Ldar), A(2, 3), //
- B(KeyedLoadICSloppy), R(1), U8((wide_idx_3 += 2)), //
+ B(KeyedLoadIC), R(1), U8((wide_idx_2 += 2)), //
B(Star), R(0), //
REPEAT_127(COMMA, //
B(Ldar), A(1, 3), //
B(Star), R(1), //
B(Ldar), A(2, 3), //
- B(KeyedLoadICSloppy), R(1), U8((wide_idx_3 += 2)), //
+ B(KeyedLoadIC), R(1), U8((wide_idx_2 += 2)), //
B(Star), R(0)), //
B(Ldar), A(1, 3), //
B(Star), R(1), //
B(Ldar), A(2, 3), //
- B(KeyedLoadICSloppyWide), R(1), U16(wide_idx_3 + 2), //
- B(Return), //
- }},
- {"function f(a, b) {\n"
- " 'use strict'; var c;\n"
- " c = a[b];"
- REPEAT_127(SPACE, " c = a[b]; ")
- " return a[b]; }\n"
- "f({name : \"test\"}, \"name\")\n",
- 2 * kPointerSize,
- 3,
- 1419,
- {
- B(Ldar), A(1, 3), //
- B(Star), R(1), //
- B(Ldar), A(2, 3), //
- B(KeyedLoadICStrict), R(1), U8((wide_idx_4 += 2)), //
- B(Star), R(0), //
- REPEAT_127(COMMA, //
- B(Ldar), A(1, 3), //
- B(Star), R(1), //
- B(Ldar), A(2, 3), //
- B(KeyedLoadICStrict), R(1), U8((wide_idx_4 += 2)), //
- B(Star), R(0)), //
- B(Ldar), A(1, 3), //
- B(Star), R(1), //
- B(Ldar), A(2, 3), //
- B(KeyedLoadICStrictWide), R(1), U16(wide_idx_4 + 2), //
+ B(KeyedLoadICWide), R(1), U16(wide_idx_2 + 2), //
B(Return), //
}},
};
+ // clang-format on
+
for (size_t i = 0; i < arraysize(snippets); i++) {
Handle<BytecodeArray> bytecode_array =
helper.MakeBytecode(snippets[i].code_snippet, helper.kFunctionName);
@@ -1119,12 +1224,14 @@
int wide_idx_3 = vector->GetIndex(slot1) - 2;
int wide_idx_4 = vector->GetIndex(slot1) - 2;
+ // clang-format off
ExpectedSnippet<const char*> snippets[] = {
{"function f(a) { a.name = \"val\"; }\nf({name : \"test\"})",
kPointerSize,
2,
- 12,
+ 13,
{
+ B(StackCheck), //
B(Ldar), A(1, 2), //
B(Star), R(0), //
B(LdaConstant), U8(0), //
@@ -1137,8 +1244,9 @@
{"function f(a) { a[\"key\"] = \"val\"; }\nf({key : \"test\"})",
kPointerSize,
2,
- 12,
+ 13,
{
+ B(StackCheck), //
B(Ldar), A(1, 2), //
B(Star), R(0), //
B(LdaConstant), U8(0), //
@@ -1151,8 +1259,9 @@
{"function f(a) { a[100] = \"val\"; }\nf({100 : \"test\"})",
2 * kPointerSize,
2,
- 16,
+ 17,
{
+ B(StackCheck), //
B(Ldar), A(1, 2), //
B(Star), R(0), //
B(LdaSmi8), U8(100), //
@@ -1168,8 +1277,9 @@
{"function f(a, b) { a[b] = \"val\"; }\nf({arg : \"test\"}, \"arg\")",
2 * kPointerSize,
3,
- 16,
+ 17,
{
+ B(StackCheck), //
B(Ldar), A(1, 3), //
B(Star), R(0), //
B(Ldar), A(2, 3), //
@@ -1186,14 +1296,15 @@
"f({\"-124\" : \"test\", name : 123 })",
2 * kPointerSize,
2,
- 19,
+ 20,
{
+ B(StackCheck), //
B(Ldar), A(1, 2), //
B(Star), R(0), //
B(Ldar), A(1, 2), //
B(Star), R(1), //
B(LdaSmi8), U8(-124), //
- B(KeyedLoadICSloppy), R(1), U8(vector->GetIndex(slot1)), //
+ B(KeyedLoadIC), R(1), U8(vector->GetIndex(slot1)), //
B(StoreICSloppy), R(0), U8(0), U8(vector->GetIndex(slot2)), //
B(LdaUndefined), //
B(Return), //
@@ -1204,8 +1315,9 @@
"f({name : \"test\"})",
kPointerSize,
2,
- 12,
+ 13,
{
+ B(StackCheck), //
B(Ldar), A(1, 2), //
B(Star), R(0), //
B(LdaConstant), U8(0), //
@@ -1219,8 +1331,9 @@
"f({arg : \"test\"}, \"arg\")",
2 * kPointerSize,
3,
- 16,
+ 17,
{
+ B(StackCheck), //
B(Ldar), A(1, 3), //
B(Star), R(0), //
B(Ldar), A(2, 3), //
@@ -1239,8 +1352,9 @@
"f({name : \"test\"})\n",
kPointerSize,
2,
- 1294,
+ 1295,
{
+ B(StackCheck), //
B(Ldar), A(1, 2), //
B(Star), R(0), //
B(LdaSmi8), U8(1), //
@@ -1268,8 +1382,9 @@
"f({name : \"test\"})\n",
kPointerSize,
2,
- 1294,
+ 1295,
{
+ B(StackCheck), //
B(Ldar), A(1, 2), //
B(Star), R(0), //
B(LdaSmi8), U8(1), //
@@ -1296,8 +1411,9 @@
"f({name : \"test\"})\n",
2 * kPointerSize,
3,
- 1809,
+ 1810,
{
+ B(StackCheck), //
B(Ldar), A(1, 3), //
B(Star), R(0), //
B(Ldar), A(2, 3), //
@@ -1329,8 +1445,9 @@
"f({name : \"test\"})\n",
2 * kPointerSize,
3,
- 1809,
+ 1810,
{
+ B(StackCheck), //
B(Ldar), A(1, 3), //
B(Star), R(0), //
B(Ldar), A(2, 3), //
@@ -1353,7 +1470,10 @@
B(KeyedStoreICStrictWide), R(0), R(1), U16(wide_idx_4 + 2), //
B(LdaUndefined), //
B(Return), //
- }}};
+ }}
+ };
+ // clang-format on
+
for (size_t i = 0; i < arraysize(snippets); i++) {
Handle<BytecodeArray> bytecode_array =
helper.MakeBytecode(snippets[i].code_snippet, helper.kFunctionName);
@@ -1380,17 +1500,19 @@
// These are a hack used by the CallWide test below.
int wide_idx = vector->GetIndex(slot1) - 2;
+ // clang-format off
ExpectedSnippet<const char*> snippets[] = {
{"function f(a) { return a.func(); }\nf(" FUNC_ARG ")",
2 * kPointerSize,
2,
- 16,
+ 17,
{
+ B(StackCheck), //
B(Ldar), A(1, 2), //
B(Star), R(1), //
- B(LoadICSloppy), R(1), U8(0), U8(vector->GetIndex(slot2)), //
+ B(LoadIC), R(1), U8(0), U8(vector->GetIndex(slot2)), //
B(Star), R(0), //
- B(Call), R(0), R(1), U8(0), U8(vector->GetIndex(slot1)), //
+ B(Call), R(0), R(1), U8(1), U8(vector->GetIndex(slot1)), //
B(Return), //
},
1,
@@ -1398,17 +1520,18 @@
{"function f(a, b, c) { return a.func(b, c); }\nf(" FUNC_ARG ", 1, 2)",
4 * kPointerSize,
4,
- 24,
+ 25,
{
+ B(StackCheck), //
B(Ldar), A(1, 4), //
B(Star), R(1), //
- B(LoadICSloppy), R(1), U8(0), U8(vector->GetIndex(slot2)), //
+ B(LoadIC), R(1), U8(0), U8(vector->GetIndex(slot2)), //
B(Star), R(0), //
B(Ldar), A(2, 4), //
B(Star), R(2), //
B(Ldar), A(3, 4), //
B(Star), R(3), //
- B(Call), R(0), R(1), U8(2), U8(vector->GetIndex(slot1)), //
+ B(Call), R(0), R(1), U8(3), U8(vector->GetIndex(slot1)), //
B(Return) //
},
1,
@@ -1416,11 +1539,12 @@
{"function f(a, b) { return a.func(b + b, b); }\nf(" FUNC_ARG ", 1)",
4 * kPointerSize,
3,
- 30,
+ 31,
{
+ B(StackCheck), //
B(Ldar), A(1, 3), //
B(Star), R(1), //
- B(LoadICSloppy), R(1), U8(0), U8(vector->GetIndex(slot2)), //
+ B(LoadIC), R(1), U8(0), U8(vector->GetIndex(slot2)), //
B(Star), R(0), //
B(Ldar), A(2, 3), //
B(Star), R(3), //
@@ -1429,36 +1553,38 @@
B(Star), R(2), //
B(Ldar), A(2, 3), //
B(Star), R(3), //
- B(Call), R(0), R(1), U8(2), U8(vector->GetIndex(slot1)), //
+ B(Call), R(0), R(1), U8(3), U8(vector->GetIndex(slot1)), //
B(Return), //
},
1,
{"func"}},
{"function f(a) {\n"
- " a.func;\n"
- REPEAT_127(SPACE, " a.func;\n")
- " return a.func(); }\nf(" FUNC_ARG ")",
+ " a.func;\n" REPEAT_127(
+ SPACE, " a.func;\n") " return a.func(); }\nf(" FUNC_ARG ")",
2 * kPointerSize,
2,
- 1044,
+ 1047,
{
+ B(StackCheck), //
B(Ldar), A(1, 2), //
B(Star), R(0), //
- B(LoadICSloppy), R(0), U8(0), U8(wide_idx += 2), //
+ B(LoadIC), R(0), U8(0), U8(wide_idx += 2), //
REPEAT_127(COMMA, //
B(Ldar), A(1, 2), //
B(Star), R(0), //
- B(LoadICSloppy), R(0), U8(0), U8((wide_idx += 2))), //
+ B(LoadIC), R(0), U8(0), U8((wide_idx += 2))), //
B(Ldar), A(1, 2), //
B(Star), R(1), //
- B(LoadICSloppyWide), R(1), U16(0), U16(wide_idx + 4), //
+ B(LoadICWide), R(1), U16(0), U16(wide_idx + 4), //
B(Star), R(0), //
- B(CallWide), R(0), R(1), U16(0), U16(wide_idx + 2), //
+ B(CallWide), R16(0), R16(1), U16(1), U16(wide_idx + 2), //
B(Return), //
},
1,
{"func"}},
};
+ // clang-format on
+
for (size_t i = 0; i < arraysize(snippets); i++) {
Handle<BytecodeArray> bytecode_array =
helper.MakeBytecode(snippets[i].code_snippet, helper.kFunctionName);
@@ -1480,15 +1606,16 @@
// These are a hack used by the LdaGlobalXXXWide tests below.
int wide_idx_1 = vector->GetIndex(slot) - 2;
- int wide_idx_2 = vector->GetIndex(slot) - 2;
+ // clang-format off
ExpectedSnippet<const char*> snippets[] = {
{"var a = 1;\nfunction f() { return a; }\nf()",
0,
1,
- 4,
+ 5,
{
- B(LdaGlobalSloppy), U8(0), U8(vector->GetIndex(slot)), //
+ B(StackCheck), //
+ B(LdaGlobal), U8(0), U8(vector->GetIndex(slot)), //
B(Return) //
},
1,
@@ -1496,29 +1623,21 @@
{"function t() { }\nfunction f() { return t; }\nf()",
0,
1,
- 4,
+ 5,
{
- B(LdaGlobalSloppy), U8(0), U8(vector->GetIndex(slot)), //
+ B(StackCheck), //
+ B(LdaGlobal), U8(0), U8(vector->GetIndex(slot)), //
B(Return) //
},
1,
{"t"}},
- {"'use strict'; var a = 1;\nfunction f() { return a; }\nf()",
- 0,
- 1,
- 4,
- {
- B(LdaGlobalStrict), U8(0), U8(vector->GetIndex(slot)), //
- B(Return) //
- },
- 1,
- {"a"}},
{"a = 1;\nfunction f() { return a; }\nf()",
0,
1,
- 4,
+ 5,
{
- B(LdaGlobalSloppy), U8(0), U8(vector->GetIndex(slot)), //
+ B(StackCheck), //
+ B(LdaGlobal), U8(0), U8(vector->GetIndex(slot)), //
B(Return) //
},
1,
@@ -1531,44 +1650,23 @@
"}\nf({name: 1});",
kPointerSize,
2,
- 1030,
+ 1031,
{
+ B(StackCheck), //
B(Ldar), A(1, 2), //
B(Star), R(0), //
- B(LoadICSloppy), R(0), U8(0), U8(wide_idx_1 += 2), //
+ B(LoadIC), R(0), U8(0), U8(wide_idx_1 += 2), //
REPEAT_127(COMMA, //
B(Ldar), A(1, 2), //
B(Star), R(0), //
- B(LoadICSloppy), R(0), U8(0), U8(wide_idx_1 += 2)), //
- B(LdaGlobalSloppyWide), U16(1), U16(wide_idx_1 + 2), //
- B(Return), //
- },
- 2,
- {"name", "a"}},
- {"a = 1;"
- "function f(b) {\n"
- " 'use strict';\n"
- " b.name\n"
- REPEAT_127(SPACE, "b.name; ")
- " return a;"
- "}\nf({name: 1});",
- kPointerSize,
- 2,
- 1030,
- {
- B(Ldar), A(1, 2), //
- B(Star), R(0), //
- B(LoadICStrict), R(0), U8(0), U8(wide_idx_2 += 2), //
- REPEAT_127(COMMA, //
- B(Ldar), A(1, 2), //
- B(Star), R(0), //
- B(LoadICStrict), R(0), U8(0), U8(wide_idx_2 += 2)), //
- B(LdaGlobalStrictWide), U16(1), U16(wide_idx_2 + 2), //
+ B(LoadIC), R(0), U8(0), U8(wide_idx_1 += 2)), //
+ B(LdaGlobalWide), U16(1), U16(wide_idx_1 + 2), //
B(Return), //
},
2,
{"name", "a"}},
};
+ // clang-format on
for (size_t i = 0; i < arraysize(snippets); i++) {
Handle<BytecodeArray> bytecode_array =
@@ -1593,12 +1691,14 @@
int wide_idx_1 = vector->GetIndex(slot) - 2;
int wide_idx_2 = vector->GetIndex(slot) - 2;
+ // clang-format off
ExpectedSnippet<const char*> snippets[] = {
{"var a = 1;\nfunction f() { a = 2; }\nf()",
0,
1,
- 7,
+ 8,
{
+ B(StackCheck), //
B(LdaSmi8), U8(2), //
B(StaGlobalSloppy), U8(0), U8(vector->GetIndex(slot)), //
B(LdaUndefined), //
@@ -1609,8 +1709,9 @@
{"var a = \"test\"; function f(b) { a = b; }\nf(\"global\")",
0,
2,
- 7,
+ 8,
{
+ B(StackCheck), //
B(Ldar), R(helper.kLastParamIndex), //
B(StaGlobalSloppy), U8(0), U8(vector->GetIndex(slot)), //
B(LdaUndefined), //
@@ -1621,8 +1722,9 @@
{"'use strict'; var a = 1;\nfunction f() { a = 2; }\nf()",
0,
1,
- 7,
+ 8,
{
+ B(StackCheck), //
B(LdaSmi8), U8(2), //
B(StaGlobalStrict), U8(0), U8(vector->GetIndex(slot)), //
B(LdaUndefined), //
@@ -1633,8 +1735,9 @@
{"a = 1;\nfunction f() { a = 2; }\nf()",
0,
1,
- 7,
+ 8,
{
+ B(StackCheck), //
B(LdaSmi8), U8(2), //
B(StaGlobalSloppy), U8(0), U8(vector->GetIndex(slot)), //
B(LdaUndefined), //
@@ -1650,15 +1753,16 @@
"f({name: 1});",
kPointerSize,
2,
- 1033,
+ 1034,
{
+ B(StackCheck), //
B(Ldar), A(1, 2), //
B(Star), R(0), //
- B(LoadICSloppy), R(0), U8(0), U8(wide_idx_1 += 2), //
+ B(LoadIC), R(0), U8(0), U8(wide_idx_1 += 2), //
REPEAT_127(COMMA, //
B(Ldar), A(1, 2), //
B(Star), R(0), //
- B(LoadICSloppy), R(0), U8(0), U8(wide_idx_1 += 2)), //
+ B(LoadIC), R(0), U8(0), U8(wide_idx_1 += 2)), //
B(LdaSmi8), U8(2), //
B(StaGlobalSloppyWide), U16(1), U16(wide_idx_1 + 2), //
B(LdaUndefined), //
@@ -1675,15 +1779,16 @@
"f({name: 1});",
kPointerSize,
2,
- 1033,
+ 1034,
{
+ B(StackCheck), //
B(Ldar), A(1, 2), //
B(Star), R(0), //
- B(LoadICStrict), R(0), U8(0), U8(wide_idx_2 += 2), //
+ B(LoadIC), R(0), U8(0), U8(wide_idx_2 += 2), //
REPEAT_127(COMMA, //
B(Ldar), A(1, 2), //
B(Star), R(0), //
- B(LoadICStrict), R(0), U8(0), U8(wide_idx_2 += 2)), //
+ B(LoadIC), R(0), U8(0), U8(wide_idx_2 += 2)), //
B(LdaSmi8), U8(2), //
B(StaGlobalStrictWide), U16(1), U16(wide_idx_2 + 2), //
B(LdaUndefined), //
@@ -1692,6 +1797,7 @@
2,
{"name", "a"}},
};
+ // clang-format on
for (size_t i = 0; i < arraysize(snippets); i++) {
Handle<BytecodeArray> bytecode_array =
@@ -1713,17 +1819,19 @@
Handle<i::TypeFeedbackVector> vector =
i::NewTypeFeedbackVector(helper.isolate(), &feedback_spec);
+ // clang-format off
ExpectedSnippet<const char*> snippets[] = {
{"function t() { }\nfunction f() { return t(); }\nf()",
2 * kPointerSize,
1,
- 14,
+ 15,
{
+ B(StackCheck), //
B(LdaUndefined), //
B(Star), R(1), //
- B(LdaGlobalSloppy), U8(0), U8(vector->GetIndex(slot2)), //
+ B(LdaGlobal), U8(0), U8(vector->GetIndex(slot2)), //
B(Star), R(0), //
- B(Call), R(0), R(1), U8(0), U8(vector->GetIndex(slot1)), //
+ B(Call), R(0), R(1), U8(1), U8(vector->GetIndex(slot1)), //
B(Return) //
},
1,
@@ -1731,11 +1839,12 @@
{"function t(a, b, c) { }\nfunction f() { return t(1, 2, 3); }\nf()",
5 * kPointerSize,
1,
- 26,
+ 27,
{
+ B(StackCheck), //
B(LdaUndefined), //
B(Star), R(1), //
- B(LdaGlobalSloppy), U8(0), U8(vector->GetIndex(slot2)), //
+ B(LdaGlobal), U8(0), U8(vector->GetIndex(slot2)), //
B(Star), R(0), //
B(LdaSmi8), U8(1), //
B(Star), R(2), //
@@ -1743,12 +1852,13 @@
B(Star), R(3), //
B(LdaSmi8), U8(3), //
B(Star), R(4), //
- B(Call), R(0), R(1), U8(3), U8(vector->GetIndex(slot1)), //
+ B(Call), R(0), R(1), U8(4), U8(vector->GetIndex(slot1)), //
B(Return) //
},
1,
{"t"}},
};
+ // clang-format on
size_t num_snippets = sizeof(snippets) / sizeof(snippets[0]);
for (size_t i = 0; i < num_snippets; i++) {
@@ -1763,13 +1873,15 @@
InitializedHandleScope handle_scope;
BytecodeGeneratorHelper helper;
+ // clang-format off
ExpectedSnippet<InstanceType> snippets[] = {
{
"function f() { %TheHole() }\nf()",
0,
1,
- 7,
+ 8,
{
+ B(StackCheck), //
B(CallRuntime), U16(Runtime::kTheHole), R(0), U8(0), //
B(LdaUndefined), //
B(Return) //
@@ -1779,8 +1891,9 @@
"function f(a) { return %IsArray(a) }\nf(undefined)",
1 * kPointerSize,
2,
- 10,
+ 11,
{
+ B(StackCheck), //
B(Ldar), A(1, 2), //
B(Star), R(0), //
B(CallRuntime), U16(Runtime::kIsArray), R(0), U8(1), //
@@ -1791,8 +1904,9 @@
"function f() { return %Add(1, 2) }\nf()",
2 * kPointerSize,
1,
- 14,
+ 15,
{
+ B(StackCheck), //
B(LdaSmi8), U8(1), //
B(Star), R(0), //
B(LdaSmi8), U8(2), //
@@ -1805,20 +1919,22 @@
"function f() { return %spread_iterable([1]) }\nf()",
2 * kPointerSize,
1,
- 15,
+ 16,
{
+ B(StackCheck), //
B(LdaUndefined), //
B(Star), R(0), //
B(CreateArrayLiteral), U8(0), U8(0), U8(3), //
B(Star), R(1), //
B(CallJSRuntime), U16(Context::SPREAD_ITERABLE_INDEX), R(0), //
- U8(1), //
+ /* */ U8(2), //
B(Return), //
},
1,
{InstanceType::FIXED_ARRAY_TYPE},
},
};
+ // clang-format on
for (size_t i = 0; i < arraysize(snippets); i++) {
Handle<BytecodeArray> bytecode_array =
@@ -1834,12 +1950,14 @@
Handle<Object> unused = helper.factory()->undefined_value();
+ // clang-format off
ExpectedSnippet<Handle<Object>> snippets[] = {
{"function f() { if (0) { return 1; } else { return -1; } } f()",
0,
1,
- 3,
+ 4,
{
+ B(StackCheck), //
B(LdaSmi8), U8(-1), //
B(Return), //
},
@@ -1848,8 +1966,9 @@
{"function f() { if ('lucky') { return 1; } else { return -1; } } f();",
0,
1,
- 3,
+ 4,
{
+ B(StackCheck), //
B(LdaSmi8), U8(1), //
B(Return), //
},
@@ -1858,8 +1977,9 @@
{"function f() { if (false) { return 1; } else { return -1; } } f();",
0,
1,
- 3,
+ 4,
{
+ B(StackCheck), //
B(LdaSmi8), U8(-1), //
B(Return), //
},
@@ -1868,8 +1988,9 @@
{"function f() { if (false) { return 1; } } f();",
0,
1,
- 2,
+ 3,
{
+ B(StackCheck), //
B(LdaUndefined), //
B(Return), //
},
@@ -1878,8 +1999,9 @@
{"function f() { var a = 1; if (a) { a += 1; } else { return 2; } } f();",
2 * kPointerSize,
1,
- 23,
+ 24,
{
+ B(StackCheck), //
B(LdaSmi8), U8(1), //
B(Star), R(0), //
B(JumpIfToBooleanFalse), U8(14), //
@@ -1900,8 +2022,9 @@
"f(99);",
kPointerSize,
2,
- 17,
+ 18,
{
+ B(StackCheck), //
B(Ldar), A(1, 2), //
B(Star), R(0), //
B(LdaZero), //
@@ -1922,8 +2045,9 @@
"f('prop', { prop: 'yes'});",
kPointerSize,
3,
- 15,
+ 16,
{
+ B(StackCheck), //
B(Ldar), A(1, 3), //
B(Star), R(0), //
B(Ldar), A(2, 3), //
@@ -1942,8 +2066,9 @@
" return 200; } else { return -200; } } f(0.001)",
3 * kPointerSize,
2,
- 282,
+ 283,
{
+ B(StackCheck), //
B(LdaZero), //
B(Star), R(0), //
B(LdaZero), //
@@ -1973,8 +2098,9 @@
" return 200; } else { return -200; } } f()",
2 * kPointerSize,
1,
- 276,
+ 277,
{
+ B(StackCheck), //
B(LdaZero), //
B(Star), R(0), //
B(LdaZero), //
@@ -2009,7 +2135,7 @@
"} f(1, 1);",
kPointerSize,
3,
- 106,
+ 107,
{
#define IF_CONDITION_RETURN(condition) \
B(Ldar), A(1, 3), \
@@ -2019,6 +2145,7 @@
B(JumpIfFalse), U8(5), \
B(LdaSmi8), U8(1), \
B(Return),
+ B(StackCheck), //
IF_CONDITION_RETURN(TestEqual) //
IF_CONDITION_RETURN(TestEqualStrict) //
IF_CONDITION_RETURN(TestLessThan) //
@@ -2042,8 +2169,9 @@
"f();",
1 * kPointerSize,
1,
- 13,
+ 14,
{
+ B(StackCheck), //
B(LdaZero), //
B(Star), R(0), //
B(JumpIfToBooleanFalse), U8(5), //
@@ -2055,7 +2183,9 @@
B(Return)
},
0,
- {unused, unused, unused, unused, unused, unused}}};
+ {unused, unused, unused, unused, unused, unused}}
+ };
+ // clang-format on
for (size_t i = 0; i < arraysize(snippets); i++) {
Handle<BytecodeArray> bytecode_array =
@@ -2086,17 +2216,19 @@
Handle<i::TypeFeedbackVector> load_vector =
i::NewTypeFeedbackVector(helper.isolate(), &feedback_spec_loads);
+ // clang-format off
ExpectedSnippet<InstanceType> snippets[] = {
{"var a = 1;",
4 * kPointerSize,
1,
- 30,
+ 31,
{
B(LdaConstant), U8(0), //
B(Star), R(1), //
B(LdaZero), //
B(Star), R(2), //
B(CallRuntime), U16(Runtime::kDeclareGlobals), R(1), U8(2), //
+ B(StackCheck), //
B(LdaConstant), U8(1), //
B(Star), R(1), //
B(LdaZero), //
@@ -2113,13 +2245,14 @@
{"function f() {}",
2 * kPointerSize,
1,
- 14,
+ 15,
{
B(LdaConstant), U8(0), //
B(Star), R(0), //
B(LdaZero), //
B(Star), R(1), //
B(CallRuntime), U16(Runtime::kDeclareGlobals), R(0), U8(2), //
+ B(StackCheck), //
B(LdaUndefined), //
B(Return) //
},
@@ -2128,13 +2261,14 @@
{"var a = 1;\na=2;",
4 * kPointerSize,
1,
- 36,
+ 37,
{
B(LdaConstant), U8(0), //
B(Star), R(1), //
B(LdaZero), //
B(Star), R(2), //
B(CallRuntime), U16(Runtime::kDeclareGlobals), R(1), U8(2), //
+ B(StackCheck), //
B(LdaConstant), U8(1), //
B(Star), R(1), //
B(LdaZero), //
@@ -2144,7 +2278,7 @@
B(CallRuntime), U16(Runtime::kInitializeVarGlobal), R(1), U8(3), //
B(LdaSmi8), U8(2), //
B(StaGlobalSloppy), U8(1), //
- U8(store_vector->GetIndex(store_slot_2)), //
+ /* */ U8(store_vector->GetIndex(store_slot_2)), //
B(Star), R(0), //
B(Return) //
},
@@ -2154,20 +2288,20 @@
{"function f() {}\nf();",
3 * kPointerSize,
1,
- 28,
+ 29,
{
B(LdaConstant), U8(0), //
B(Star), R(1), //
B(LdaZero), //
B(Star), R(2), //
B(CallRuntime), U16(Runtime::kDeclareGlobals), R(1), U8(2), //
+ B(StackCheck), //
B(LdaUndefined), //
B(Star), R(2), //
- B(LdaGlobalSloppy), U8(1), //
- U8(load_vector->GetIndex(load_slot_1)), //
+ B(LdaGlobal), U8(1), U8(load_vector->GetIndex(load_slot_1)), //
B(Star), R(1), //
- B(Call), R(1), R(2), U8(0), //
- U8(load_vector->GetIndex(call_slot_1)), //
+ B(Call), R(1), R(2), U8(1), //
+ /* */ U8(load_vector->GetIndex(call_slot_1)), //
B(Star), R(0), //
B(Return) //
},
@@ -2175,6 +2309,7 @@
{InstanceType::FIXED_ARRAY_TYPE,
InstanceType::ONE_BYTE_INTERNALIZED_STRING_TYPE}},
};
+ // clang-format on
for (size_t i = 0; i < arraysize(snippets); i++) {
Handle<BytecodeArray> bytecode_array =
@@ -2188,7 +2323,11 @@
InitializedHandleScope handle_scope;
BytecodeGeneratorHelper helper;
- ExpectedSnippet<int> snippets[] = {
+ int closure = Register::function_closure().index();
+ int context = Register::current_context().index();
+
+ // clang-format off
+ ExpectedSnippet<InstanceType> snippets[] = {
{"var x = 0;\n"
"label: {\n"
" x = x + 1;\n"
@@ -2198,8 +2337,9 @@
"return x;",
2 * kPointerSize,
1,
- 16,
+ 17,
{
+ B(StackCheck), //
B(LdaZero), //
B(Star), R(0), //
B(Star), R(1), //
@@ -2222,8 +2362,9 @@
"return sum;",
5 * kPointerSize,
1,
- 72,
+ 75,
{
+ B(StackCheck), //
B(LdaZero), //
B(Star), R(0), //
B(LdaZero), //
@@ -2232,14 +2373,16 @@
B(Star), R(3), //
B(LdaSmi8), U8(10), //
B(TestLessThan), R(3), //
- B(JumpIfFalse), U8(55), //
+ B(JumpIfFalse), U8(57), //
+ B(StackCheck), //
B(LdaZero), //
B(Star), R(2), //
B(Ldar), R(2), //
B(Star), R(3), //
B(LdaSmi8), U8(3), //
B(TestLessThan), R(3), //
- B(JumpIfFalse), U8(34), //
+ B(JumpIfFalse), U8(35), //
+ B(StackCheck), //
B(Ldar), R(0), //
B(ToNumber), //
B(Inc), //
@@ -2257,16 +2400,128 @@
B(ToNumber), //
B(Inc), //
B(Star), R(2), //
- B(Jump), U8(-40), //
+ B(Jump), U8(-41), //
B(Ldar), R(1), //
B(ToNumber), //
B(Inc), //
B(Star), R(1), //
- B(Jump), U8(-61), //
+ B(Jump), U8(-63), //
B(Ldar), R(0), //
B(Return), //
}},
+ {"outer: {\n"
+ " let y = 10;"
+ " function f() { return y; }\n"
+ " break outer;\n"
+ "}\n",
+ 5 * kPointerSize,
+ 1,
+ 51,
+ {
+ B(StackCheck), //
+ B(LdaConstant), U8(0), //
+ B(Star), R(3), //
+ B(Ldar), R(closure), //
+ B(Star), R(4), //
+ B(CallRuntime), U16(Runtime::kPushBlockContext), R(3), U8(2), //
+ B(PushContext), R(2), //
+ B(LdaTheHole), //
+ B(StaContextSlot), R(context), U8(4), //
+ B(CreateClosure), U8(1), U8(0), //
+ B(Star), R(0), //
+ B(LdaSmi8), U8(10), //
+ B(StaContextSlot), R(context), U8(4), //
+ B(Ldar), R(0), //
+ B(JumpIfNotHole), U8(11), //
+ B(LdaConstant), U8(2), //
+ B(Star), R(3), //
+ B(CallRuntime), U16(Runtime::kThrowReferenceError), R(3), U8(1), //
+ B(Star), R(1), //
+ B(Jump), U8(2), //
+ B(PopContext), R(2), //
+ B(LdaUndefined), //
+ B(Return), //
+ },
+ 3,
+ {InstanceType::FIXED_ARRAY_TYPE, InstanceType::SHARED_FUNCTION_INFO_TYPE,
+ InstanceType::ONE_BYTE_INTERNALIZED_STRING_TYPE}},
+ {"let x = 1;\n"
+ "outer: {\n"
+ " inner: {\n"
+ " let y = 2;\n"
+ " function f() { return x + y; }\n"
+ " if (y) break outer;\n"
+ " y = 3;\n"
+ " }\n"
+ "}\n"
+ "x = 4;",
+ 6 * kPointerSize,
+ 1,
+ 131,
+ {
+ B(CallRuntime), U16(Runtime::kNewFunctionContext), R(closure), //
+ U8(1), //
+ B(PushContext), R(2), //
+ B(LdaTheHole), //
+ B(StaContextSlot), R(context), U8(4), //
+ B(StackCheck), //
+ B(LdaSmi8), U8(1), //
+ B(StaContextSlot), R(context), U8(4), //
+ B(LdaConstant), U8(0), //
+ B(Star), R(4), //
+ B(Ldar), R(closure), //
+ B(Star), R(5), //
+ B(CallRuntime), U16(Runtime::kPushBlockContext), R(4), U8(2), //
+ B(PushContext), R(3), //
+ B(LdaTheHole), //
+ B(StaContextSlot), R(context), U8(4), //
+ B(CreateClosure), U8(1), U8(0), //
+ B(Star), R(0), //
+ B(LdaSmi8), U8(2), //
+ B(StaContextSlot), R(context), U8(4), //
+ B(Ldar), R(0), //
+ B(JumpIfNotHole), U8(11), //
+ B(LdaConstant), U8(2), //
+ B(Star), R(4), //
+ B(CallRuntime), U16(Runtime::kThrowReferenceError), R(4), U8(1), //
+ B(Star), R(1), //
+ B(LdaContextSlot), R(context), U8(4), //
+ B(JumpIfNotHole), U8(11), //
+ B(LdaConstant), U8(3), //
+ B(Star), R(4), //
+ B(CallRuntime), U16(Runtime::kThrowReferenceError), R(4), U8(1), //
+ B(JumpIfToBooleanFalse), U8(6), //
+ B(PopContext), R(3), //
+ B(Jump), U8(27), //
+ B(LdaSmi8), U8(3), //
+ B(Star), R(4), //
+ B(LdaContextSlot), R(context), U8(4), //
+ B(JumpIfNotHole), U8(11), //
+ B(LdaConstant), U8(3), //
+ B(Star), R(5), //
+ B(CallRuntime), U16(Runtime::kThrowReferenceError), R(5), U8(1), //
+ B(Ldar), R(4), //
+ B(StaContextSlot), R(context), U8(4), //
+ B(PopContext), R(3), //
+ B(LdaSmi8), U8(4), //
+ B(Star), R(4), //
+ B(LdaContextSlot), R(context), U8(4), //
+ B(JumpIfNotHole), U8(11), //
+ B(LdaConstant), U8(4), //
+ B(Star), R(5), //
+ B(CallRuntime), U16(Runtime::kThrowReferenceError), R(5), U8(1), //
+ B(Ldar), R(4), //
+ B(StaContextSlot), R(context), U8(4), //
+ B(LdaUndefined), //
+ B(Return), //
+ },
+ 5,
+ {InstanceType::FIXED_ARRAY_TYPE, InstanceType::SHARED_FUNCTION_INFO_TYPE,
+ InstanceType::ONE_BYTE_INTERNALIZED_STRING_TYPE,
+ InstanceType::ONE_BYTE_INTERNALIZED_STRING_TYPE,
+ InstanceType::ONE_BYTE_INTERNALIZED_STRING_TYPE}},
};
+ // clang-format on
for (size_t i = 0; i < arraysize(snippets); i++) {
Handle<BytecodeArray> bytecode_array =
@@ -2280,14 +2535,19 @@
InitializedHandleScope handle_scope;
BytecodeGeneratorHelper helper;
- ExpectedSnippet<int> snippets[] = {
+ int closure = Register::function_closure().index();
+ int context = Register::current_context().index();
+
+ // clang-format off
+ ExpectedSnippet<InstanceType> snippets[] = {
{"var x = 0;\n"
"while (false) { x = 99; break; continue; }\n"
"return x;",
1 * kPointerSize,
1,
- 4,
+ 5,
{
+ B(StackCheck), //
B(LdaZero), //
B(Star), R(0), //
B(Return) //
@@ -2299,8 +2559,9 @@
"return x;",
1 * kPointerSize,
1,
- 4,
+ 5,
{
+ B(StackCheck), //
B(LdaZero), //
B(Star), R(0), //
B(Return), //
@@ -2317,8 +2578,9 @@
"return y;",
3 * kPointerSize,
1,
- 64,
+ 66,
{
+ B(StackCheck), //
B(LdaZero), //
B(Star), R(0), //
B(LdaSmi8), U8(1), //
@@ -2327,7 +2589,8 @@
B(Star), R(2), //
B(LdaSmi8), U8(10), //
B(TestLessThan), R(2), //
- B(JumpIfFalse), U8(46), //
+ B(JumpIfFalse), U8(47), //
+ B(StackCheck), //
B(Ldar), R(1), //
B(Star), R(2), //
B(LdaSmi8), U8(12), //
@@ -2342,14 +2605,14 @@
B(LdaSmi8), U8(3), //
B(TestEqual), R(2), //
B(JumpIfFalse), U8(4), //
- B(Jump), U8(-38), //
+ B(Jump), U8(-39), //
B(Ldar), R(0), //
B(Star), R(2), //
B(LdaSmi8), U8(4), //
B(TestEqual), R(2), //
B(JumpIfFalse), U8(4), //
B(Jump), U8(4), //
- B(Jump), U8(-52), //
+ B(Jump), U8(-53), //
B(Ldar), R(1), //
B(Return), //
},
@@ -2366,16 +2629,18 @@
"return i;",
2 * kPointerSize,
1,
- 77,
+ 79,
{
+ B(StackCheck), //
B(LdaZero), //
B(Star), R(0), //
+ B(StackCheck), //
B(Ldar), R(0), //
B(Star), R(1), //
B(LdaZero), //
B(TestLessThan), R(1), //
B(JumpIfFalse), U8(4), //
- B(Jump), U8(-9), //
+ B(Jump), U8(-10), //
B(Ldar), R(0), //
B(Star), R(1), //
B(LdaSmi8), U8(3), //
@@ -2393,7 +2658,7 @@
B(LdaSmi8), U8(10), //
B(TestEqual), R(1), //
B(JumpIfFalse), U8(4), //
- B(Jump), U8(-45), //
+ B(Jump), U8(-46), //
B(Ldar), R(0), //
B(Star), R(1), //
B(LdaSmi8), U8(5), //
@@ -2405,7 +2670,7 @@
B(LdaSmi8), U8(1), //
B(Add), R(1), //
B(Star), R(0), //
- B(Jump), U8(-69), //
+ B(Jump), U8(-70), //
B(Ldar), R(0), //
B(Return), //
},
@@ -2422,15 +2687,18 @@
"return i;",
2 * kPointerSize,
1,
- 54,
+ 57,
{
+ B(StackCheck), //
B(LdaZero), //
B(Star), R(0), //
+ B(StackCheck), //
B(Ldar), R(0), //
B(Star), R(1), //
B(LdaSmi8), U8(3), //
B(TestLessThan), R(1), //
- B(JumpIfFalse), U8(26), //
+ B(JumpIfFalse), U8(27), //
+ B(StackCheck), //
B(Ldar), R(0), //
B(Star), R(1), //
B(LdaSmi8), U8(2), //
@@ -2442,14 +2710,14 @@
B(LdaSmi8), U8(1), //
B(Add), R(1), //
B(Star), R(0), //
- B(Jump), U8(-32), //
+ B(Jump), U8(-33), //
B(Ldar), R(0), //
B(Star), R(1), //
B(LdaSmi8), U8(1), //
B(Add), R(1), //
B(Star), R(0), //
B(Jump), U8(4), //
- B(Jump), U8(-46), //
+ B(Jump), U8(-48), //
B(Ldar), R(0), //
B(Return), //
},
@@ -2463,14 +2731,16 @@
"return y;",
3 * kPointerSize,
1,
- 37,
+ 39,
{
+ B(StackCheck), //
B(LdaSmi8), U8(10), //
B(Star), R(0), //
B(LdaSmi8), U8(1), //
B(Star), R(1), //
B(Ldar), R(0), //
- B(JumpIfToBooleanFalse), U8(24), //
+ B(JumpIfToBooleanFalse), U8(25), //
+ B(StackCheck), //
B(Ldar), R(1), //
B(Star), R(2), //
B(LdaSmi8), U8(12), //
@@ -2481,7 +2751,7 @@
B(LdaSmi8), U8(1), //
B(Sub), R(2), //
B(Star), R(0), //
- B(Jump), U8(-24), //
+ B(Jump), U8(-25), //
B(Ldar), R(1), //
B(Return), //
},
@@ -2496,12 +2766,14 @@
"return y;",
3 * kPointerSize,
1,
- 64,
+ 66,
{
+ B(StackCheck), //
B(LdaZero), //
B(Star), R(0), //
B(LdaSmi8), U8(1), //
B(Star), R(1), //
+ B(StackCheck), //
B(Ldar), R(1), //
B(Star), R(2), //
B(LdaSmi8), U8(10), //
@@ -2528,7 +2800,7 @@
B(Star), R(2), //
B(LdaSmi8), U8(10), //
B(TestLessThan), R(2), //
- B(JumpIfTrue), U8(-52), //
+ B(JumpIfTrue), U8(-53), //
B(Ldar), R(1), //
B(Return), //
},
@@ -2542,12 +2814,14 @@
"return y;",
3 * kPointerSize,
1,
- 35,
+ 37,
{
+ B(StackCheck), //
B(LdaSmi8), U8(10), //
B(Star), R(0), //
B(LdaSmi8), U8(1), //
B(Star), R(1), //
+ B(StackCheck), //
B(Ldar), R(1), //
B(Star), R(2), //
B(LdaSmi8), U8(12), //
@@ -2559,7 +2833,7 @@
B(Sub), R(2), //
B(Star), R(0), //
B(Ldar), R(0), //
- B(JumpIfToBooleanTrue), U8(-22), //
+ B(JumpIfToBooleanTrue), U8(-23), //
B(Ldar), R(1), //
B(Return), //
},
@@ -2574,12 +2848,14 @@
"return y;",
3 * kPointerSize,
1,
- 52,
+ 54,
{
+ B(StackCheck), //
B(LdaZero), //
B(Star), R(0), //
B(LdaSmi8), U8(1), //
B(Star), R(1), //
+ B(StackCheck), //
B(Ldar), R(1), //
B(Star), R(2), //
B(LdaSmi8), U8(10), //
@@ -2615,12 +2891,14 @@
"return y;",
3 * kPointerSize,
1,
- 54,
+ 56,
{
+ B(StackCheck), //
B(LdaZero), //
B(Star), R(0), //
B(LdaSmi8), U8(1), //
B(Star), R(1), //
+ B(StackCheck), //
B(Ldar), R(1), //
B(Star), R(2), //
B(LdaSmi8), U8(10), //
@@ -2641,8 +2919,8 @@
B(LdaSmi8), U8(6), //
B(TestEqual), R(2), //
B(JumpIfFalse), U8(4), //
- B(Jump), U8(-40), //
- B(Jump), U8(-42), //
+ B(Jump), U8(-41), //
+ B(Jump), U8(-43), //
B(Ldar), R(1), //
B(Return), //
},
@@ -2655,10 +2933,12 @@
"}",
2 * kPointerSize,
1,
- 41,
+ 43,
{
+ B(StackCheck), //
B(LdaZero), //
B(Star), R(0), //
+ B(StackCheck), //
B(Ldar), R(0), //
B(Star), R(1), //
B(LdaSmi8), U8(1), //
@@ -2670,13 +2950,13 @@
B(LdaSmi8), U8(2), //
B(TestEqual), R(1), //
B(JumpIfFalse), U8(4), //
- B(Jump), U8(-22), //
+ B(Jump), U8(-23), //
B(Ldar), R(0), //
B(Star), R(1), //
B(LdaSmi8), U8(1), //
B(Add), R(1), //
B(Star), R(0), //
- B(Jump), U8(-34), //
+ B(Jump), U8(-35), //
B(LdaUndefined), //
B(Return), //
},
@@ -2688,10 +2968,12 @@
"}",
2 * kPointerSize,
1,
- 41,
+ 43,
{
+ B(StackCheck), //
B(LdaZero), //
B(Star), R(0), //
+ B(StackCheck), //
B(Ldar), R(0), //
B(Star), R(1), //
B(LdaSmi8), U8(1), //
@@ -2703,13 +2985,13 @@
B(LdaSmi8), U8(2), //
B(TestEqual), R(1), //
B(JumpIfFalse), U8(4), //
- B(Jump), U8(-22), //
+ B(Jump), U8(-23), //
B(Ldar), R(0), //
B(Star), R(1), //
B(LdaSmi8), U8(1), //
B(Add), R(1), //
B(Star), R(0), //
- B(Jump), U8(-34), //
+ B(Jump), U8(-35), //
B(LdaUndefined), //
B(Return), //
},
@@ -2721,10 +3003,12 @@
"}",
2 * kPointerSize,
1,
- 41,
+ 43,
{
+ B(StackCheck), //
B(LdaZero), //
B(Star), R(0), //
+ B(StackCheck), //
B(Ldar), R(0), //
B(Star), R(1), //
B(LdaSmi8), U8(1), //
@@ -2742,7 +3026,7 @@
B(LdaSmi8), U8(1), //
B(Add), R(1), //
B(Star), R(0), //
- B(Jump), U8(-34), //
+ B(Jump), U8(-35), //
B(LdaUndefined), //
B(Return), //
},
@@ -2753,10 +3037,12 @@
"}",
2 * kPointerSize,
1,
- 41,
+ 43,
{
+ B(StackCheck), //
B(LdaZero), //
B(Star), R(0), //
+ B(StackCheck), //
B(Ldar), R(0), //
B(Star), R(1), //
B(LdaSmi8), U8(1), //
@@ -2774,7 +3060,7 @@
B(LdaSmi8), U8(1), //
B(Add), R(1), //
B(Star), R(0), //
- B(Jump), U8(-34), //
+ B(Jump), U8(-35), //
B(LdaUndefined), //
B(Return), //
},
@@ -2786,8 +3072,9 @@
"}",
3 * kPointerSize,
1,
- 42,
+ 44,
{
+ B(StackCheck), //
B(LdaZero), //
B(Star), R(0), //
B(LdaZero), //
@@ -2796,7 +3083,8 @@
B(Star), R(2), //
B(LdaSmi8), U8(100), //
B(TestLessThan), R(2), //
- B(JumpIfFalse), U8(26), //
+ B(JumpIfFalse), U8(27), //
+ B(StackCheck), //
B(Ldar), R(0), //
B(Star), R(2), //
B(LdaSmi8), U8(1), //
@@ -2808,7 +3096,7 @@
B(LdaSmi8), U8(1), //
B(Add), R(2), //
B(Star), R(1), //
- B(Jump), U8(-32), //
+ B(Jump), U8(-33), //
B(LdaUndefined), //
B(Return), //
},
@@ -2820,14 +3108,16 @@
"return y;",
3 * kPointerSize,
1,
- 33,
+ 35,
{
+ B(StackCheck), //
B(LdaSmi8), U8(1), //
B(Star), R(0), //
B(LdaSmi8), U8(10), //
B(Star), R(1), //
B(Ldar), R(1), //
- B(JumpIfToBooleanFalse), U8(20), //
+ B(JumpIfToBooleanFalse), U8(21), //
+ B(StackCheck), //
B(Ldar), R(0), //
B(Star), R(2), //
B(LdaSmi8), U8(12), //
@@ -2837,7 +3127,7 @@
B(ToNumber), //
B(Dec), //
B(Star), R(1), //
- B(Jump), U8(-20), //
+ B(Jump), U8(-21), //
B(Ldar), R(0), //
B(Return), //
},
@@ -2849,8 +3139,9 @@
"return x;",
2 * kPointerSize,
1,
- 9,
+ 10,
{
+ B(StackCheck), //
B(LdaZero), //
B(Star), R(0), //
B(LdaZero), //
@@ -2867,12 +3158,14 @@
"return x;",
3 * kPointerSize,
1,
- 37,
+ 39,
{
+ B(StackCheck), //
B(LdaZero), //
B(Star), R(0), //
B(LdaZero), //
B(Star), R(1), //
+ B(StackCheck), //
B(Ldar), R(0), //
B(Star), R(2), //
B(LdaSmi8), U8(1), //
@@ -2887,12 +3180,83 @@
B(ToNumber), //
B(Inc), //
B(Star), R(1), //
- B(Jump), U8(-26), //
+ B(Jump), U8(-27), //
B(Ldar), R(0), //
B(Return), //
},
0},
+ {"var a = 0;\n"
+ "while (a) {\n"
+ " { \n"
+ " let z = 1;\n"
+ " function f() { z = 2; }\n"
+ " if (z) continue;\n"
+ " z++;\n"
+ " }\n"
+ "}\n",
+ 7 * kPointerSize,
+ 1,
+ 118,
+ {
+ B(StackCheck), //
+ B(LdaZero), //
+ B(Star), R(1), //
+ B(Ldar), R(1), //
+ B(JumpIfToBooleanFalse), U8(110), //
+ B(StackCheck), //
+ B(LdaConstant), U8(0), //
+ B(Star), R(4), //
+ B(Ldar), R(closure), //
+ B(Star), R(5), //
+ B(CallRuntime), U16(Runtime::kPushBlockContext), R(4), U8(2), //
+ B(PushContext), R(3), //
+ B(LdaTheHole), //
+ B(StaContextSlot), R(context), U8(4), //
+ B(CreateClosure), U8(1), U8(0), //
+ B(Star), R(0), //
+ B(LdaSmi8), U8(1), //
+ B(StaContextSlot), R(context), U8(4), //
+ B(Ldar), R(0), //
+ B(JumpIfNotHole), U8(11), //
+ B(LdaConstant), U8(2), //
+ B(Star), R(4), //
+ B(CallRuntime), U16(Runtime::kThrowReferenceError), R(4), U8(1), //
+ B(Star), R(2), //
+ B(LdaContextSlot), R(context), U8(4), //
+ B(JumpIfNotHole), U8(11), //
+ B(LdaConstant), U8(3), //
+ B(Star), R(4), //
+ B(CallRuntime), U16(Runtime::kThrowReferenceError), R(4), U8(1), //
+ B(JumpIfToBooleanFalse), U8(6), //
+ B(PopContext), R(3), //
+ B(Jump), U8(-67), //
+ B(LdaContextSlot), R(context), U8(4), //
+ B(JumpIfNotHole), U8(11), //
+ B(LdaConstant), U8(3), //
+ B(Star), R(4), //
+ B(CallRuntime), U16(Runtime::kThrowReferenceError), R(4), U8(1), //
+ B(ToNumber), //
+ B(Star), R(4), //
+ B(Inc), //
+ B(Star), R(5), //
+ B(LdaContextSlot), R(context), U8(4), //
+ B(JumpIfNotHole), U8(11), //
+ B(LdaConstant), U8(3), //
+ B(Star), R(6), //
+ B(CallRuntime), U16(Runtime::kThrowReferenceError), R(6), U8(1), //
+ B(Ldar), R(5), //
+ B(StaContextSlot), R(context), U8(4), //
+ B(PopContext), R(3), //
+ B(Jump), U8(-110), //
+ B(LdaUndefined), //
+ B(Return), //
+ },
+ 4,
+ {InstanceType::FIXED_ARRAY_TYPE, InstanceType::SHARED_FUNCTION_INFO_TYPE,
+ InstanceType::ONE_BYTE_INTERNALIZED_STRING_TYPE,
+ InstanceType::ONE_BYTE_INTERNALIZED_STRING_TYPE}},
};
+ // clang-format on
for (size_t i = 0; i < arraysize(snippets); i++) {
Handle<BytecodeArray> bytecode_array =
@@ -2907,6 +3271,7 @@
BytecodeGeneratorHelper helper;
int constant_count = 0;
+ // clang-format off
ExpectedSnippet<Handle<Object>, 316> snippets[] = {
{
REPEAT_256(SPACE, "var x = 0.1;")
@@ -2920,8 +3285,9 @@
"return 3;",
kPointerSize * 3,
1,
- 1359,
+ 1361,
{
+ B(StackCheck), //
#define L(c) B(LdaConstant), U8(c), B(Star), R(0)
REPEAT_256(COMMA, L(constant_count++)),
#undef L
@@ -2937,6 +3303,7 @@
B(LdaSmi8), U8(3), //
B(TestLessThan), R(2), //
B(JumpIfFalseConstantWide), U16(313), //
+ B(StackCheck), //
B(Ldar), R(1), //
B(Star), R(2), //
B(LdaSmi8), U8(1), //
@@ -2954,7 +3321,7 @@
B(Star), R(2), //
B(Inc), //
B(Star), R(1), //
- B(Jump), U8(-47), //
+ B(Jump), U8(-48), //
B(LdaSmi8), U8(3), //
B(Return) //
},
@@ -2967,9 +3334,11 @@
REPEAT_8(COMMA, S(0.4)),
#undef S
#define N(x) CcTest::i_isolate()->factory()->NewNumberFromInt(x)
- N(6), N(41), N(13), N(17)
+ N(6), N(42), N(13), N(17)
#undef N
- }}};
+ }}
+ };
+ // clang-format on
for (size_t i = 0; i < arraysize(snippets); i++) {
Handle<BytecodeArray> bytecode_array =
@@ -2983,6 +3352,7 @@
InitializedHandleScope handle_scope;
BytecodeGeneratorHelper helper;
+ // clang-format off
ExpectedSnippet<int> snippets[] = {
{"var x = 0;"
"while (x != 10) {"
@@ -2991,8 +3361,9 @@
"return x;",
2 * kPointerSize,
1,
- 29,
+ 31,
{
+ B(StackCheck), //
B(LdaZero), //
B(Star), R(0), //
B(Ldar), R(0), //
@@ -3000,13 +3371,14 @@
B(LdaSmi8), U8(10), //
B(TestEqual), R(1), //
B(LogicalNot), //
- B(JumpIfFalse), U8(14), //
+ B(JumpIfFalse), U8(15), //
+ B(StackCheck), //
B(Ldar), R(0), //
B(Star), R(1), //
B(LdaSmi8), U8(10), //
B(Add), R(1), //
B(Star), R(0), //
- B(Jump), U8(-21), //
+ B(Jump), U8(-22), //
B(Ldar), R(0), //
B(Return), //
},
@@ -3018,28 +3390,31 @@
"return x;",
2 * kPointerSize,
1,
- 20,
+ 22,
{
- B(LdaFalse), //
- B(Star), R(0), //
- B(Ldar), R(0), //
- B(LogicalNot), //
- B(Star), R(0), //
- B(Ldar), R(0), //
- B(Star), R(1), //
- B(LdaFalse), //
- B(TestEqual), R(1), //
- B(JumpIfTrue), U8(-12), //
- B(Ldar), R(0), //
- B(Return), //
+ B(StackCheck), //
+ B(LdaFalse), //
+ B(Star), R(0), //
+ B(StackCheck), //
+ B(Ldar), R(0), //
+ B(LogicalNot), //
+ B(Star), R(0), //
+ B(Ldar), R(0), //
+ B(Star), R(1), //
+ B(LdaFalse), //
+ B(TestEqual), R(1), //
+ B(JumpIfTrue), U8(-13), //
+ B(Ldar), R(0), //
+ B(Return), //
},
0},
{"var x = 101;"
"return void(x * 3);",
2 * kPointerSize,
1,
- 12,
+ 13,
{
+ B(StackCheck), //
B(LdaSmi8), U8(101), //
B(Star), R(0), //
B(Star), R(1), //
@@ -3054,8 +3429,9 @@
"return y;",
4 * kPointerSize,
1,
- 20,
+ 21,
{
+ B(StackCheck), //
B(LdaConstant), U8(0), //
B(Star), R(0), //
B(Star), R(2), //
@@ -3074,8 +3450,9 @@
"return ~x;",
2 * kPointerSize,
1,
- 11,
+ 12,
{
+ B(StackCheck), //
B(LdaSmi8), U8(13), //
B(Star), R(0), //
B(Star), R(1), //
@@ -3088,8 +3465,9 @@
"return +x;",
2 * kPointerSize,
1,
- 11,
+ 12,
{
+ B(StackCheck), //
B(LdaSmi8), U8(13), //
B(Star), R(0), //
B(Star), R(1), //
@@ -3102,8 +3480,9 @@
"return -x;",
2 * kPointerSize,
1,
- 11,
+ 12,
{
+ B(StackCheck), //
B(LdaSmi8), U8(13), //
B(Star), R(0), //
B(Star), R(1), //
@@ -3111,7 +3490,9 @@
B(Mul), R(1), //
B(Return), //
},
- 0}};
+ 0}
+ };
+ // clang-format on
for (size_t i = 0; i < arraysize(snippets); i++) {
Handle<BytecodeArray> bytecode_array =
@@ -3132,6 +3513,7 @@
Handle<i::TypeFeedbackVector> vector =
i::NewTypeFeedbackVector(helper.isolate(), &feedback_spec);
+ // clang-format off
ExpectedSnippet<const char*> snippets[] = {
{"function f() {\n"
" var x = 13;\n"
@@ -3139,8 +3521,9 @@
"}; f();",
kPointerSize,
1,
- 6,
+ 7,
{
+ B(StackCheck), //
B(LdaSmi8), U8(13), //
B(Star), R(0), //
B(TypeOf), //
@@ -3152,32 +3535,17 @@
"}; f();",
0,
1,
- 5,
+ 6,
{
- B(LdaGlobalInsideTypeofSloppy), U8(0), //
- U8(vector->GetIndex(slot)), //
- B(TypeOf), //
- B(Return), //
- },
- 1,
- {"x"}},
- {"var x = 13;\n"
- "function f() {\n"
- " 'use strict';\n"
- " return typeof(x);\n"
- "}; f();",
- 0,
- 1,
- 5,
- {
- B(LdaGlobalInsideTypeofStrict), U8(0), //
- U8(vector->GetIndex(slot)), //
- B(TypeOf), //
- B(Return), //
+ B(StackCheck), //
+ B(LdaGlobalInsideTypeof), U8(0), U8(vector->GetIndex(slot)), //
+ B(TypeOf), //
+ B(Return), //
},
1,
{"x"}},
};
+ // clang-format on
for (size_t i = 0; i < arraysize(snippets); i++) {
Handle<BytecodeArray> bytecode_array =
@@ -3194,63 +3562,65 @@
int deep_elements_flags =
ObjectLiteral::kFastElements | ObjectLiteral::kDisableMementos;
int closure = Register::function_closure().index();
+ int context = Register::current_context().index();
int first_context_slot = Context::MIN_CONTEXT_SLOTS;
+ // clang-format off
ExpectedSnippet<InstanceType> snippets[] = {
{"var a = {x:13, y:14}; return delete a.x;",
2 * kPointerSize,
1,
- 13,
+ 16,
{
- B(CreateObjectLiteral), U8(0), U8(0), U8(deep_elements_flags), //
- B(Star), R(0), //
- B(Star), R(1), //
- B(LdaConstant), U8(1), //
- B(DeletePropertySloppy), R(1), //
- B(Return)
- },
+ B(StackCheck), //
+ B(CreateObjectLiteral), U8(0), U8(0), U8(deep_elements_flags), //
+ B(Star), R(1), //
+ B(Star), R(0), //
+ B(Star), R(1), //
+ B(LdaConstant), U8(1), //
+ B(DeletePropertySloppy), R(1), //
+ B(Return)},
2,
{InstanceType::FIXED_ARRAY_TYPE,
InstanceType::ONE_BYTE_INTERNALIZED_STRING_TYPE}},
{"'use strict'; var a = {x:13, y:14}; return delete a.x;",
2 * kPointerSize,
1,
- 13,
- {
- B(CreateObjectLiteral), U8(0), U8(0), U8(deep_elements_flags), //
- B(Star), R(0), //
- B(Star), R(1), //
- B(LdaConstant), U8(1), //
- B(DeletePropertyStrict), R(1), //
- B(Return)
- },
+ 16,
+ {B(StackCheck), //
+ B(CreateObjectLiteral), U8(0), U8(0), U8(deep_elements_flags), //
+ B(Star), R(1), //
+ B(Star), R(0), //
+ B(Star), R(1), //
+ B(LdaConstant), U8(1), //
+ B(DeletePropertyStrict), R(1), //
+ B(Return)},
2,
{InstanceType::FIXED_ARRAY_TYPE,
InstanceType::ONE_BYTE_INTERNALIZED_STRING_TYPE}},
{"var a = {1:13, 2:14}; return delete a[2];",
2 * kPointerSize,
1,
- 13,
- {
- B(CreateObjectLiteral), U8(0), U8(0), U8(deep_elements_flags), //
- B(Star), R(0), //
- B(Star), R(1), //
- B(LdaSmi8), U8(2), //
- B(DeletePropertySloppy), R(1), //
- B(Return)
- },
+ 16,
+ {B(StackCheck), //
+ B(CreateObjectLiteral), U8(0), U8(0), U8(deep_elements_flags), //
+ B(Star), R(1), //
+ B(Star), R(0), //
+ B(Star), R(1), //
+ B(LdaSmi8), U8(2), //
+ B(DeletePropertySloppy), R(1), //
+ B(Return)},
1,
{InstanceType::FIXED_ARRAY_TYPE}},
{"var a = 10; return delete a;",
1 * kPointerSize,
1,
- 6,
- {
- B(LdaSmi8), U8(10), //
- B(Star), R(0), //
- B(LdaFalse), //
- B(Return)
- },
+ 7,
+ {B(StackCheck), //
+ B(LdaSmi8), U8(10), //
+ B(Star), R(0), //
+ B(LdaFalse), //
+ B(Return)},
0},
{"'use strict';"
"var a = {1:10};"
@@ -3258,33 +3628,33 @@
"return delete a[1];",
2 * kPointerSize,
1,
- 27,
- {
- B(CallRuntime), U16(Runtime::kNewFunctionContext), //
- R(closure), U8(1), //
- B(PushContext), R(0), //
- B(CreateObjectLiteral), U8(0), U8(0), U8(deep_elements_flags), //
- B(StaContextSlot), R(0), U8(first_context_slot), //
- B(CreateClosure), U8(1), U8(0), //
- B(LdaContextSlot), R(0), U8(first_context_slot), //
- B(Star), R(1), //
- B(LdaSmi8), U8(1), //
- B(DeletePropertyStrict), R(1), //
- B(Return)
- },
+ 30,
+ {B(CallRuntime), U16(Runtime::kNewFunctionContext), //
+ /* */ R(closure), U8(1), //
+ B(PushContext), R(0), //
+ B(StackCheck), //
+ B(CreateObjectLiteral), U8(0), U8(0), U8(deep_elements_flags), //
+ B(Star), R(1), //
+ B(StaContextSlot), R(context), U8(first_context_slot), //
+ B(CreateClosure), U8(1), U8(0), //
+ B(LdaContextSlot), R(context), U8(first_context_slot), //
+ B(Star), R(1), //
+ B(LdaSmi8), U8(1), //
+ B(DeletePropertyStrict), R(1), //
+ B(Return)},
2,
{InstanceType::FIXED_ARRAY_TYPE,
InstanceType::SHARED_FUNCTION_INFO_TYPE}},
{"return delete 'test';",
0 * kPointerSize,
1,
- 2,
- {
- B(LdaTrue), //
- B(Return)
- },
+ 3,
+ {B(StackCheck), //
+ B(LdaTrue), //
+ B(Return)},
0},
};
+ // clang-format on
for (size_t i = 0; i < arraysize(snippets); i++) {
Handle<BytecodeArray> bytecode_array =
@@ -3299,7 +3669,7 @@
BytecodeGeneratorHelper helper;
Zone zone;
- int context = Register::function_context().index();
+ int context = Register::current_context().index();
int native_context_index = Context::NATIVE_CONTEXT_INDEX;
int global_context_index = Context::EXTENSION_INDEX;
FeedbackVectorSpec feedback_spec(&zone);
@@ -3308,12 +3678,14 @@
Handle<i::TypeFeedbackVector> vector =
i::NewTypeFeedbackVector(helper.isolate(), &feedback_spec);
+ // clang-format off
ExpectedSnippet<InstanceType> snippets[] = {
{"var a = {x:13, y:14};\n function f() { return delete a.x; };\n f();",
1 * kPointerSize,
1,
- 10,
- {B(LdaGlobalSloppy), U8(0), U8(vector->GetIndex(slot)), //
+ 11,
+ {B(StackCheck), //
+ B(LdaGlobal), U8(0), U8(vector->GetIndex(slot)), //
B(Star), R(0), //
B(LdaConstant), U8(1), //
B(DeletePropertySloppy), R(0), //
@@ -3325,8 +3697,9 @@
"function f() {'use strict'; return delete a[1];};\n f();",
1 * kPointerSize,
1,
- 10,
- {B(LdaGlobalStrict), U8(0), U8(vector->GetIndex(slot)), //
+ 11,
+ {B(StackCheck), //
+ B(LdaGlobal), U8(0), U8(vector->GetIndex(slot)), //
B(Star), R(0), //
B(LdaSmi8), U8(1), //
B(DeletePropertyStrict), R(0), //
@@ -3336,8 +3709,9 @@
{"var a = {x:13, y:14};\n function f() { return delete a; };\n f();",
2 * kPointerSize,
1,
- 15,
- {B(LdaContextSlot), R(context), U8(native_context_index), //
+ 16,
+ {B(StackCheck), //
+ B(LdaContextSlot), R(context), U8(native_context_index), //
B(Star), R(0), //
B(LdaContextSlot), R(0), U8(global_context_index), //
B(Star), R(1), //
@@ -3349,8 +3723,9 @@
{"b = 30;\n function f() { return delete b; };\n f();",
2 * kPointerSize,
1,
- 15,
- {B(LdaContextSlot), R(context), U8(native_context_index), //
+ 16,
+ {B(StackCheck), //
+ B(LdaContextSlot), R(context), U8(native_context_index), //
B(Star), R(0), //
B(LdaContextSlot), R(0), U8(global_context_index), //
B(Star), R(1), //
@@ -3358,7 +3733,9 @@
B(DeletePropertySloppy), R(1), //
B(Return)},
1,
- {InstanceType::ONE_BYTE_INTERNALIZED_STRING_TYPE}}};
+ {InstanceType::ONE_BYTE_INTERNALIZED_STRING_TYPE}}
+ };
+ // clang-format on
for (size_t i = 0; i < arraysize(snippets); i++) {
Handle<BytecodeArray> bytecode_array =
@@ -3379,12 +3756,14 @@
Handle<i::TypeFeedbackVector> vector =
i::NewTypeFeedbackVector(helper.isolate(), &feedback_spec);
+ // clang-format off
ExpectedSnippet<InstanceType> snippets[] = {
{"return function(){ }",
0,
1,
- 4,
+ 5,
{
+ B(StackCheck), //
B(CreateClosure), U8(0), U8(0), //
B(Return) //
},
@@ -3393,13 +3772,14 @@
{"return (function(){ })()",
2 * kPointerSize,
1,
- 14,
+ 15,
{
+ B(StackCheck), //
B(LdaUndefined), //
B(Star), R(1), //
B(CreateClosure), U8(0), U8(0), //
B(Star), R(0), //
- B(Call), R(0), R(1), U8(0), U8(vector->GetIndex(slot)), //
+ B(Call), R(0), R(1), U8(1), U8(vector->GetIndex(slot)), //
B(Return) //
},
1,
@@ -3407,20 +3787,22 @@
{"return (function(x){ return x; })(1)",
3 * kPointerSize,
1,
- 18,
+ 19,
{
+ B(StackCheck), //
B(LdaUndefined), //
B(Star), R(1), //
B(CreateClosure), U8(0), U8(0), //
B(Star), R(0), //
B(LdaSmi8), U8(1), //
B(Star), R(2), //
- B(Call), R(0), R(1), U8(1), U8(vector->GetIndex(slot)), //
+ B(Call), R(0), R(1), U8(2), U8(vector->GetIndex(slot)), //
B(Return) //
},
1,
{InstanceType::SHARED_FUNCTION_INFO_TYPE}},
};
+ // clang-format on
for (size_t i = 0; i < arraysize(snippets); i++) {
Handle<BytecodeArray> bytecode_array =
@@ -3443,12 +3825,14 @@
Handle<i::TypeFeedbackVector> vector =
i::NewTypeFeedbackVector(helper.isolate(), &feedback_spec);
+ // clang-format off
ExpectedSnippet<const char*> snippets[] = {
{"return /ab+d/;",
0 * kPointerSize,
1,
- 5,
+ 6,
{
+ B(StackCheck), //
B(CreateRegExpLiteral), U8(0), U8(0), U8(0), //
B(Return), //
},
@@ -3457,8 +3841,9 @@
{"return /(\\w+)\\s(\\w+)/i;",
0 * kPointerSize,
1,
- 5,
+ 6,
{
+ B(StackCheck), //
B(CreateRegExpLiteral), U8(0), U8(0), U8(i_flags), //
B(Return), //
},
@@ -3467,20 +3852,22 @@
{"return /ab+d/.exec('abdd');",
3 * kPointerSize,
1,
- 22,
+ 23,
{
+ B(StackCheck), //
B(CreateRegExpLiteral), U8(0), U8(0), U8(0), //
B(Star), R(1), //
- B(LoadICSloppy), R(1), U8(1), U8(vector->GetIndex(slot2)), //
+ B(LoadIC), R(1), U8(1), U8(vector->GetIndex(slot2)), //
B(Star), R(0), //
B(LdaConstant), U8(2), //
B(Star), R(2), //
- B(Call), R(0), R(1), U8(1), U8(vector->GetIndex(slot1)), //
+ B(Call), R(0), R(1), U8(2), U8(vector->GetIndex(slot1)), //
B(Return), //
},
3,
{"ab+d", "exec", "abdd"}},
};
+ // clang-format on
for (size_t i = 0; i < arraysize(snippets); i++) {
Handle<BytecodeArray> bytecode_array =
@@ -3497,12 +3884,14 @@
int wide_idx = 0;
+ // clang-format off
ExpectedSnippet<InstanceType, 257> snippets[] = {
{"var a;" REPEAT_256(SPACE, "a = 1.23;") "return /ab+d/;",
1 * kPointerSize,
1,
- 1031,
+ 1032,
{
+ B(StackCheck), //
REPEAT_256(COMMA, //
B(LdaConstant), U8(wide_idx++), //
B(Star), R(0)), //
@@ -3513,6 +3902,7 @@
{REPEAT_256(COMMA, InstanceType::HEAP_NUMBER_TYPE),
InstanceType::ONE_BYTE_INTERNALIZED_STRING_TYPE}},
};
+ // clang-format on
for (size_t i = 0; i < arraysize(snippets); i++) {
Handle<BytecodeArray> bytecode_array =
@@ -3538,12 +3928,14 @@
int simple_flags =
ArrayLiteral::kDisableMementos | ArrayLiteral::kShallowElements;
int deep_elements_flags = ArrayLiteral::kDisableMementos;
+ // clang-format off
ExpectedSnippet<InstanceType> snippets[] = {
{"return [ 1, 2 ];",
0,
1,
- 5,
+ 6,
{
+ B(StackCheck), //
B(CreateArrayLiteral), U8(0), U8(0), U8(simple_flags), //
B(Return) //
},
@@ -3552,8 +3944,9 @@
{"var a = 1; return [ a, a + 1 ];",
4 * kPointerSize,
1,
- 38,
+ 39,
{
+ B(StackCheck), //
B(LdaSmi8), U8(1), //
B(Star), R(0), //
B(CreateArrayLiteral), U8(0), U8(0), U8(3), //
@@ -3577,8 +3970,9 @@
{"return [ [ 1, 2 ], [ 3 ] ];",
0,
1,
- 5,
+ 6,
{
+ B(StackCheck), //
B(CreateArrayLiteral), U8(0), U8(2), U8(deep_elements_flags), //
B(Return) //
},
@@ -3587,8 +3981,9 @@
{"var a = 1; return [ [ a, 2 ], [ a + 2 ] ];",
6 * kPointerSize,
1,
- 68,
+ 69,
{
+ B(StackCheck), //
B(LdaSmi8), U8(1), //
B(Star), R(0), //
B(CreateArrayLiteral), U8(0), U8(2), U8(deep_elements_flags), //
@@ -3623,6 +4018,7 @@
{InstanceType::FIXED_ARRAY_TYPE, InstanceType::FIXED_ARRAY_TYPE,
InstanceType::FIXED_ARRAY_TYPE}},
};
+ // clang-format on
for (size_t i = 0; i < arraysize(snippets); i++) {
Handle<BytecodeArray> bytecode_array =
@@ -3641,12 +4037,14 @@
int simple_flags =
ArrayLiteral::kDisableMementos | ArrayLiteral::kShallowElements;
+ // clang-format off
ExpectedSnippet<InstanceType, 257> snippets[] = {
{"var a;" REPEAT_256(SPACE, "a = 1.23;") "return [ 1 , 2 ];",
1 * kPointerSize,
1,
- 1031,
+ 1032,
{
+ B(StackCheck), //
REPEAT_256(COMMA, //
B(LdaConstant), U8(wide_idx++), //
B(Star), R(0)), //
@@ -3657,6 +4055,7 @@
{REPEAT_256(COMMA, InstanceType::HEAP_NUMBER_TYPE),
InstanceType::FIXED_ARRAY_TYPE}},
};
+ // clang-format on
for (size_t i = 0; i < arraysize(snippets); i++) {
Handle<BytecodeArray> bytecode_array =
@@ -3682,23 +4081,29 @@
ObjectLiteral::kDisableMementos;
int deep_elements_flags =
ObjectLiteral::kFastElements | ObjectLiteral::kDisableMementos;
+
+ // clang-format off
ExpectedSnippet<InstanceType> snippets[] = {
{"return { };",
- 0,
+ kPointerSize,
1,
- 5,
+ 8,
{
+ B(StackCheck), //
B(CreateObjectLiteral), U8(0), U8(0), U8(simple_flags), //
+ B(Star), R(0), //
B(Return) //
},
1,
{InstanceType::FIXED_ARRAY_TYPE}},
{"return { name: 'string', val: 9.2 };",
- 0,
+ kPointerSize,
1,
- 5,
+ 8,
{
+ B(StackCheck), //
B(CreateObjectLiteral), U8(0), U8(0), U8(deep_elements_flags), //
+ B(Star), R(0), //
B(Return) //
},
1,
@@ -3706,8 +4111,9 @@
{"var a = 1; return { name: 'string', val: a };",
2 * kPointerSize,
1,
- 19,
+ 20,
{
+ B(StackCheck), //
B(LdaSmi8), U8(1), //
B(Star), R(0), //
B(CreateObjectLiteral), U8(0), U8(0), U8(deep_elements_flags), //
@@ -3723,8 +4129,9 @@
{"var a = 1; return { val: a, val: a + 1 };",
3 * kPointerSize,
1,
- 25,
+ 26,
{
+ B(StackCheck), //
B(LdaSmi8), U8(1), //
B(Star), R(0), //
B(CreateObjectLiteral), U8(0), U8(0), U8(deep_elements_flags), //
@@ -3743,8 +4150,9 @@
{"return { func: function() { } };",
1 * kPointerSize,
1,
- 16,
+ 17,
{
+ B(StackCheck), //
B(CreateObjectLiteral), U8(0), U8(0), U8(deep_elements_flags), //
B(Star), R(0), //
B(CreateClosure), U8(1), U8(0), //
@@ -3753,14 +4161,14 @@
B(Return), //
},
3,
- {InstanceType::FIXED_ARRAY_TYPE,
- InstanceType::SHARED_FUNCTION_INFO_TYPE,
+ {InstanceType::FIXED_ARRAY_TYPE, InstanceType::SHARED_FUNCTION_INFO_TYPE,
InstanceType::ONE_BYTE_INTERNALIZED_STRING_TYPE}},
{"return { func(a) { return a; } };",
1 * kPointerSize,
1,
- 16,
+ 17,
{
+ B(StackCheck), //
B(CreateObjectLiteral), U8(0), U8(0), U8(deep_elements_flags), //
B(Star), R(0), //
B(CreateClosure), U8(1), U8(0), //
@@ -3769,26 +4177,27 @@
B(Return), //
},
3,
- {InstanceType::FIXED_ARRAY_TYPE,
- InstanceType::SHARED_FUNCTION_INFO_TYPE,
+ {InstanceType::FIXED_ARRAY_TYPE, InstanceType::SHARED_FUNCTION_INFO_TYPE,
InstanceType::ONE_BYTE_INTERNALIZED_STRING_TYPE}},
{"return { get a() { return 2; } };",
- 5 * kPointerSize,
+ 6 * kPointerSize,
1,
- 29,
+ 33,
{
+ B(StackCheck), //
B(CreateObjectLiteral), U8(0), U8(0), U8(deep_elements_flags), //
B(Star), R(0), //
+ B(Mov), R(0), R(1), //
B(LdaConstant), U8(1), //
- B(Star), R(1), //
- B(CreateClosure), U8(2), U8(0), //
B(Star), R(2), //
- B(LdaNull), //
+ B(CreateClosure), U8(2), U8(0), //
B(Star), R(3), //
- B(LdaZero), //
+ B(LdaNull), //
B(Star), R(4), //
+ B(LdaZero), //
+ B(Star), R(5), //
B(CallRuntime), U16(Runtime::kDefineAccessorPropertyUnchecked), //
- R(0), U8(5), //
+ /* */ R(1), U8(5), //
B(Ldar), R(0), //
B(Return), //
},
@@ -3797,22 +4206,24 @@
InstanceType::ONE_BYTE_INTERNALIZED_STRING_TYPE,
InstanceType::SHARED_FUNCTION_INFO_TYPE}},
{"return { get a() { return this.x; }, set a(val) { this.x = val } };",
- 5 * kPointerSize,
+ 6 * kPointerSize,
1,
- 31,
+ 35,
{
+ B(StackCheck), //
B(CreateObjectLiteral), U8(0), U8(0), U8(deep_elements_flags), //
B(Star), R(0), //
+ B(Mov), R(0), R(1), //
B(LdaConstant), U8(1), //
- B(Star), R(1), //
- B(CreateClosure), U8(2), U8(0), //
B(Star), R(2), //
- B(CreateClosure), U8(3), U8(0), //
+ B(CreateClosure), U8(2), U8(0), //
B(Star), R(3), //
- B(LdaZero), //
+ B(CreateClosure), U8(3), U8(0), //
B(Star), R(4), //
+ B(LdaZero), //
+ B(Star), R(5), //
B(CallRuntime), U16(Runtime::kDefineAccessorPropertyUnchecked), //
- R(0), U8(5), //
+ /* */ R(1), U8(5), //
B(Ldar), R(0), //
B(Return), //
},
@@ -3822,22 +4233,24 @@
InstanceType::SHARED_FUNCTION_INFO_TYPE,
InstanceType::SHARED_FUNCTION_INFO_TYPE}},
{"return { set b(val) { this.y = val } };",
- 5 * kPointerSize,
+ 6 * kPointerSize,
1,
- 29,
+ 33,
{
+ B(StackCheck), //
B(CreateObjectLiteral), U8(0), U8(0), U8(deep_elements_flags), //
B(Star), R(0), //
+ B(Mov), R(0), R(1), //
B(LdaConstant), U8(1), //
- B(Star), R(1), //
- B(LdaNull), //
B(Star), R(2), //
- B(CreateClosure), U8(2), U8(0), //
+ B(LdaNull), //
B(Star), R(3), //
- B(LdaZero), //
+ B(CreateClosure), U8(2), U8(0), //
B(Star), R(4), //
+ B(LdaZero), //
+ B(Star), R(5), //
B(CallRuntime), U16(Runtime::kDefineAccessorPropertyUnchecked), //
- R(0), U8(5), //
+ /* */ R(1), U8(5), //
B(Ldar), R(0), //
B(Return), //
},
@@ -3846,58 +4259,66 @@
InstanceType::ONE_BYTE_INTERNALIZED_STRING_TYPE,
InstanceType::SHARED_FUNCTION_INFO_TYPE}},
{"var a = 1; return { 1: a };",
- 5 * kPointerSize,
+ 6 * kPointerSize,
1,
- 29,
+ 33,
{
+ B(StackCheck), //
B(LdaSmi8), U8(1), //
B(Star), R(0), //
B(CreateObjectLiteral), U8(0), U8(0), U8(deep_elements_flags), //
B(Star), R(1), //
+ B(Mov), R(1), R(2), //
B(LdaSmi8), U8(1), //
- B(Star), R(2), //
- B(Ldar), R(0), //
B(Star), R(3), //
- B(LdaZero), //
+ B(Ldar), R(0), //
B(Star), R(4), //
- B(CallRuntime), U16(Runtime::kSetProperty), R(1), U8(4), //
+ B(LdaZero), //
+ B(Star), R(5), //
+ B(CallRuntime), U16(Runtime::kSetProperty), R(2), U8(4), //
B(Ldar), R(1), //
B(Return), //
},
1,
{InstanceType::FIXED_ARRAY_TYPE}},
{"return { __proto__: null }",
- 2 * kPointerSize,
+ 3 * kPointerSize,
1,
- 17,
+ 21,
{
+ B(StackCheck), //
B(CreateObjectLiteral), U8(0), U8(0), U8(simple_flags), //
B(Star), R(0), //
- B(LdaNull), B(Star), R(1), //
- B(CallRuntime), U16(Runtime::kInternalSetPrototype), R(0), U8(2), //
+ B(Mov), R(0), R(1), //
+ B(LdaNull), B(Star), R(2), //
+ B(CallRuntime), U16(Runtime::kInternalSetPrototype), R(1), U8(2), //
B(Ldar), R(0), //
B(Return), //
},
1,
{InstanceType::FIXED_ARRAY_TYPE}},
{"var a = 'test'; return { [a]: 1 }",
- 5 * kPointerSize,
+ 7 * kPointerSize,
1,
- 30,
+ 37,
{
+ B(StackCheck), //
B(LdaConstant), U8(0), //
B(Star), R(0), //
B(CreateObjectLiteral), U8(1), U8(0), U8(simple_flags), //
B(Star), R(1), //
+ B(Mov), R(1), R(2), //
B(Ldar), R(0), //
B(ToName), //
- B(Star), R(2), //
- B(LdaSmi8), U8(1), //
B(Star), R(3), //
- B(LdaZero), //
+ B(LdaSmi8), U8(1), //
B(Star), R(4), //
- B(CallRuntime), U16(Runtime::kDefineDataPropertyUnchecked), R(1), //
- U8(4), //
+ B(LdaZero), //
+ B(Star), R(5), //
+ B(LdaZero), //
+ B(Star), R(6), //
+ B(CallRuntime), U16(Runtime::kDefineDataPropertyInLiteral), R(2), //
+ /* */ U8(5), //
B(Ldar), R(1), //
B(Return), //
},
@@ -3905,25 +4326,29 @@
{InstanceType::ONE_BYTE_INTERNALIZED_STRING_TYPE,
InstanceType::FIXED_ARRAY_TYPE}},
{"var a = 'test'; return { val: a, [a]: 1 }",
- 5 * kPointerSize,
+ 7 * kPointerSize,
1,
- 36,
+ 43,
{
+ B(StackCheck), //
B(LdaConstant), U8(0), //
B(Star), R(0), //
B(CreateObjectLiteral), U8(1), U8(0), U8(deep_elements_flags), //
B(Star), R(1), //
B(Ldar), R(0), //
B(StoreICSloppy), R(1), U8(2), U8(vector->GetIndex(slot1)), //
+ B(Mov), R(1), R(2), //
B(Ldar), R(0), //
B(ToName), //
- B(Star), R(2), //
- B(LdaSmi8), U8(1), //
B(Star), R(3), //
- B(LdaZero), //
+ B(LdaSmi8), U8(1), //
B(Star), R(4), //
- B(CallRuntime), U16(Runtime::kDefineDataPropertyUnchecked), R(1), //
- U8(4), //
+ B(LdaZero), //
+ B(Star), R(5), //
+ B(LdaZero), //
+ B(Star), R(6), //
+ B(CallRuntime), U16(Runtime::kDefineDataPropertyInLiteral), R(2), //
+ /* */ U8(5), //
B(Ldar), R(1), //
B(Return), //
},
@@ -3932,26 +4357,32 @@
InstanceType::FIXED_ARRAY_TYPE,
InstanceType::ONE_BYTE_INTERNALIZED_STRING_TYPE}},
{"var a = 'test'; return { [a]: 1, __proto__: {} }",
- 5 * kPointerSize,
+ 7 * kPointerSize,
1,
- 41,
+ 53,
{
+ B(StackCheck), //
B(LdaConstant), U8(0), //
B(Star), R(0), //
B(CreateObjectLiteral), U8(1), U8(1), U8(simple_flags), //
B(Star), R(1), //
+ B(Mov), R(1), R(2), //
B(Ldar), R(0), //
B(ToName), //
- B(Star), R(2), //
- B(LdaSmi8), U8(1), //
B(Star), R(3), //
- B(LdaZero), //
+ B(LdaSmi8), U8(1), //
B(Star), R(4), //
- B(CallRuntime), U16(Runtime::kDefineDataPropertyUnchecked), R(1), //
- U8(4), //
+ B(LdaZero), //
+ B(Star), R(5), //
+ B(LdaZero), //
+ B(Star), R(6), //
+ B(CallRuntime), U16(Runtime::kDefineDataPropertyInLiteral), R(2), //
+ /* */ U8(5), //
+ B(Mov), R(1), R(2), //
B(CreateObjectLiteral), U8(1), U8(0), U8(13), //
- B(Star), R(2), //
- B(CallRuntime), U16(Runtime::kInternalSetPrototype), R(1), U8(2), //
+ B(Star), R(4), //
+ B(Star), R(3), //
+ B(CallRuntime), U16(Runtime::kInternalSetPrototype), R(2), U8(2), //
B(Ldar), R(1), //
B(Return), //
},
@@ -3959,39 +4390,45 @@
{InstanceType::ONE_BYTE_INTERNALIZED_STRING_TYPE,
InstanceType::FIXED_ARRAY_TYPE}},
{"var n = 'name'; return { [n]: 'val', get a() { }, set a(b) {} };",
- 5 * kPointerSize,
+ 7 * kPointerSize,
1,
- 64,
+ 77,
{
+ B(StackCheck), //
B(LdaConstant), U8(0), //
B(Star), R(0), //
B(CreateObjectLiteral), U8(1), U8(0), U8(simple_flags), //
B(Star), R(1), //
+ B(Mov), R(1), R(2), //
B(Ldar), R(0), //
B(ToName), //
- B(Star), R(2), //
+ B(Star), R(3), //
B(LdaConstant), U8(2), //
- B(Star), R(3), //
- B(LdaZero), //
B(Star), R(4), //
- B(CallRuntime), U16(Runtime::kDefineDataPropertyUnchecked), R(1), //
- U8(4), //
+ B(LdaZero), //
+ B(Star), R(5), //
+ B(LdaZero), //
+ B(Star), R(6), //
+ B(CallRuntime), U16(Runtime::kDefineDataPropertyInLiteral), R(2), //
+ /* */ U8(5), //
+ B(Mov), R(1), R(2), //
B(LdaConstant), U8(3), //
- B(Star), R(2), //
+ B(Star), R(3), //
B(CreateClosure), U8(4), U8(0), //
- B(Star), R(3), //
- B(LdaZero), //
B(Star), R(4), //
+ B(LdaZero), //
+ B(Star), R(5), //
B(CallRuntime), U16(Runtime::kDefineGetterPropertyUnchecked), //
- R(1), U8(4), //
+ /* */ R(2), U8(4), //
+ B(Mov), R(1), R(2), //
B(LdaConstant), U8(3), //
- B(Star), R(2), //
- B(CreateClosure), U8(5), U8(0), //
B(Star), R(3), //
- B(LdaZero), //
+ B(CreateClosure), U8(5), U8(0), //
B(Star), R(4), //
+ B(LdaZero), //
+ B(Star), R(5), //
B(CallRuntime), U16(Runtime::kDefineSetterPropertyUnchecked), //
- R(1), U8(4), //
+ /* */ R(2), U8(4), //
B(Ldar), R(1), //
B(Return), //
},
@@ -4003,6 +4440,7 @@
InstanceType::SHARED_FUNCTION_INFO_TYPE,
InstanceType::SHARED_FUNCTION_INFO_TYPE}},
};
+ // clang-format on
for (size_t i = 0; i < arraysize(snippets); i++) {
Handle<BytecodeArray> bytecode_array =
@@ -4021,24 +4459,28 @@
ObjectLiteral::kFastElements | ObjectLiteral::kDisableMementos;
int wide_idx = 0;
+ // clang-format off
ExpectedSnippet<InstanceType, 257> snippets[] = {
{"var a;" REPEAT_256(SPACE,
"a = 1.23;") "return { name: 'string', val: 9.2 };",
- 1 * kPointerSize,
+ 2 * kPointerSize,
1,
- 1031,
+ 1034,
{
+ B(StackCheck), //
REPEAT_256(COMMA, //
- B(LdaConstant), U8(wide_idx++), //
- B(Star), R(0)), //
+ B(LdaConstant), U8(wide_idx++), //
+ B(Star), R(0)), //
B(CreateObjectLiteralWide), U16(256), U16(0), //
- U8(deep_elements_flags), //
+ /* */ U8(deep_elements_flags), //
+ B(Star), R(1), //
B(Return) //
},
257,
{REPEAT_256(COMMA, InstanceType::HEAP_NUMBER_TYPE),
InstanceType::FIXED_ARRAY_TYPE}},
};
+ // clang-format on
for (size_t i = 0; i < arraysize(snippets); i++) {
Handle<BytecodeArray> bytecode_array =
@@ -4055,17 +4497,19 @@
int has_function_flags = ObjectLiteral::kFastElements |
ObjectLiteral::kHasFunction |
ObjectLiteral::kDisableMementos;
+ // clang-format off
ExpectedSnippet<InstanceType> snippets[] = {
{"var a = { func: function() { } };",
5 * kPointerSize,
1,
- 48,
+ 49,
{
B(LdaConstant), U8(0), //
B(Star), R(1), //
B(LdaZero), //
B(Star), R(2), //
B(CallRuntime), U16(Runtime::kDeclareGlobals), R(1), U8(2), //
+ B(StackCheck), //
B(LdaConstant), U8(1), //
B(Star), R(1), //
B(LdaZero), //
@@ -4088,6 +4532,7 @@
InstanceType::SHARED_FUNCTION_INFO_TYPE,
InstanceType::ONE_BYTE_INTERNALIZED_STRING_TYPE}},
};
+ // clang-format on
for (size_t i = 0; i < arraysize(snippets); i++) {
Handle<BytecodeArray> bytecode_array =
@@ -4101,18 +4546,91 @@
InitializedHandleScope handle_scope;
BytecodeGeneratorHelper helper;
- // TODO(rmcilroy): modify tests when we have real try catch support.
- ExpectedSnippet<int> snippets[] = {
+ int closure = Register::function_closure().index();
+ int context = Register::current_context().index();
+
+ // clang-format off
+ ExpectedSnippet<const char*> snippets[] = {
{"try { return 1; } catch(e) { return 2; }",
- kPointerSize,
+ 5 * kPointerSize,
1,
- 3,
+ 40,
{
- B(LdaSmi8), U8(1), //
- B(Return), //
+ B(StackCheck), //
+ B(Mov), R(context), R(1), //
+ B(LdaSmi8), U8(1), //
+ B(Return), //
+ B(Star), R(3), //
+ B(LdaConstant), U8(0), //
+ B(Star), R(2), //
+ B(Ldar), R(closure), //
+ B(Star), R(4), //
+ B(CallRuntime), U16(Runtime::kPushCatchContext), R(2), U8(3), //
+ B(Star), R(1), //
+ B(CallRuntime), U16(Runtime::kInterpreterClearPendingMessage), //
+ /* */ R(0), U8(0), //
+ B(Ldar), R(1), //
+ B(PushContext), R(0), //
+ B(LdaSmi8), U8(2), //
+ B(PopContext), R(0), //
+ B(Return), //
+ // TODO(mstarzinger): Potential optimization, elide next bytes.
+ B(LdaUndefined), //
+ B(Return), //
},
- 0},
+ 1,
+ {"e"},
+ 1,
+ {{4, 7, 7}}},
+ {"var a; try { a = 1 } catch(e1) {}; try { a = 2 } catch(e2) { a = 3 }",
+ 6 * kPointerSize,
+ 1,
+ 81,
+ {
+ B(StackCheck), //
+ B(Mov), R(context), R(2), //
+ B(LdaSmi8), U8(1), //
+ B(Star), R(0), //
+ B(Jump), U8(30), //
+ B(Star), R(4), //
+ B(LdaConstant), U8(0), //
+ B(Star), R(3), //
+ B(Ldar), R(closure), //
+ B(Star), R(5), //
+ B(CallRuntime), U16(Runtime::kPushCatchContext), R(3), U8(3), //
+ B(Star), R(2), //
+ B(CallRuntime), U16(Runtime::kInterpreterClearPendingMessage), //
+ /* */ R(0), U8(0), //
+ B(Ldar), R(2), //
+ B(PushContext), R(1), //
+ B(PopContext), R(1), //
+ B(Mov), R(context), R(2), //
+ B(LdaSmi8), U8(2), //
+ B(Star), R(0), //
+ B(Jump), U8(34), //
+ B(Star), R(4), //
+ B(LdaConstant), U8(1), //
+ B(Star), R(3), //
+ B(Ldar), R(closure), //
+ B(Star), R(5), //
+ B(CallRuntime), U16(Runtime::kPushCatchContext), R(3), U8(3), //
+ B(Star), R(2), //
+ B(CallRuntime), U16(Runtime::kInterpreterClearPendingMessage), //
+ /* */ R(0), U8(0), //
+ B(Ldar), R(2), //
+ B(PushContext), R(1), //
+ B(LdaSmi8), U8(3), //
+ B(Star), R(0), //
+ B(PopContext), R(1), //
+ B(LdaUndefined), //
+ B(Return), //
+ },
+ 2,
+ {"e1", "e2"},
+ 2,
+ {{4, 8, 10}, {41, 45, 47}}},
};
+ // clang-format on
for (size_t i = 0; i < arraysize(snippets); i++) {
Handle<BytecodeArray> bytecode_array =
@@ -4126,39 +4644,172 @@
InitializedHandleScope handle_scope;
BytecodeGeneratorHelper helper;
- // TODO(rmcilroy): modify tests when we have real try finally support.
- ExpectedSnippet<int> snippets[] = {
+ int closure = Register::function_closure().index();
+ int context = Register::current_context().index();
+
+ // clang-format off
+ ExpectedSnippet<const char*> snippets[] = {
{"var a = 1; try { a = 2; } finally { a = 3; }",
- kPointerSize,
+ 4 * kPointerSize,
1,
- 14,
+ 51,
{
- B(LdaSmi8), U8(1), //
- B(Star), R(0), //
- B(LdaSmi8), U8(2), //
- B(Star), R(0), //
- B(LdaSmi8), U8(3), //
- B(Star), R(0), //
- B(LdaUndefined), //
- B(Return), //
+ B(StackCheck), //
+ B(LdaSmi8), U8(1), //
+ B(Star), R(0), //
+ B(Mov), R(context), R(3), //
+ B(LdaSmi8), U8(2), //
+ B(Star), R(0), //
+ B(LdaSmi8), U8(-1), //
+ B(Star), R(1), //
+ B(Jump), U8(7), //
+ B(Star), R(2), //
+ B(LdaZero), //
+ B(Star), R(1), //
+ B(CallRuntime), U16(Runtime::kInterpreterClearPendingMessage), //
+ /* */ R(0), U8(0), //
+ B(Star), R(3), //
+ B(LdaSmi8), U8(3), //
+ B(Star), R(0), //
+ B(CallRuntime), U16(Runtime::kInterpreterSetPendingMessage), //
+ /* */ R(3), U8(1), //
+ B(LdaZero), //
+ B(TestEqualStrict), R(1), //
+ B(JumpIfTrue), U8(4), //
+ B(Jump), U8(5), //
+ B(Ldar), R(2), //
+ B(ReThrow), //
+ B(LdaUndefined), //
+ B(Return), //
},
- 0},
+ 0,
+ {},
+ 1,
+ {{8, 12, 18}}},
{"var a = 1; try { a = 2; } catch(e) { a = 20 } finally { a = 3; }",
- 2 * kPointerSize,
+ 9 * kPointerSize,
1,
- 14,
+ 88,
{
- B(LdaSmi8), U8(1), //
- B(Star), R(0), //
- B(LdaSmi8), U8(2), //
- B(Star), R(0), //
- B(LdaSmi8), U8(3), //
- B(Star), R(0), //
- B(LdaUndefined), //
- B(Return), //
+ B(StackCheck), //
+ B(LdaSmi8), U8(1), //
+ B(Star), R(0), //
+ B(Mov), R(context), R(4), //
+ B(Mov), R(context), R(5), //
+ B(LdaSmi8), U8(2), //
+ B(Star), R(0), //
+ B(Jump), U8(34), //
+ B(Star), R(7), //
+ B(LdaConstant), U8(0), //
+ B(Star), R(6), //
+ B(Ldar), R(closure), //
+ B(Star), R(8), //
+ B(CallRuntime), U16(Runtime::kPushCatchContext), R(6), U8(3), //
+ B(Star), R(5), //
+ B(CallRuntime), U16(Runtime::kInterpreterClearPendingMessage), //
+ /* */ R(0), U8(0), //
+ B(Ldar), R(5), //
+ B(PushContext), R(1), //
+ B(LdaSmi8), U8(20), //
+ B(Star), R(0), //
+ B(PopContext), R(1), //
+ B(LdaSmi8), U8(-1), //
+ B(Star), R(2), //
+ B(Jump), U8(7), //
+ B(Star), R(3), //
+ B(LdaZero), //
+ B(Star), R(2), //
+ B(CallRuntime), U16(Runtime::kInterpreterClearPendingMessage), //
+ /* */ R(0), U8(0), //
+ B(Star), R(4), //
+ B(LdaSmi8), U8(3), //
+ B(Star), R(0), //
+ B(CallRuntime), U16(Runtime::kInterpreterSetPendingMessage), //
+ /* */ R(4), U8(1), //
+ B(LdaZero), //
+ B(TestEqualStrict), R(2), //
+ B(JumpIfTrue), U8(4), //
+ B(Jump), U8(5), //
+ B(Ldar), R(3), //
+ B(ReThrow), //
+ B(LdaUndefined), //
+ B(Return), //
},
- 0},
+ 1,
+ {"e"},
+ 2,
+ {{8, 49, 55}, {11, 15, 17}}},
+ {"var a; try {"
+ " try { a = 1 } catch(e) { a = 2 }"
+ "} catch(e) { a = 20 } finally { a = 3; }",
+ 10 * kPointerSize,
+ 1,
+ 121,
+ {
+ B(StackCheck), //
+ B(Mov), R(context), R(4), //
+ B(Mov), R(context), R(5), //
+ B(Mov), R(context), R(6), //
+ B(LdaSmi8), U8(1), //
+ B(Star), R(0), //
+ B(Jump), U8(34), //
+ B(Star), R(8), //
+ B(LdaConstant), U8(0), //
+ B(Star), R(7), //
+ B(Ldar), R(closure), //
+ B(Star), R(9), //
+ B(CallRuntime), U16(Runtime::kPushCatchContext), R(7), U8(3), //
+ B(Star), R(6), //
+ B(CallRuntime), U16(Runtime::kInterpreterClearPendingMessage), //
+ /* */ R(0), U8(0), //
+ B(Ldar), R(6), //
+ B(PushContext), R(1), //
+ B(LdaSmi8), U8(2), //
+ B(Star), R(0), //
+ B(PopContext), R(1), //
+ B(Jump), U8(34), //
+ B(Star), R(7), //
+ B(LdaConstant), U8(0), //
+ B(Star), R(6), //
+ B(Ldar), R(closure), //
+ B(Star), R(8), //
+ B(CallRuntime), U16(Runtime::kPushCatchContext), R(6), U8(3), //
+ B(Star), R(5), //
+ B(CallRuntime), U16(Runtime::kInterpreterClearPendingMessage), //
+ /* */ R(0), U8(0), //
+ B(Ldar), R(5), //
+ B(PushContext), R(1), //
+ B(LdaSmi8), U8(20), //
+ B(Star), R(0), //
+ B(PopContext), R(1), //
+ B(LdaSmi8), U8(-1), //
+ B(Star), R(2), //
+ B(Jump), U8(7), //
+ B(Star), R(3), //
+ B(LdaZero), //
+ B(Star), R(2), //
+ B(CallRuntime), U16(Runtime::kInterpreterClearPendingMessage), //
+ /* */ R(0), U8(0), //
+ B(Star), R(4), //
+ B(LdaSmi8), U8(3), //
+ B(Star), R(0), //
+ B(CallRuntime), U16(Runtime::kInterpreterSetPendingMessage), //
+ /* */ R(4), U8(1), //
+ B(LdaZero), //
+ B(TestEqualStrict), R(2), //
+ B(JumpIfTrue), U8(4), //
+ B(Jump), U8(5), //
+ B(Ldar), R(3), //
+ B(ReThrow), //
+ B(LdaUndefined), //
+ B(Return), //
+ },
+ 1,
+ {"e"},
+ 3,
+ {{4, 82, 88}, {7, 48, 50}, {10, 14, 16}}},
};
+ // clang-format on
for (size_t i = 0; i < arraysize(snippets); i++) {
Handle<BytecodeArray> bytecode_array =
@@ -4172,13 +4823,14 @@
InitializedHandleScope handle_scope;
BytecodeGeneratorHelper helper;
- // TODO(rmcilroy): modify tests when we have real try catch support.
+ // clang-format off
ExpectedSnippet<const char*> snippets[] = {
{"throw 1;",
0,
1,
- 3,
+ 4,
{
+ B(StackCheck), //
B(LdaSmi8), U8(1), //
B(Throw), //
},
@@ -4186,8 +4838,9 @@
{"throw 'Error';",
0,
1,
- 3,
+ 4,
{
+ B(StackCheck), //
B(LdaConstant), U8(0), //
B(Throw), //
},
@@ -4196,8 +4849,9 @@
{"var a = 1; if (a) { throw 'Error'; };",
1 * kPointerSize,
1,
- 11,
+ 12,
{
+ B(StackCheck), //
B(LdaSmi8), U8(1), //
B(Star), R(0), //
B(JumpIfToBooleanFalse), U8(5), //
@@ -4209,6 +4863,7 @@
1,
{"Error"}},
};
+ // clang-format on
for (size_t i = 0; i < arraysize(snippets); i++) {
Handle<BytecodeArray> bytecode_array =
@@ -4231,15 +4886,17 @@
Handle<i::TypeFeedbackVector> vector =
i::NewTypeFeedbackVector(helper.isolate(), &feedback_spec);
+ // clang-format off
ExpectedSnippet<InstanceType> snippets[] = {
{"function bar() { this.value = 0; }\n"
"function f() { return new bar(); }\n"
"f()",
1 * kPointerSize,
1,
- 10,
+ 11,
{
- B(LdaGlobalSloppy), U8(0), U8(vector->GetIndex(slot2)), //
+ B(StackCheck), //
+ B(LdaGlobal), U8(0), U8(vector->GetIndex(slot2)), //
B(Star), R(0), //
B(New), R(0), R(0), U8(0), //
B(Return), //
@@ -4251,12 +4908,14 @@
"f()",
2 * kPointerSize,
1,
- 14,
+ 17,
{
- B(LdaGlobalSloppy), U8(0), U8(vector->GetIndex(slot2)), //
+ B(StackCheck), //
+ B(LdaGlobal), U8(0), U8(vector->GetIndex(slot2)), //
B(Star), R(0), //
B(LdaSmi8), U8(3), //
B(Star), R(1), //
+ B(Ldar), R(0), //
B(New), R(0), R(1), U8(1), //
B(Return), //
},
@@ -4272,9 +4931,10 @@
"f()",
4 * kPointerSize,
1,
- 22,
+ 25,
{
- B(LdaGlobalSloppy), U8(0), U8(vector->GetIndex(slot2)), //
+ B(StackCheck), //
+ B(LdaGlobal), U8(0), U8(vector->GetIndex(slot2)), //
B(Star), R(0), //
B(LdaSmi8), U8(3), //
B(Star), R(1), //
@@ -4282,12 +4942,14 @@
B(Star), R(2), //
B(LdaSmi8), U8(5), //
B(Star), R(3), //
+ B(Ldar), R(0), //
B(New), R(0), R(1), U8(3), //
B(Return), //
},
1,
{InstanceType::ONE_BYTE_INTERNALIZED_STRING_TYPE}},
};
+ // clang-format on
for (size_t i = 0; i < arraysize(snippets); i++) {
Handle<BytecodeArray> bytecode_array =
@@ -4309,6 +4971,7 @@
i::NewTypeFeedbackVector(helper.isolate(), &feedback_spec);
int closure = Register::function_closure().index();
+ int context = Register::current_context().index();
int new_target = Register::new_target().index();
int first_context_slot = Context::MIN_CONTEXT_SLOTS;
@@ -4318,15 +4981,17 @@
STATIC_ASSERT(Context::MIN_CONTEXT_SLOTS + 3 + 249 == 256);
int wide_slot = first_context_slot + 3;
+ // clang-format off
ExpectedSnippet<InstanceType> snippets[] = {
{"var a; return function() { a = 1; };",
1 * kPointerSize,
1,
- 11,
+ 12,
{
B(CallRuntime), U16(Runtime::kNewFunctionContext), //
- R(closure), U8(1), //
+ /* */ R(closure), U8(1), //
B(PushContext), R(0), //
+ B(StackCheck), //
B(CreateClosure), U8(0), U8(0), //
B(Return), //
},
@@ -4335,49 +5000,52 @@
{"var a = 1; return function() { a = 2; };",
1 * kPointerSize,
1,
- 16,
+ 17,
{
- B(CallRuntime), U16(Runtime::kNewFunctionContext), //
- R(closure), U8(1), //
- B(PushContext), R(0), //
- B(LdaSmi8), U8(1), //
- B(StaContextSlot), R(0), U8(first_context_slot), //
- B(CreateClosure), U8(0), U8(0), //
- B(Return), //
+ B(CallRuntime), U16(Runtime::kNewFunctionContext), //
+ /* */ R(closure), U8(1), //
+ B(PushContext), R(0), //
+ B(StackCheck), //
+ B(LdaSmi8), U8(1), //
+ B(StaContextSlot), R(context), U8(first_context_slot), //
+ B(CreateClosure), U8(0), U8(0), //
+ B(Return), //
},
1,
{InstanceType::SHARED_FUNCTION_INFO_TYPE}},
{"var a = 1; var b = 2; return function() { a = 2; b = 3 };",
1 * kPointerSize,
1,
- 21,
+ 22,
{
- B(CallRuntime), U16(Runtime::kNewFunctionContext), //
- R(closure), U8(1), //
- B(PushContext), R(0), //
- B(LdaSmi8), U8(1), //
- B(StaContextSlot), R(0), U8(first_context_slot), //
- B(LdaSmi8), U8(2), //
- B(StaContextSlot), R(0), U8(first_context_slot + 1), //
- B(CreateClosure), U8(0), U8(0), //
- B(Return), //
+ B(CallRuntime), U16(Runtime::kNewFunctionContext), //
+ /* */ R(closure), U8(1), //
+ B(PushContext), R(0), //
+ B(StackCheck), //
+ B(LdaSmi8), U8(1), //
+ B(StaContextSlot), R(context), U8(first_context_slot), //
+ B(LdaSmi8), U8(2), //
+ B(StaContextSlot), R(context), U8(first_context_slot + 1), //
+ B(CreateClosure), U8(0), U8(0), //
+ B(Return), //
},
1,
{InstanceType::SHARED_FUNCTION_INFO_TYPE}},
{"var a; (function() { a = 2; })(); return a;",
3 * kPointerSize,
1,
- 24,
+ 25,
{
B(CallRuntime), U16(Runtime::kNewFunctionContext), //
- R(closure), U8(1), //
+ /* */ R(closure), U8(1), //
B(PushContext), R(0), //
+ B(StackCheck), //
B(LdaUndefined), //
B(Star), R(2), //
B(CreateClosure), U8(0), U8(0), //
B(Star), R(1), //
- B(Call), R(1), R(2), U8(0), U8(vector->GetIndex(slot)), //
- B(LdaContextSlot), R(0), U8(first_context_slot), //
+ B(Call), R(1), R(2), U8(1), U8(vector->GetIndex(slot)), //
+ B(LdaContextSlot), R(context), U8(first_context_slot), //
B(Return), //
},
1,
@@ -4385,15 +5053,16 @@
{"'use strict'; let a = 1; { let b = 2; return function() { a + b; }; }",
4 * kPointerSize,
1,
- 44,
+ 47,
{
B(CallRuntime), U16(Runtime::kNewFunctionContext), //
- R(closure), U8(1), //
+ /* */ R(closure), U8(1), //
B(PushContext), R(0), //
B(LdaTheHole), //
- B(StaContextSlot), R(0), U8(first_context_slot), //
+ B(StaContextSlot), R(context), U8(first_context_slot), //
+ B(StackCheck), //
B(LdaSmi8), U8(1), //
- B(StaContextSlot), R(0), U8(first_context_slot), //
+ B(StaContextSlot), R(context), U8(first_context_slot), //
B(LdaConstant), U8(0), //
B(Star), R(2), //
B(Ldar), R(closure), //
@@ -4401,10 +5070,11 @@
B(CallRuntime), U16(Runtime::kPushBlockContext), R(2), U8(2), //
B(PushContext), R(1), //
B(LdaTheHole), //
- B(StaContextSlot), R(1), U8(first_context_slot), //
+ B(StaContextSlot), R(context), U8(first_context_slot), //
B(LdaSmi8), U8(2), //
- B(StaContextSlot), R(1), U8(first_context_slot), //
+ B(StaContextSlot), R(context), U8(first_context_slot), //
B(CreateClosure), U8(1), U8(0), //
+ B(PopContext), R(0), //
B(Return), //
},
2,
@@ -4417,33 +5087,35 @@
"return b",
3 * kPointerSize,
1,
- 1041,
+ 1042,
{
B(CallRuntime), U16(Runtime::kNewFunctionContext), R(closure), //
- U8(1), //
+ /* */ U8(1), //
B(PushContext), R(0), //
B(Ldar), THIS(1), //
- B(StaContextSlot), R(0), U8(first_context_slot), //
+ B(StaContextSlot), R(context), U8(first_context_slot), //
B(CreateUnmappedArguments), //
- B(StaContextSlot), R(0), U8(first_context_slot + 1), //
+ B(StaContextSlot), R(context), U8(first_context_slot + 1), //
B(Ldar), R(new_target), //
- B(StaContextSlot), R(0), U8(first_context_slot + 2), //
+ B(StaContextSlot), R(context), U8(first_context_slot + 2), //
+ B(StackCheck), //
REPEAT_249(COMMA, //
B(LdaZero), //
- B(StaContextSlot), R(0), U8(wide_slot++)), //
+ B(StaContextSlot), R(context), U8(wide_slot++)), //
B(LdaUndefined), //
B(Star), R(2), //
- B(LdaGlobalStrict), U8(0), U8(1), //
+ B(LdaGlobal), U8(0), U8(1), //
B(Star), R(1), //
- B(Call), R(1), R(2), U8(0), U8(0), //
+ B(Call), R(1), R(2), U8(1), U8(0), //
B(LdaSmi8), U8(100), //
- B(StaContextSlotWide), R(0), U16(256), //
- B(LdaContextSlotWide), R(0), U16(256), //
+ B(StaContextSlotWide), R(context), U16(256), //
+ B(LdaContextSlotWide), R(context), U16(256), //
B(Return), //
},
1,
{InstanceType::ONE_BYTE_INTERNALIZED_STRING_TYPE}},
};
+ // clang-format on
for (size_t i = 0; i < arraysize(snippets); i++) {
Handle<BytecodeArray> bytecode_array =
@@ -4458,74 +5130,81 @@
BytecodeGeneratorHelper helper;
int closure = Register::function_closure().index();
+ int context = Register::current_context().index();
int first_context_slot = Context::MIN_CONTEXT_SLOTS;
+ // clang-format off
ExpectedSnippet<InstanceType> snippets[] = {
{"function f(arg1) { return function() { arg1 = 2; }; }",
1 * kPointerSize,
2,
- 16,
+ 17,
{
- B(CallRuntime), U16(Runtime::kNewFunctionContext), //
- R(closure), U8(1), //
- B(PushContext), R(0), //
- B(Ldar), R(helper.kLastParamIndex), //
- B(StaContextSlot), R(0), U8(first_context_slot), //
- B(CreateClosure), U8(0), U8(0), //
- B(Return), //
+ B(CallRuntime), U16(Runtime::kNewFunctionContext), //
+ /* */ R(closure), U8(1), //
+ B(PushContext), R(0), //
+ B(Ldar), R(helper.kLastParamIndex), //
+ B(StaContextSlot), R(context), U8(first_context_slot), //
+ B(StackCheck), //
+ B(CreateClosure), U8(0), U8(0), //
+ B(Return), //
},
1,
{InstanceType::SHARED_FUNCTION_INFO_TYPE}},
{"function f(arg1) { var a = function() { arg1 = 2; }; return arg1; }",
2 * kPointerSize,
2,
- 21,
+ 22,
{
- B(CallRuntime), U16(Runtime::kNewFunctionContext), //
- R(closure), U8(1), //
- B(PushContext), R(1), //
- B(Ldar), R(helper.kLastParamIndex), //
- B(StaContextSlot), R(1), U8(first_context_slot), //
- B(CreateClosure), U8(0), U8(0), //
- B(Star), R(0), //
- B(LdaContextSlot), R(1), U8(first_context_slot), //
- B(Return), //
+ B(CallRuntime), U16(Runtime::kNewFunctionContext), //
+ /* */ R(closure), U8(1), //
+ B(PushContext), R(1), //
+ B(Ldar), R(helper.kLastParamIndex), //
+ B(StaContextSlot), R(context), U8(first_context_slot), //
+ B(StackCheck), //
+ B(CreateClosure), U8(0), U8(0), //
+ B(Star), R(0), //
+ B(LdaContextSlot), R(context), U8(first_context_slot), //
+ B(Return), //
},
1,
{InstanceType::SHARED_FUNCTION_INFO_TYPE}},
{"function f(a1, a2, a3, a4) { return function() { a1 = a3; }; }",
1 * kPointerSize,
5,
- 21,
+ 22,
{
- B(CallRuntime), U16(Runtime::kNewFunctionContext), //
- R(closure), U8(1), //
- B(PushContext), R(0), //
- B(Ldar), R(helper.kLastParamIndex - 3), //
- B(StaContextSlot), R(0), U8(first_context_slot + 1), //
- B(Ldar), R(helper.kLastParamIndex -1), //
- B(StaContextSlot), R(0), U8(first_context_slot), //
- B(CreateClosure), U8(0), U8(0), //
- B(Return), //
+ B(CallRuntime), U16(Runtime::kNewFunctionContext), //
+ /* */ R(closure), U8(1), //
+ B(PushContext), R(0), //
+ B(Ldar), R(helper.kLastParamIndex - 3), //
+ B(StaContextSlot), R(context), U8(first_context_slot + 1), //
+ B(Ldar), R(helper.kLastParamIndex -1), //
+ B(StaContextSlot), R(context), U8(first_context_slot), //
+ B(StackCheck), //
+ B(CreateClosure), U8(0), U8(0), //
+ B(Return), //
},
1,
{InstanceType::SHARED_FUNCTION_INFO_TYPE}},
{"function f() { var self = this; return function() { self = 2; }; }",
1 * kPointerSize,
1,
- 16,
+ 17,
{
- B(CallRuntime), U16(Runtime::kNewFunctionContext), //
- R(closure), U8(1), //
- B(PushContext), R(0), //
- B(Ldar), R(helper.kLastParamIndex), //
- B(StaContextSlot), R(0), U8(first_context_slot), //
- B(CreateClosure), U8(0), U8(0), //
- B(Return), //
+ B(CallRuntime), U16(Runtime::kNewFunctionContext), //
+ /* */ R(closure), U8(1), //
+ B(PushContext), R(0), //
+ B(StackCheck), //
+ B(Ldar), R(helper.kLastParamIndex), //
+ B(StaContextSlot), R(context), U8(first_context_slot), //
+ B(CreateClosure), U8(0), U8(0), //
+ B(Return), //
},
1,
{InstanceType::SHARED_FUNCTION_INFO_TYPE}},
};
+ // clang-format on
for (size_t i = 0; i < arraysize(snippets); i++) {
Handle<BytecodeArray> bytecode_array =
@@ -4539,9 +5218,10 @@
InitializedHandleScope handle_scope;
BytecodeGeneratorHelper helper;
- int context = Register::function_context().index();
+ int context = Register::current_context().index();
int first_context_slot = Context::MIN_CONTEXT_SLOTS;
+ // clang-format off
ExpectedSnippet<InstanceType> snippets[] = {
{"function Outer() {"
" var outerVar = 1;"
@@ -4553,8 +5233,9 @@
"var f = new Outer().getInnerFunc();",
2 * kPointerSize,
1,
- 20,
+ 21,
{
+ B(StackCheck), //
B(Ldar), R(context), //
B(Star), R(0), //
B(LdaContextSlot), R(0), U8(Context::PREVIOUS_INDEX), //
@@ -4575,8 +5256,9 @@
"var f = new Outer().getInnerFunc();",
2 * kPointerSize,
1,
- 21,
+ 22,
{
+ B(StackCheck), //
B(LdaContextSlot), R(context), U8(first_context_slot), //
B(Star), R(0), //
B(Ldar), R(context), //
@@ -4589,6 +5271,7 @@
B(Return), //
}},
};
+ // clang-format on
for (size_t i = 0; i < arraysize(snippets); i++) {
Handle<BytecodeArray> bytecode_array =
@@ -4615,6 +5298,7 @@
i::NewTypeFeedbackVector(helper.isolate(), &store_feedback_spec);
int closure = Register::function_closure().index();
+ int context = Register::current_context().index();
int first_context_slot = Context::MIN_CONTEXT_SLOTS;
int object_literal_flags =
@@ -4622,12 +5306,14 @@
int array_literal_flags =
ArrayLiteral::kDisableMementos | ArrayLiteral::kShallowElements;
+ // clang-format off
ExpectedSnippet<InstanceType> snippets[] = {
{"var a = 1; return ++a;",
1 * kPointerSize,
1,
- 9,
+ 10,
{
+ B(StackCheck), //
B(LdaSmi8), U8(1), //
B(Star), R(0), //
B(ToNumber), //
@@ -4638,8 +5324,9 @@
{"var a = 1; return a++;",
2 * kPointerSize,
1,
- 13,
+ 14,
{
+ B(StackCheck), //
B(LdaSmi8), U8(1), //
B(Star), R(0), //
B(ToNumber), //
@@ -4652,8 +5339,9 @@
{"var a = 1; return --a;",
1 * kPointerSize,
1,
- 9,
+ 10,
{
+ B(StackCheck), //
B(LdaSmi8), U8(1), //
B(Star), R(0), //
B(ToNumber), //
@@ -4664,8 +5352,9 @@
{"var a = 1; return a--;",
2 * kPointerSize,
1,
- 13,
+ 14,
{
+ B(StackCheck), //
B(LdaSmi8), U8(1), //
B(Star), R(0), //
B(ToNumber), //
@@ -4678,12 +5367,14 @@
{"var a = { val: 1 }; return a.val++;",
3 * kPointerSize,
1,
- 23,
+ 26,
{
+ B(StackCheck), //
B(CreateObjectLiteral), U8(0), U8(0), U8(object_literal_flags), //
+ B(Star), R(1), //
B(Star), R(0), //
B(Star), R(1), //
- B(LoadICSloppy), R(1), U8(1), U8(vector->GetIndex(slot1)), //
+ B(LoadIC), R(1), U8(1), U8(vector->GetIndex(slot1)), //
B(ToNumber), //
B(Star), R(2), //
B(Inc), //
@@ -4697,12 +5388,14 @@
{"var a = { val: 1 }; return --a.val;",
2 * kPointerSize,
1,
- 19,
+ 22,
{
+ B(StackCheck), //
B(CreateObjectLiteral), U8(0), U8(0), U8(object_literal_flags), //
+ B(Star), R(1), //
B(Star), R(0), //
B(Star), R(1), //
- B(LoadICSloppy), R(1), U8(1), U8(vector->GetIndex(slot1)), //
+ B(LoadIC), R(1), U8(1), U8(vector->GetIndex(slot1)), //
B(ToNumber), //
B(Dec), //
B(StoreICSloppy), R(1), U8(1), U8(vector->GetIndex(slot2)), //
@@ -4714,16 +5407,18 @@
{"var name = 'var'; var a = { val: 1 }; return a[name]--;",
5 * kPointerSize,
1,
- 30,
+ 33,
{
+ B(StackCheck), //
B(LdaConstant), U8(0), //
B(Star), R(0), //
B(CreateObjectLiteral), U8(1), U8(0), U8(object_literal_flags), //
+ B(Star), R(2), //
B(Star), R(1), //
B(Star), R(2), //
B(Ldar), R(0), //
B(Star), R(3), //
- B(KeyedLoadICSloppy), R(2), U8(vector->GetIndex(slot1)), //
+ B(KeyedLoadIC), R(2), U8(vector->GetIndex(slot1)), //
B(ToNumber), //
B(Star), R(4), //
B(Dec), //
@@ -4737,16 +5432,18 @@
{"var name = 'var'; var a = { val: 1 }; return ++a[name];",
4 * kPointerSize,
1,
- 26,
+ 29,
{
+ B(StackCheck), //
B(LdaConstant), U8(0), //
B(Star), R(0), //
B(CreateObjectLiteral), U8(1), U8(0), U8(object_literal_flags), //
+ B(Star), R(2), //
B(Star), R(1), //
B(Star), R(2), //
B(Ldar), R(0), //
B(Star), R(3), //
- B(KeyedLoadICSloppy), R(2), U8(vector->GetIndex(slot1)), //
+ B(KeyedLoadIC), R(2), U8(vector->GetIndex(slot1)), //
B(ToNumber), //
B(Inc), //
B(KeyedStoreICSloppy), R(2), R(3), U8(vector->GetIndex(slot2)), //
@@ -4758,19 +5455,20 @@
{"var a = 1; var b = function() { return a }; return ++a;",
2 * kPointerSize,
1,
- 26,
+ 27,
{
B(CallRuntime), U16(Runtime::kNewFunctionContext), R(closure), //
- U8(1), //
+ /* */ U8(1), //
B(PushContext), R(1), //
+ B(StackCheck), //
B(LdaSmi8), U8(1), //
- B(StaContextSlot), R(1), U8(first_context_slot), //
+ B(StaContextSlot), R(context), U8(first_context_slot), //
B(CreateClosure), U8(0), U8(0), //
B(Star), R(0), //
- B(LdaContextSlot), R(1), U8(first_context_slot), //
+ B(LdaContextSlot), R(context), U8(first_context_slot), //
B(ToNumber), //
B(Inc), //
- B(StaContextSlot), R(1), U8(first_context_slot), //
+ B(StaContextSlot), R(context), U8(first_context_slot), //
B(Return), //
},
1,
@@ -4778,20 +5476,21 @@
{"var a = 1; var b = function() { return a }; return a--;",
3 * kPointerSize,
1,
- 30,
+ 31,
{
B(CallRuntime), U16(Runtime::kNewFunctionContext), R(closure), //
- U8(1), //
+ /* */ U8(1), //
B(PushContext), R(1), //
+ B(StackCheck), //
B(LdaSmi8), U8(1), //
- B(StaContextSlot), R(1), U8(first_context_slot), //
+ B(StaContextSlot), R(context), U8(first_context_slot), //
B(CreateClosure), U8(0), U8(0), //
B(Star), R(0), //
- B(LdaContextSlot), R(1), U8(first_context_slot), //
+ B(LdaContextSlot), R(context), U8(first_context_slot), //
B(ToNumber), //
B(Star), R(2), //
B(Dec), //
- B(StaContextSlot), R(1), U8(first_context_slot), //
+ B(StaContextSlot), R(context), U8(first_context_slot), //
B(Ldar), R(2), //
B(Return), //
},
@@ -4800,8 +5499,9 @@
{"var idx = 1; var a = [1, 2]; return a[idx++] = 2;",
4 * kPointerSize,
1,
- 27,
+ 28,
{
+ B(StackCheck), //
B(LdaSmi8), U8(1), //
B(Star), R(0), //
B(CreateArrayLiteral), U8(0), U8(0), U8(array_literal_flags), //
@@ -4814,12 +5514,13 @@
B(Star), R(0), //
B(LdaSmi8), U8(2), //
B(KeyedStoreICSloppy), R(2), R(3), //
- U8(store_vector->GetIndex(store_slot)), //
+ /* */ U8(store_vector->GetIndex(store_slot)), //
B(Return), //
},
1,
{InstanceType::FIXED_ARRAY_TYPE}},
};
+ // clang-format on
for (size_t i = 0; i < arraysize(snippets); i++) {
Handle<BytecodeArray> bytecode_array =
@@ -4841,13 +5542,15 @@
Handle<i::TypeFeedbackVector> vector =
i::NewTypeFeedbackVector(helper.isolate(), &feedback_spec);
+ // clang-format off
ExpectedSnippet<const char*> snippets[] = {
{"var global = 1;\nfunction f() { return ++global; }\nf()",
0,
1,
- 9,
+ 10,
{
- B(LdaGlobalSloppy), U8(0), U8(vector->GetIndex(slot1)), //
+ B(StackCheck), //
+ B(LdaGlobal), U8(0), U8(vector->GetIndex(slot1)), //
B(ToNumber), //
B(Inc), //
B(StaGlobalSloppy), U8(0), U8(vector->GetIndex(slot2)), //
@@ -4858,9 +5561,10 @@
{"var global = 1;\nfunction f() { return global--; }\nf()",
1 * kPointerSize,
1,
- 13,
+ 14,
{
- B(LdaGlobalSloppy), U8(0), U8(vector->GetIndex(slot1)), //
+ B(StackCheck), //
+ B(LdaGlobal), U8(0), U8(vector->GetIndex(slot1)), //
B(ToNumber), //
B(Star), R(0), //
B(Dec), //
@@ -4874,9 +5578,10 @@
"f()",
0,
1,
- 9,
+ 10,
{
- B(LdaGlobalStrict), U8(0), U8(vector->GetIndex(slot1)), //
+ B(StackCheck), //
+ B(LdaGlobal), U8(0), U8(vector->GetIndex(slot1)), //
B(ToNumber), //
B(Dec), //
B(StaGlobalStrict), U8(0), U8(vector->GetIndex(slot2)), //
@@ -4887,9 +5592,10 @@
{"unallocated = 1;\nfunction f() { return unallocated++; }\nf()",
1 * kPointerSize,
1,
- 13,
+ 14,
{
- B(LdaGlobalSloppy), U8(0), U8(vector->GetIndex(slot1)), //
+ B(StackCheck), //
+ B(LdaGlobal), U8(0), U8(vector->GetIndex(slot1)), //
B(ToNumber), //
B(Star), R(0), //
B(Inc), //
@@ -4900,6 +5606,7 @@
1,
{"unallocated"}},
};
+ // clang-format on
for (size_t i = 0; i < arraysize(snippets); i++) {
Handle<BytecodeArray> bytecode_array =
@@ -4915,6 +5622,7 @@
Zone zone;
int closure = Register::function_closure().index();
+ int context = Register::current_context().index();
int first_context_slot = Context::MIN_CONTEXT_SLOTS;
FeedbackVectorSpec feedback_spec(&zone);
@@ -4926,12 +5634,15 @@
int object_literal_flags =
ObjectLiteral::kFastElements | ObjectLiteral::kDisableMementos;
+
+ // clang-format off
ExpectedSnippet<InstanceType> snippets[] = {
{"var a = 1; a += 2;",
2 * kPointerSize,
1,
- 14,
+ 15,
{
+ B(StackCheck), //
B(LdaSmi8), U8(1), //
B(Star), R(0), //
B(Star), R(1), //
@@ -4944,8 +5655,9 @@
{"var a = 1; a /= 2;",
2 * kPointerSize,
1,
- 14,
+ 15,
{
+ B(StackCheck), //
B(LdaSmi8), U8(1), //
B(Star), R(0), //
B(Star), R(1), //
@@ -4958,12 +5670,14 @@
{"var a = { val: 2 }; a.name *= 2;",
3 * kPointerSize,
1,
- 24,
+ 27,
{
+ B(StackCheck), //
B(CreateObjectLiteral), U8(0), U8(0), U8(object_literal_flags), //
+ B(Star), R(1), //
B(Star), R(0), //
B(Star), R(1), //
- B(LoadICSloppy), R(1), U8(1), U8(vector->GetIndex(slot1)), //
+ B(LoadIC), R(1), U8(1), U8(vector->GetIndex(slot1)), //
B(Star), R(2), //
B(LdaSmi8), U8(2), //
B(Mul), R(2), //
@@ -4977,14 +5691,16 @@
{"var a = { 1: 2 }; a[1] ^= 2;",
4 * kPointerSize,
1,
- 27,
+ 30,
{
+ B(StackCheck), //
B(CreateObjectLiteral), U8(0), U8(0), U8(object_literal_flags), //
+ B(Star), R(1), //
B(Star), R(0), //
B(Star), R(1), //
B(LdaSmi8), U8(1), //
B(Star), R(2), //
- B(KeyedLoadICSloppy), R(1), U8(vector->GetIndex(slot1)), //
+ B(KeyedLoadIC), R(1), U8(vector->GetIndex(slot1)), //
B(Star), R(3), //
B(LdaSmi8), U8(2), //
B(BitwiseXor), R(3), //
@@ -4997,25 +5713,27 @@
{"var a = 1; (function f() { return a; }); a |= 24;",
2 * kPointerSize,
1,
- 29,
+ 30,
{
B(CallRuntime), U16(Runtime::kNewFunctionContext), R(closure), //
- U8(1), //
+ /* */ U8(1), //
B(PushContext), R(0), //
+ B(StackCheck), //
B(LdaSmi8), U8(1), //
- B(StaContextSlot), R(0), U8(first_context_slot), //
+ B(StaContextSlot), R(context), U8(first_context_slot), //
B(CreateClosure), U8(0), U8(0), //
- B(LdaContextSlot), R(0), U8(first_context_slot), //
+ B(LdaContextSlot), R(context), U8(first_context_slot), //
B(Star), R(1), //
B(LdaSmi8), U8(24), //
B(BitwiseOr), R(1), //
- B(StaContextSlot), R(0), U8(first_context_slot), //
+ B(StaContextSlot), R(context), U8(first_context_slot), //
B(LdaUndefined), //
B(Return), //
},
1,
{InstanceType::SHARED_FUNCTION_INFO_TYPE}},
};
+ // clang-format on
for (size_t i = 0; i < arraysize(snippets); i++) {
Handle<BytecodeArray> bytecode_array =
@@ -5037,13 +5755,15 @@
Handle<i::TypeFeedbackVector> vector =
i::NewTypeFeedbackVector(helper.isolate(), &feedback_spec);
+ // clang-format off
ExpectedSnippet<const char*> snippets[] = {
{"var global = 1;\nfunction f() { return global &= 1; }\nf()",
1 * kPointerSize,
1,
- 13,
+ 14,
{
- B(LdaGlobalSloppy), U8(0), U8(vector->GetIndex(slot1)), //
+ B(StackCheck), //
+ B(LdaGlobal), U8(0), U8(vector->GetIndex(slot1)), //
B(Star), R(0), //
B(LdaSmi8), U8(1), //
B(BitwiseAnd), R(0), //
@@ -5055,9 +5775,10 @@
{"unallocated = 1;\nfunction f() { return unallocated += 1; }\nf()",
1 * kPointerSize,
1,
- 13,
+ 14,
{
- B(LdaGlobalSloppy), U8(0), U8(vector->GetIndex(slot1)), //
+ B(StackCheck), //
+ B(LdaGlobal), U8(0), U8(vector->GetIndex(slot1)), //
B(Star), R(0), //
B(LdaSmi8), U8(1), //
B(Add), R(0), //
@@ -5067,6 +5788,7 @@
1,
{"unallocated"}},
};
+ // clang-format on
for (size_t i = 0; i < arraysize(snippets); i++) {
Handle<BytecodeArray> bytecode_array =
@@ -5082,6 +5804,7 @@
Zone zone;
int closure = Register::function_closure().index();
+ int context = Register::current_context().index();
int first_context_slot = Context::MIN_CONTEXT_SLOTS;
FeedbackVectorSpec feedback_spec(&zone);
@@ -5090,82 +5813,96 @@
Handle<i::TypeFeedbackVector> vector =
i::NewTypeFeedbackVector(helper.isolate(), &feedback_spec);
+ // clang-format off
ExpectedSnippet<const char*> snippets[] = {
{"function f() { return arguments; }",
1 * kPointerSize,
1,
- 4,
+ 7,
{
B(CreateMappedArguments), //
B(Star), R(0), //
+ B(StackCheck), //
+ B(Ldar), R(0), //
B(Return), //
}},
{"function f() { return arguments[0]; }",
2 * kPointerSize,
1,
- 10,
+ 13,
{
B(CreateMappedArguments), //
B(Star), R(0), //
+ B(StackCheck), //
+ B(Ldar), R(0), //
B(Star), R(1), //
B(LdaZero), //
- B(KeyedLoadICSloppy), R(1), U8(vector->GetIndex(slot)), //
+ B(KeyedLoadIC), R(1), U8(vector->GetIndex(slot)), //
B(Return), //
}},
{"function f() { 'use strict'; return arguments; }",
1 * kPointerSize,
1,
- 4,
+ 7,
{
B(CreateUnmappedArguments), //
B(Star), R(0), //
+ B(StackCheck), //
+ B(Ldar), R(0), //
B(Return), //
}},
{"function f(a) { return arguments[0]; }",
3 * kPointerSize,
2,
- 22,
+ 25,
{
B(CallRuntime), U16(Runtime::kNewFunctionContext), R(closure), //
- U8(1), //
+ /* */ U8(1), //
B(PushContext), R(1), //
B(Ldar), R(BytecodeGeneratorHelper::kLastParamIndex), //
- B(StaContextSlot), R(1), U8(first_context_slot), //
+ B(StaContextSlot), R(context), U8(first_context_slot), //
B(CreateMappedArguments), //
B(Star), R(0), //
+ B(StackCheck), //
+ B(Ldar), R(0), //
B(Star), R(2), //
B(LdaZero), //
- B(KeyedLoadICSloppy), R(2), U8(vector->GetIndex(slot)), //
+ B(KeyedLoadIC), R(2), U8(vector->GetIndex(slot)), //
B(Return), //
}},
{"function f(a, b, c) { return arguments; }",
2 * kPointerSize,
4,
- 26,
+ 29,
{
B(CallRuntime), U16(Runtime::kNewFunctionContext), R(closure), //
- U8(1), //
+ /* */ U8(1), //
B(PushContext), R(1), //
B(Ldar), R(BytecodeGeneratorHelper::kLastParamIndex - 2), //
- B(StaContextSlot), R(1), U8(first_context_slot + 2), //
+ B(StaContextSlot), R(context), U8(first_context_slot + 2), //
B(Ldar), R(BytecodeGeneratorHelper::kLastParamIndex - 1), //
- B(StaContextSlot), R(1), U8(first_context_slot + 1), //
+ B(StaContextSlot), R(context), U8(first_context_slot + 1), //
B(Ldar), R(BytecodeGeneratorHelper::kLastParamIndex), //
- B(StaContextSlot), R(1), U8(first_context_slot), //
+ B(StaContextSlot), R(context), U8(first_context_slot), //
B(CreateMappedArguments), //
B(Star), R(0), //
+ B(StackCheck), //
+ B(Ldar), R(0), //
B(Return), //
}},
{"function f(a, b, c) { 'use strict'; return arguments; }",
1 * kPointerSize,
4,
- 4,
+ 7,
{
B(CreateUnmappedArguments), //
B(Star), R(0), //
+ B(StackCheck), //
+ B(Ldar), R(0), //
B(Return), //
}},
};
+ // clang-format on
for (size_t i = 0; i < arraysize(snippets); i++) {
Handle<BytecodeArray> bytecode_array =
@@ -5174,14 +5911,119 @@
}
}
+TEST(CreateRestParameter) {
+ InitializedHandleScope handle_scope;
+ BytecodeGeneratorHelper helper;
+ Zone zone;
+
+ FeedbackVectorSpec feedback_spec(&zone);
+ FeedbackVectorSlot slot = feedback_spec.AddKeyedLoadICSlot();
+ FeedbackVectorSlot slot1 = feedback_spec.AddKeyedLoadICSlot();
+
+ Handle<i::TypeFeedbackVector> vector =
+ i::NewTypeFeedbackVector(helper.isolate(), &feedback_spec);
+
+ // clang-format off
+ ExpectedSnippet<int> snippets[] = {
+ {"function f(...restArgs) { return restArgs; }",
+ 1 * kPointerSize,
+ 1,
+ 7,
+ {
+ B(CreateRestParameter), //
+ B(Star), R(0), //
+ B(StackCheck), //
+ B(Ldar), R(0), //
+ B(Return), //
+ },
+ 0,
+ {}},
+ {"function f(a, ...restArgs) { return restArgs; }",
+ 2 * kPointerSize,
+ 2,
+ 14,
+ {
+ B(CreateRestParameter), //
+ B(Star), R(0), //
+ B(LdaTheHole), //
+ B(Star), R(1), //
+ B(StackCheck), //
+ B(Ldar), A(1, 2), //
+ B(Star), R(1), //
+ B(Ldar), R(0), //
+ B(Return), //
+ },
+ 0,
+ {}},
+ {"function f(a, ...restArgs) { return restArgs[0]; }",
+ 3 * kPointerSize,
+ 2,
+ 20,
+ {
+ B(CreateRestParameter), //
+ B(Star), R(0), //
+ B(LdaTheHole), //
+ B(Star), R(1), //
+ B(StackCheck), //
+ B(Ldar), A(1, 2), //
+ B(Star), R(1), //
+ B(Ldar), R(0), //
+ B(Star), R(2), //
+ B(LdaZero), //
+ B(KeyedLoadIC), R(2), U8(vector->GetIndex(slot)), //
+ B(Return), //
+ },
+ 0,
+ {}},
+ {"function f(a, ...restArgs) { return restArgs[0] + arguments[0]; }",
+ 5 * kPointerSize,
+ 2,
+ 35,
+ {
+ B(CreateUnmappedArguments), //
+ B(Star), R(0), //
+ B(CreateRestParameter), //
+ B(Star), R(1), //
+ B(LdaTheHole), //
+ B(Star), R(2), //
+ B(StackCheck), //
+ B(Ldar), A(1, 2), //
+ B(Star), R(2), //
+ B(Ldar), R(1), //
+ B(Star), R(3), //
+ B(LdaZero), //
+ B(KeyedLoadIC), R(3), U8(vector->GetIndex(slot)), //
+ B(Star), R(4), //
+ B(Ldar), R(0), //
+ B(Star), R(3), //
+ B(LdaZero), //
+ B(KeyedLoadIC), R(3), U8(vector->GetIndex(slot1)), //
+ B(Add), R(4), //
+ B(Return), //
+ },
+ 0,
+ {}},
+ };
+ // clang-format on
+
+ for (size_t i = 0; i < arraysize(snippets); i++) {
+ Handle<BytecodeArray> bytecode_array =
+ helper.MakeBytecodeForFunction(snippets[i].code_snippet);
+ CheckBytecodeArrayEqual(snippets[i], bytecode_array);
+ }
+}
TEST(IllegalRedeclaration) {
+ bool old_legacy_const_flag = FLAG_legacy_const;
+ FLAG_legacy_const = true;
+
InitializedHandleScope handle_scope;
BytecodeGeneratorHelper helper;
CHECK_GE(MessageTemplate::kVarRedeclaration, 128);
// Must adapt bytecode if this changes.
+ // clang-format off
ExpectedSnippet<Handle<Object>, 2> snippets[] = {
{"const a = 1; { var a = 2; }",
3 * kPointerSize,
@@ -5199,12 +6041,15 @@
{helper.factory()->NewNumberFromInt(MessageTemplate::kVarRedeclaration),
helper.factory()->NewStringFromAsciiChecked("a")}},
};
+ // clang-format on
for (size_t i = 0; i < arraysize(snippets); i++) {
Handle<BytecodeArray> bytecode_array =
helper.MakeBytecodeForFunctionBody(snippets[i].code_snippet);
CheckBytecodeArrayEqual(snippets[i], bytecode_array);
}
+
+ FLAG_legacy_const = old_legacy_const_flag;
}
@@ -5226,53 +6071,69 @@
Handle<i::TypeFeedbackVector> vector =
i::NewTypeFeedbackVector(helper.isolate(), &feedback_spec);
+ // clang-format off
ExpectedSnippet<InstanceType> snippets[] = {
{"for (var p in null) {}",
2 * kPointerSize,
1,
- 2,
- {B(LdaUndefined), B(Return)},
+ 3,
+ {
+ B(StackCheck), //
+ B(LdaUndefined), //
+ B(Return) //
+ },
0},
{"for (var p in undefined) {}",
2 * kPointerSize,
1,
- 2,
- {B(LdaUndefined), B(Return)},
+ 3,
+ {
+ B(StackCheck), //
+ B(LdaUndefined), //
+ B(Return) //
+ },
0},
{"for (var p in undefined) {}",
2 * kPointerSize,
1,
- 2,
- {B(LdaUndefined), B(Return)},
+ 3,
+ {
+ B(StackCheck), //
+ B(LdaUndefined), //
+ B(Return) //
+ },
0},
{"var x = 'potatoes';\n"
"for (var p in x) { return p; }",
8 * kPointerSize,
1,
- 45,
+ 46,
{
- B(LdaConstant), U8(0), //
- B(Star), R(1), //
- B(JumpIfUndefined), U8(39), //
- B(JumpIfNull), U8(37), //
- B(ToObject), //
- B(JumpIfNull), U8(34), //
- B(Star), R(3), //
- B(ForInPrepare), R(4), R(5), R(6), //
- B(LdaZero), //
- B(Star), R(7), //
- B(ForInDone), R(7), R(6), //
- B(JumpIfTrue), U8(20), //
- B(ForInNext), R(3), R(4), R(5), R(7), //
- B(JumpIfUndefined), U8(7), //
- B(Star), R(0), //
- B(Star), R(2), //
- B(Return), //
- B(ForInStep), R(7), //
- B(Star), R(7), //
- B(Jump), U8(-21), //
- B(LdaUndefined), //
- B(Return), //
+ B(StackCheck), //
+ B(LdaConstant), U8(0), //
+ B(Star), R(1), //
+ B(JumpIfUndefined), U8(39), //
+ B(JumpIfNull), U8(37), //
+ B(ToObject), //
+ B(JumpIfNull), U8(34), //
+ B(Star), R(3), //
+ B(ForInPrepare), R(4), //
+ B(LdaZero), //
+ B(Star), R(7), //
+ B(ForInDone), R(7), R(6), //
+ B(JumpIfTrue), U8(22), //
+ B(ForInNext), R(3), R(7), R(4), //
+ B(JumpIfUndefined), U8(10), //
+ B(Star), R(0), //
+ B(StackCheck), //
+ B(Ldar), R(0), //
+ B(Star), R(2), //
+ B(Return), //
+ B(ForInStep), R(7), //
+ B(Star), R(7), //
+ B(Jump), U8(-23), //
+ B(LdaUndefined), //
+ B(Return), //
},
1,
{InstanceType::ONE_BYTE_INTERNALIZED_STRING_TYPE}},
@@ -5280,8 +6141,9 @@
"for (var p in [1,2,3]) { x += p; }",
9 * kPointerSize,
1,
- 57,
+ 58,
{
+ B(StackCheck), //
B(LdaZero), //
B(Star), R(1), //
B(CreateArrayLiteral), U8(0), U8(0), U8(3), //
@@ -5290,14 +6152,16 @@
B(ToObject), //
B(JumpIfNull), U8(43), //
B(Star), R(3), //
- B(ForInPrepare), R(4), R(5), R(6), //
+ B(ForInPrepare), R(4), //
B(LdaZero), //
B(Star), R(7), //
B(ForInDone), R(7), R(6), //
- B(JumpIfTrue), U8(29), //
- B(ForInNext), R(3), R(4), R(5), R(7), //
- B(JumpIfUndefined), U8(16), //
+ B(JumpIfTrue), U8(31), //
+ B(ForInNext), R(3), R(7), R(4), //
+ B(JumpIfUndefined), U8(19), //
B(Star), R(0), //
+ B(StackCheck), //
+ B(Ldar), R(0), //
B(Star), R(2), //
B(Ldar), R(1), //
B(Star), R(8), //
@@ -5306,7 +6170,7 @@
B(Star), R(1), //
B(ForInStep), R(7), //
B(Star), R(7), //
- B(Jump), U8(-30), //
+ B(Jump), U8(-32), //
B(LdaUndefined), //
B(Return), //
},
@@ -5319,31 +6183,34 @@
"}",
8 * kPointerSize,
1,
- 94,
+ 95,
{
+ B(StackCheck), //
B(CreateObjectLiteral), U8(0), U8(0), U8(deep_elements_flags), //
+ B(Star), R(1), //
B(Star), R(0), //
B(CreateArrayLiteral), U8(1), U8(1), U8(simple_flags), //
- B(JumpIfUndefined), U8(82), //
- B(JumpIfNull), U8(80), //
+ B(JumpIfUndefined), U8(80), //
+ B(JumpIfNull), U8(78), //
B(ToObject), //
- B(JumpIfNull), U8(77), //
+ B(JumpIfNull), U8(75), //
B(Star), R(1), //
- B(ForInPrepare), R(2), R(3), R(4), //
+ B(ForInPrepare), R(2), //
B(LdaZero), //
B(Star), R(5), //
B(ForInDone), R(5), R(4), //
B(JumpIfTrue), U8(63), //
- B(ForInNext), R(1), R(2), R(3), R(5), //
- B(JumpIfUndefined), U8(50), //
+ B(ForInNext), R(1), R(5), R(2), //
+ B(JumpIfUndefined), U8(51), //
B(Star), R(6), //
B(Ldar), R(0), //
B(Star), R(7), //
B(Ldar), R(6), //
B(StoreICSloppy), R(7), U8(2), U8(vector->GetIndex(slot4)), //
+ B(StackCheck), //
B(Ldar), R(0), //
B(Star), R(6), //
- B(LoadICSloppy), R(6), U8(2), U8(vector->GetIndex(slot2)), //
+ B(LoadIC), R(6), U8(2), U8(vector->GetIndex(slot2)), //
B(Star), R(7), //
B(LdaSmi8), U8(10), //
B(TestEqual), R(7), //
@@ -5351,7 +6218,7 @@
B(Jump), U8(20), //
B(Ldar), R(0), //
B(Star), R(6), //
- B(LoadICSloppy), R(6), U8(2), U8(vector->GetIndex(slot3)), //
+ B(LoadIC), R(6), U8(2), U8(vector->GetIndex(slot3)), //
B(Star), R(7), //
B(LdaSmi8), U8(20), //
B(TestEqual), R(7), //
@@ -5370,23 +6237,24 @@
"for (x[0] in [1,2,3]) { return x[3]; }",
9 * kPointerSize,
1,
- 71,
+ 70,
{
+ B(StackCheck), //
B(CreateArrayLiteral), U8(0), U8(0), U8(simple_flags), //
B(Star), R(0), //
B(CreateArrayLiteral), U8(1), U8(1), U8(simple_flags), //
- B(JumpIfUndefined), U8(59), //
- B(JumpIfNull), U8(57), //
+ B(JumpIfUndefined), U8(57), //
+ B(JumpIfNull), U8(55), //
B(ToObject), //
- B(JumpIfNull), U8(54), //
+ B(JumpIfNull), U8(52), //
B(Star), R(1), //
- B(ForInPrepare), R(2), R(3), R(4), //
+ B(ForInPrepare), R(2), //
B(LdaZero), //
B(Star), R(5), //
B(ForInDone), R(5), R(4), //
B(JumpIfTrue), U8(40), //
- B(ForInNext), R(1), R(2), R(3), R(5), //
- B(JumpIfUndefined), U8(27), //
+ B(ForInNext), R(1), R(5), R(2), //
+ B(JumpIfUndefined), U8(28), //
B(Star), R(6), //
B(Ldar), R(0), //
B(Star), R(7), //
@@ -5394,10 +6262,11 @@
B(Star), R(8), //
B(Ldar), R(6), //
B(KeyedStoreICSloppy), R(7), R(8), U8(vector->GetIndex(slot3)), //
+ B(StackCheck), //
B(Ldar), R(0), //
B(Star), R(6), //
B(LdaSmi8), U8(3), //
- B(KeyedLoadICSloppy), R(6), U8(vector->GetIndex(slot2)), //
+ B(KeyedLoadIC), R(6), U8(vector->GetIndex(slot2)), //
B(Return), //
B(ForInStep), R(5), //
B(Star), R(5), //
@@ -5408,6 +6277,259 @@
2,
{InstanceType::FIXED_ARRAY_TYPE, InstanceType::FIXED_ARRAY_TYPE}},
};
+ // clang-format on
+
+ for (size_t i = 0; i < arraysize(snippets); i++) {
+ Handle<BytecodeArray> bytecode_array =
+ helper.MakeBytecodeForFunctionBody(snippets[i].code_snippet);
+ CheckBytecodeArrayEqual(snippets[i], bytecode_array);
+ }
+}
+
+
+// TODO(rmcilroy): Do something about this; new bytecode is too large
+// (150+ instructions) to adapt manually.
+DISABLED_TEST(ForOf) {
+ InitializedHandleScope handle_scope;
+ BytecodeGeneratorHelper helper;
+ Zone zone;
+
+ int array_literal_flags =
+ ArrayLiteral::kDisableMementos | ArrayLiteral::kShallowElements;
+ int object_literal_flags =
+ ObjectLiteral::kFastElements | ObjectLiteral::kDisableMementos;
+
+ FeedbackVectorSpec feedback_spec(&zone);
+ FeedbackVectorSlot slot1 = feedback_spec.AddCallICSlot();
+ FeedbackVectorSlot slot2 = feedback_spec.AddKeyedLoadICSlot();
+ FeedbackVectorSlot slot3 = feedback_spec.AddCallICSlot();
+ FeedbackVectorSlot slot4 = feedback_spec.AddLoadICSlot();
+ FeedbackVectorSlot slot5 = feedback_spec.AddLoadICSlot();
+ FeedbackVectorSlot slot6 = feedback_spec.AddLoadICSlot();
+ FeedbackVectorSlot slot7 = feedback_spec.AddStoreICSlot();
+ FeedbackVectorSlot slot8 = feedback_spec.AddLoadICSlot();
+ Handle<i::TypeFeedbackVector> vector =
+ i::NewTypeFeedbackVector(helper.isolate(), &feedback_spec);
+
+ // clang-format off
+ ExpectedSnippet<InstanceType, 8> snippets[] = {
+ {"for (var p of [0, 1, 2]) {}",
+ 7 * kPointerSize,
+ 1,
+ 86,
+ {
+ B(StackCheck), //
+ B(CreateArrayLiteral), U8(0), U8(0), U8(array_literal_flags), //
+ B(Star), R(5), //
+ B(LdaConstant), U8(1), //
+ B(KeyedLoadIC), R(5), U8(vector->GetIndex(slot2)), //
+ B(Star), R(4), //
+ B(Call), R(4), R(5), U8(1), U8(vector->GetIndex(slot1)), //
+ B(Star), R(1), //
+ B(Ldar), R(1), //
+ B(Star), R(6), //
+ B(LoadIC), R(6), U8(2), U8(vector->GetIndex(slot4)), //
+ B(Star), R(5), //
+ B(Call), R(5), R(6), U8(1), U8(vector->GetIndex(slot3)), //
+ B(Star), R(2), //
+ B(Star), R(4), //
+ B(CallRuntime), U16(Runtime::kInlineIsJSReceiver), R(4), U8(1), //
+ B(LogicalNot), //
+ B(JumpIfFalse), U8(11), //
+ B(Ldar), R(2), //
+ B(Star), R(4), //
+ B(CallRuntime), U16(Runtime::kThrowIteratorResultNotAnObject), //
+ /* */ R(4), U8(1), //
+ B(Ldar), R(2), //
+ B(Star), R(4), //
+ B(LoadIC), R(4), U8(3), U8(vector->GetIndex(slot5)), //
+ B(JumpIfToBooleanTrue), U8(19), //
+ B(Ldar), R(2), //
+ B(Star), R(4), //
+ B(LoadIC), R(4), U8(4), U8(vector->GetIndex(slot6)), //
+ B(Star), R(0), //
+ B(StackCheck), //
+ B(Ldar), R(0), //
+ B(Star), R(3), //
+ B(Jump), U8(-61), //
+ B(LdaUndefined), //
+ B(Return), //
+ },
+ 5,
+ {InstanceType::FIXED_ARRAY_TYPE, InstanceType::SYMBOL_TYPE,
+ InstanceType::ONE_BYTE_INTERNALIZED_STRING_TYPE,
+ InstanceType::ONE_BYTE_INTERNALIZED_STRING_TYPE,
+ InstanceType::ONE_BYTE_INTERNALIZED_STRING_TYPE}},
+ {"var x = 'potatoes';\n"
+ "for (var p of x) { return p; }",
+ 8 * kPointerSize,
+ 1,
+ 85,
+ {
+ B(StackCheck), //
+ B(LdaConstant), U8(0), //
+ B(Star), R(3), //
+ B(Star), R(6), //
+ B(LdaConstant), U8(1), //
+ B(KeyedLoadIC), R(6), U8(vector->GetIndex(slot2)), //
+ B(Star), R(5), //
+ B(Call), R(5), R(6), U8(1), U8(vector->GetIndex(slot1)), //
+ B(Star), R(1), //
+ B(Ldar), R(1), //
+ B(Star), R(7), //
+ B(LoadIC), R(7), U8(2), U8(vector->GetIndex(slot4)), //
+ B(Star), R(6), //
+ B(Call), R(6), R(7), U8(1), U8(vector->GetIndex(slot3)), //
+ B(Star), R(2), //
+ B(Star), R(5), //
+ B(CallRuntime), U16(Runtime::kInlineIsJSReceiver), R(5), U8(1), //
+ B(LogicalNot), //
+ B(JumpIfFalse), U8(11), //
+ B(Ldar), R(2), //
+ B(Star), R(5), //
+ B(CallRuntime), U16(Runtime::kThrowIteratorResultNotAnObject), //
+ /* */ R(5), U8(1), //
+ B(Ldar), R(2), //
+ B(Star), R(5), //
+ B(LoadIC), R(5), U8(3), U8(vector->GetIndex(slot5)), //
+ B(JumpIfToBooleanTrue), U8(18), //
+ B(Ldar), R(2), //
+ B(Star), R(5), //
+ B(LoadIC), R(5), U8(4), U8(vector->GetIndex(slot6)), //
+ B(Star), R(0), //
+ B(StackCheck), //
+ B(Ldar), R(0), //
+ B(Star), R(4), //
+ B(Return), //
+ B(LdaUndefined), //
+ B(Return), //
+ },
+ 5,
+ {InstanceType::ONE_BYTE_INTERNALIZED_STRING_TYPE,
+ InstanceType::SYMBOL_TYPE,
+ InstanceType::ONE_BYTE_INTERNALIZED_STRING_TYPE,
+ InstanceType::ONE_BYTE_INTERNALIZED_STRING_TYPE,
+ InstanceType::ONE_BYTE_INTERNALIZED_STRING_TYPE}},
+ {"for (var x of [10, 20, 30]) {\n"
+ " if (x == 10) continue;\n"
+ " if (x == 20) break;\n"
+ "}",
+ 7 * kPointerSize,
+ 1,
+ 108,
+ {
+ B(StackCheck), //
+ B(CreateArrayLiteral), U8(0), U8(0), U8(array_literal_flags), //
+ B(Star), R(5), //
+ B(LdaConstant), U8(1), //
+ B(KeyedLoadIC), R(5), U8(vector->GetIndex(slot2)), //
+ B(Star), R(4), //
+ B(Call), R(4), R(5), U8(1), U8(vector->GetIndex(slot1)), //
+ B(Star), R(1), //
+ B(Ldar), R(1), //
+ B(Star), R(6), //
+ B(LoadIC), R(6), U8(2), U8(vector->GetIndex(slot4)), //
+ B(Star), R(5), //
+ B(Call), R(5), R(6), U8(1), U8(vector->GetIndex(slot3)), //
+ B(Star), R(2), //
+ B(Star), R(4), //
+ B(CallRuntime), U16(Runtime::kInlineIsJSReceiver), R(4), U8(1), //
+ B(LogicalNot), //
+ B(JumpIfFalse), U8(11), //
+ B(Ldar), R(2), //
+ B(Star), R(4), //
+ B(CallRuntime), U16(Runtime::kThrowIteratorResultNotAnObject), //
+ /* */ R(4), U8(1), //
+ B(Ldar), R(2), //
+ B(Star), R(4), //
+ B(LoadIC), R(4), U8(3), U8(vector->GetIndex(slot5)), //
+ B(JumpIfToBooleanTrue), U8(41), //
+ B(Ldar), R(2), //
+ B(Star), R(4), //
+ B(LoadIC), R(4), U8(4), U8(vector->GetIndex(slot6)), //
+ B(Star), R(0), //
+ B(StackCheck), //
+ B(Ldar), R(0), //
+ B(Star), R(3), //
+ B(Star), R(4), //
+ B(LdaSmi8), U8(10), //
+ B(TestEqual), R(4), //
+ B(JumpIfFalse), U8(4), //
+ B(Jump), U8(-69), //
+ B(Ldar), R(3), //
+ B(Star), R(4), //
+ B(LdaSmi8), U8(20), //
+ B(TestEqual), R(4), //
+ B(JumpIfFalse), U8(4), //
+ B(Jump), U8(4), //
+ B(Jump), U8(-83), //
+ B(LdaUndefined), //
+ B(Return), //
+ },
+ 5,
+ {InstanceType::FIXED_ARRAY_TYPE, InstanceType::SYMBOL_TYPE,
+ InstanceType::ONE_BYTE_INTERNALIZED_STRING_TYPE,
+ InstanceType::ONE_BYTE_INTERNALIZED_STRING_TYPE,
+ InstanceType::ONE_BYTE_INTERNALIZED_STRING_TYPE}},
+ {"var x = { 'a': 1, 'b': 2 };\n"
+ "for (x['a'] of [1,2,3]) { return x['a']; }",
+ 6 * kPointerSize,
+ 1,
+ 103,
+ {
+ B(StackCheck), //
+ B(CreateObjectLiteral), U8(0), U8(0), U8(object_literal_flags), //
+ B(Star), R(3), //
+ B(Star), R(2), //
+ B(CreateArrayLiteral), U8(1), U8(1), U8(array_literal_flags), //
+ B(Star), R(4), //
+ B(LdaConstant), U8(2), //
+ B(KeyedLoadIC), R(4), U8(vector->GetIndex(slot2)), //
+ B(Star), R(3), //
+ B(Call), R(3), R(4), U8(1), U8(vector->GetIndex(slot1)), //
+ B(Star), R(0), //
+ B(Ldar), R(0), //
+ B(Star), R(5), //
+ B(LoadIC), R(5), U8(3), U8(vector->GetIndex(slot4)), //
+ B(Star), R(4), //
+ B(Call), R(4), R(5), U8(1), U8(vector->GetIndex(slot3)), //
+ B(Star), R(1), //
+ B(Star), R(3), //
+ B(CallRuntime), U16(Runtime::kInlineIsJSReceiver), R(3), U8(1), //
+ B(LogicalNot), //
+ B(JumpIfFalse), U8(11), //
+ B(Ldar), R(1), //
+ B(Star), R(3), //
+ B(CallRuntime), U16(Runtime::kThrowIteratorResultNotAnObject), //
+ /* */ R(3), U8(1), //
+ B(Ldar), R(1), //
+ B(Star), R(3), //
+ B(LoadIC), R(3), U8(4), U8(vector->GetIndex(slot5)), //
+ B(JumpIfToBooleanTrue), U8(28), //
+ B(Ldar), R(2), //
+ B(Star), R(3), //
+ B(Ldar), R(1), //
+ B(Star), R(4), //
+ B(LoadIC), R(4), U8(5), U8(vector->GetIndex(slot6)), //
+ B(StoreICSloppy), R(3), U8(6), U8(vector->GetIndex(slot7)), //
+ B(StackCheck), //
+ B(Ldar), R(2), //
+ B(Star), R(3), //
+ B(LoadIC), R(3), U8(6), U8(vector->GetIndex(slot8)), //
+ B(Return), //
+ B(LdaUndefined), //
+ B(Return), //
+ },
+ 7,
+ {InstanceType::FIXED_ARRAY_TYPE,
+ InstanceType::FIXED_ARRAY_TYPE,
+ InstanceType::SYMBOL_TYPE,
+ InstanceType::ONE_BYTE_INTERNALIZED_STRING_TYPE,
+ InstanceType::ONE_BYTE_INTERNALIZED_STRING_TYPE,
+ InstanceType::ONE_BYTE_INTERNALIZED_STRING_TYPE,
+ InstanceType::ONE_BYTE_INTERNALIZED_STRING_TYPE}},
+ };
+ // clang-format on
for (size_t i = 0; i < arraysize(snippets); i++) {
Handle<BytecodeArray> bytecode_array =
@@ -5421,12 +6543,14 @@
InitializedHandleScope handle_scope;
BytecodeGeneratorHelper helper;
+ // clang-format off
ExpectedSnippet<int> snippets[] = {
{"return 1 ? 2 : 3;",
0,
1,
- 11,
+ 12,
{
+ B(StackCheck), //
B(LdaSmi8), U8(1), //
B(JumpIfToBooleanFalse), U8(6), //
B(LdaSmi8), U8(2), //
@@ -5437,8 +6561,9 @@
{"return 1 ? 2 ? 3 : 4 : 5;",
0,
1,
- 19,
+ 20,
{
+ B(StackCheck), //
B(LdaSmi8), U8(1), //
B(JumpIfToBooleanFalse), U8(14), //
B(LdaSmi8), U8(2), //
@@ -5451,6 +6576,7 @@
B(Return), //
}},
};
+ // clang-format on
for (size_t i = 0; i < arraysize(snippets); i++) {
Handle<BytecodeArray> bytecode_array =
@@ -5464,6 +6590,7 @@
InitializedHandleScope handle_scope;
BytecodeGeneratorHelper helper;
+ // clang-format off
ExpectedSnippet<int> snippets[] = {
{"var a = 1;\n"
"switch(a) {\n"
@@ -5472,8 +6599,9 @@
"}\n",
3 * kPointerSize,
1,
- 30,
+ 31,
{
+ B(StackCheck), //
B(LdaSmi8), U8(1), //
B(Star), R(1), // The tag variable is allocated as a
B(Star), R(0), // local by the parser, hence the store
@@ -5499,8 +6627,9 @@
"}\n",
3 * kPointerSize,
1,
- 36,
+ 37,
{
+ B(StackCheck), //
B(LdaSmi8), U8(1), //
B(Star), R(1), //
B(Star), R(0), //
@@ -5528,8 +6657,9 @@
"}\n",
3 * kPointerSize,
1,
- 34,
+ 35,
{
+ B(StackCheck), //
B(LdaSmi8), U8(1), //
B(Star), R(1), //
B(Star), R(0), //
@@ -5557,8 +6687,9 @@
"}\n",
3 * kPointerSize,
1,
- 34,
+ 35,
{
+ B(StackCheck), //
B(LdaSmi8), U8(1), //
B(Star), R(1), //
B(Star), R(0), //
@@ -5586,8 +6717,9 @@
"}\n",
3 * kPointerSize,
1,
- 43,
+ 44,
{
+ B(StackCheck), //
B(LdaSmi8), U8(1), //
B(Star), R(1), //
B(TypeOf), //
@@ -5619,8 +6751,9 @@
"}\n",
3 * kPointerSize,
1,
- 31,
+ 32,
{
+ B(StackCheck), //
B(LdaSmi8), U8(1), //
B(Star), R(1), //
B(Star), R(0), //
@@ -5647,8 +6780,9 @@
"}\n",
3 * kPointerSize,
1,
- 288,
+ 289,
{
+ B(StackCheck), //
B(LdaSmi8), U8(1), //
B(Star), R(1), //
B(Star), R(0), //
@@ -5683,8 +6817,9 @@
"}\n",
5 * kPointerSize,
1,
- 60,
+ 61,
{
+ B(StackCheck), //
B(LdaSmi8), U8(1), //
B(Star), R(2), //
B(Star), R(0), //
@@ -5718,6 +6853,7 @@
B(Return), //
}},
};
+ // clang-format on
for (size_t i = 0; i < arraysize(snippets); i++) {
Handle<BytecodeArray> bytecode_array =
@@ -5733,12 +6869,14 @@
// Check that we generate JumpIfToBoolean if they are at the start of basic
// blocks.
+ // clang-format off
ExpectedSnippet<int> snippets[] = {
{"var a = 1; if (a || a < 0) { return 1; }",
2 * kPointerSize,
1,
- 20,
+ 21,
{
+ B(StackCheck), //
B(LdaSmi8), U8(1), //
B(Star), R(0), //
B(JumpIfToBooleanTrue), U8(9), //
@@ -5755,8 +6893,9 @@
{"var a = 1; if (a && a < 0) { return 1; }",
2 * kPointerSize,
1,
- 20,
+ 21,
{
+ B(StackCheck), //
B(LdaSmi8), U8(1), //
B(Star), R(0), //
B(JumpIfToBooleanFalse), U8(9), //
@@ -5773,8 +6912,9 @@
{"var a = 1; a = (a || a < 0) ? 2 : 3;",
2 * kPointerSize,
1,
- 25,
+ 26,
{
+ B(StackCheck), //
B(LdaSmi8), U8(1), //
B(Star), R(0), //
B(JumpIfToBooleanTrue), U8(9), //
@@ -5791,6 +6931,7 @@
B(Return), //
}},
};
+ // clang-format on
for (size_t i = 0; i < arraysize(snippets); i++) {
Handle<BytecodeArray> bytecode_array =
@@ -5804,20 +6945,23 @@
InitializedHandleScope handle_scope;
BytecodeGeneratorHelper helper;
+ // clang-format off
ExpectedSnippet<int> snippets[] = {
{"return; var a = 1; a();",
1 * kPointerSize,
1,
- 2,
+ 3,
{
+ B(StackCheck), //
B(LdaUndefined), //
B(Return), //
}},
{"if (false) { return; }; var a = 1;",
1 * kPointerSize,
1,
- 6,
+ 7,
{
+ B(StackCheck), //
B(LdaSmi8), U8(1), //
B(Star), R(0), //
B(LdaUndefined), //
@@ -5826,16 +6970,18 @@
{"if (true) { return 1; } else { return 2; };",
0,
1,
- 3,
+ 4,
{
+ B(StackCheck), //
B(LdaSmi8), U8(1), //
B(Return), //
}},
{"var a = 1; if (a) { return 1; }; return 2;",
1 * kPointerSize,
1,
- 12,
+ 13,
{
+ B(StackCheck), //
B(LdaSmi8), U8(1), //
B(Star), R(0), //
B(JumpIfToBooleanFalse), U8(5), //
@@ -5845,6 +6991,7 @@
B(Return), //
}},
};
+ // clang-format on
for (size_t i = 0; i < arraysize(snippets); i++) {
Handle<BytecodeArray> bytecode_array =
@@ -5860,31 +7007,46 @@
int closure = Register::function_closure().index();
+ // clang-format off
ExpectedSnippet<int> snippets[] = {
{"var f;\n f = function f() { }",
- 1 * kPointerSize,
+ 2 * kPointerSize,
1,
- 9,
+ 19,
{
- B(LdaTheHole), //
- B(Star), R(0), //
- B(Ldar), R(closure), //
- B(Star), R(0), //
- B(LdaUndefined), //
- B(Return), //
+ B(LdaTheHole), //
+ B(Star), R(0), //
+ B(StackCheck), //
+ B(Ldar), R(closure), //
+ B(Star), R(1), //
+ B(Ldar), R(0), //
+ B(JumpIfNotHole), U8(5), //
+ B(Mov), R(1), R(0), //
+ B(Ldar), R(1), //
+ B(LdaUndefined), //
+ B(Return), //
}},
{"var f;\n f = function f() { return f; }",
- 1 * kPointerSize,
+ 2 * kPointerSize,
1,
- 8,
+ 23,
{
- B(LdaTheHole), //
- B(Star), R(0), //
- B(Ldar), R(closure), //
- B(Star), R(0), //
- B(Return), //
+ B(LdaTheHole), //
+ B(Star), R(0), //
+ B(StackCheck), //
+ B(Ldar), R(closure), //
+ B(Star), R(1), //
+ B(Ldar), R(0), //
+ B(JumpIfNotHole), U8(5), //
+ B(Mov), R(1), R(0), //
+ B(Ldar), R(1), //
+ B(Ldar), R(0), //
+ B(JumpIfNotHole), U8(3), //
+ B(LdaUndefined), //
+ B(Return), //
}},
};
+ // clang-format on
for (size_t i = 0; i < arraysize(snippets); i++) {
Handle<BytecodeArray> bytecode_array =
@@ -5900,27 +7062,44 @@
int new_target = Register::new_target().index();
- ExpectedSnippet<int> snippets[] = {
+ // clang-format off
+ ExpectedSnippet<InstanceType> snippets[] = {
{"return new.target;",
- 1 * kPointerSize,
+ 2 * kPointerSize,
1,
- 5,
+ 19,
{
- B(Ldar), R(new_target), //
- B(Star), R(0), //
- B(Return), //
- }},
+ B(Ldar), R(new_target), //
+ B(Star), R(0), //
+ B(StackCheck), //
+ B(Ldar), R(0), //
+ B(JumpIfNotHole), U8(11), //
+ B(LdaConstant), U8(0), //
+ B(Star), R(1), //
+ B(CallRuntime), U16(Runtime::kThrowReferenceError), R(1), U8(1), //
+ B(Return), //
+ },
+ 1,
+ {InstanceType::ONE_BYTE_INTERNALIZED_STRING_TYPE}},
{"new.target;",
- 1 * kPointerSize,
+ 2 * kPointerSize,
1,
- 6,
+ 20,
{
- B(Ldar), R(new_target), //
- B(Star), R(0), //
- B(LdaUndefined), //
- B(Return), //
- }},
- };
+ B(Ldar), R(new_target), //
+ B(Star), R(0), //
+ B(StackCheck), //
+ B(Ldar), R(0), //
+ B(JumpIfNotHole), U8(11), //
+ B(LdaConstant), U8(0), //
+ B(Star), R(1), //
+ B(CallRuntime), U16(Runtime::kThrowReferenceError), R(1), U8(1), //
+ B(LdaUndefined), //
+ B(Return), //
+ },
+ 1,
+ {InstanceType::ONE_BYTE_INTERNALIZED_STRING_TYPE}}};
+ // clang-format on
for (size_t i = 0; i < arraysize(snippets); i++) {
Handle<BytecodeArray> bytecode_array =
@@ -5934,6 +7113,7 @@
InitializedHandleScope handle_scope;
BytecodeGeneratorHelper helper;
+ // clang-format off
ExpectedSnippet<int> snippets[] = {
{"var ld_a = 1;\n" // This test is to check Ldar does not
"while(true) {\n" // get removed if the preceding Star is
@@ -5943,9 +7123,11 @@
"return ld_a;",
2 * kPointerSize,
1,
- 29,
- {B(LdaSmi8), U8(1), //
+ 31,
+ {B(StackCheck), //
+ B(LdaSmi8), U8(1), //
B(Star), R(0), //
+ B(StackCheck), //
B(Ldar), R(0), // This load should not be removed as it
B(Star), R(1), // is the target of the branch.
B(Ldar), R(0), //
@@ -5956,7 +7138,7 @@
B(TestGreaterThan), R(1), //
B(JumpIfFalse), U8(4), //
B(Jump), U8(4), //
- B(Jump), U8(-20), //
+ B(Jump), U8(-21), //
B(Ldar), R(0), //
B(Return)}},
{"var ld_a = 1;\n"
@@ -5967,9 +7149,11 @@
"return ld_a;",
2 * kPointerSize,
1,
- 27,
- {B(LdaSmi8), U8(1), //
+ 29,
+ {B(StackCheck), //
+ B(LdaSmi8), U8(1), //
B(Star), R(0), //
+ B(StackCheck), //
B(Ldar), R(0), //
B(Star), R(1), //
B(Ldar), R(0), //
@@ -5987,8 +7171,9 @@
" return ld_a;",
2 * kPointerSize,
1,
- 13,
+ 14,
{
+ B(StackCheck), //
B(LdaSmi8), U8(1), //
B(Star), R(0), //
B(Star), R(1), //
@@ -5998,6 +7183,7 @@
B(Return) //
}},
};
+ // clang-format on
for (size_t i = 0; i < arraysize(snippets); i++) {
Handle<BytecodeArray> bytecode_array =
@@ -6011,13 +7197,15 @@
InitializedHandleScope handle_scope;
BytecodeGeneratorHelper helper;
+ // clang-format off
ExpectedSnippet<const char*> snippets[] = {
{"var x = 0, y = 1;\n"
"return (x = 2, y = 3, x = 4, y = 5)",
2 * kPointerSize,
1,
- 24,
+ 25,
{
+ B(StackCheck), //
B(LdaZero), B(Star), R(0), //
B(LdaSmi8), U8(1), //
B(Star), R(1), //
@@ -6037,8 +7225,9 @@
"return y",
2 * kPointerSize,
1,
- 11,
+ 12,
{
+ B(StackCheck), //
B(LdaSmi8), U8(55), //
B(Star), R(0), //
B(LdaSmi8), U8(100), //
@@ -6052,8 +7241,9 @@
"return x;",
3 * kPointerSize,
1,
- 23,
+ 24,
{
+ B(StackCheck), //
B(LdaSmi8), U8(55), //
B(Star), R(0), //
B(Star), R(1), //
@@ -6074,8 +7264,9 @@
"return x;",
3 * kPointerSize,
1,
- 31,
+ 32,
{
+ B(StackCheck), //
B(LdaSmi8), U8(55), //
B(Star), R(0), //
B(LdaSmi8), U8(56), //
@@ -6100,8 +7291,9 @@
"return y;",
4 * kPointerSize,
1,
- 31,
+ 32,
{
+ B(StackCheck), //
B(LdaSmi8), U8(55), //
B(Star), R(0), //
B(Star), R(2), //
@@ -6125,8 +7317,9 @@
"return x;",
3 * kPointerSize,
1,
- 31,
+ 32,
{
+ B(StackCheck), //
B(LdaSmi8), U8(55), //
B(Star), R(0), //
B(Star), R(1), //
@@ -6150,8 +7343,9 @@
"y;\n",
5 * kPointerSize,
1,
- 69,
+ 70,
{
+ B(StackCheck), //
B(LdaSmi8), U8(10), //
B(Star), R(0), //
B(LdaSmi8), U8(20), //
@@ -6193,8 +7387,9 @@
"return 1 + x + (x++) + (++x);\n",
4 * kPointerSize,
1,
- 37,
+ 38,
{
+ B(StackCheck), //
B(LdaSmi8), U8(17), //
B(Star), R(0), //
B(LdaSmi8), U8(1), //
@@ -6217,7 +7412,9 @@
B(Add), R(3), //
B(Return), //
},
- 0}};
+ 0}
+ };
+ // clang-format on
for (size_t i = 0; i < arraysize(snippets); i++) {
Handle<BytecodeArray> bytecode_array =
@@ -6233,49 +7430,51 @@
Zone zone;
int closure = Register::function_closure().index();
- int context = Register::function_context().index();
+ int context = Register::current_context().index();
int new_target = Register::new_target().index();
int first_context_slot = Context::MIN_CONTEXT_SLOTS;
+ // clang-format off
ExpectedSnippet<const char*> snippets[] = {
{"return eval('1;');",
9 * kPointerSize,
1,
- 67,
+ 65,
{
- B(CallRuntime), U16(Runtime::kNewFunctionContext), R(closure), //
- U8(1), //
- B(PushContext), R(0), //
- B(Ldar), THIS(1), //
- B(StaContextSlot), R(0), U8(first_context_slot), //
- B(CreateMappedArguments), //
- B(StaContextSlot), R(0), U8(first_context_slot + 1), //
- B(Ldar), R(new_target), //
- B(StaContextSlot), R(0), U8(first_context_slot + 2), //
- B(Mov), R(context), R(3), //
- B(LdaConstant), U8(0), //
- B(Star), R(4), //
- B(CallRuntimeForPair), U16(Runtime::kLoadLookupSlot), //
- R(3), U8(2), R(1), //
- B(LdaConstant), U8(1), //
- B(Star), R(3), //
- B(Mov), R(1), R(4), //
- B(Mov), R(3), R(5), //
- B(Mov), R(closure), R(6), //
- B(LdaZero), //
- B(Star), R(7), //
- B(LdaSmi8), U8(10), //
- B(Star), R(8), //
- B(CallRuntime), U16(Runtime::kResolvePossiblyDirectEval), R(4), //
- U8(5), //
- B(Star), R(1), //
- B(Call), R(1), R(2), U8(1), U8(0), //
- B(Return), //
+ B(CallRuntime), U16(Runtime::kNewFunctionContext), R(closure), //
+ /* */ U8(1), //
+ B(PushContext), R(0), //
+ B(Ldar), THIS(1), //
+ B(StaContextSlot), R(context), U8(first_context_slot), //
+ B(CreateMappedArguments), //
+ B(StaContextSlot), R(context), U8(first_context_slot + 1), //
+ B(Ldar), R(new_target), //
+ B(StaContextSlot), R(context), U8(first_context_slot + 2), //
+ B(StackCheck), //
+ B(LdaConstant), U8(0), //
+ B(Star), R(3), //
+ B(CallRuntimeForPair), U16(Runtime::kLoadLookupSlotForCall), //
+ /* */ R(3), U8(1), R(1), //
+ B(LdaConstant), U8(1), //
+ B(Star), R(3), //
+ B(Mov), R(1), R(4), //
+ B(Mov), R(3), R(5), //
+ B(Mov), R(closure), R(6), //
+ B(LdaZero), //
+ B(Star), R(7), //
+ B(LdaSmi8), U8(10), //
+ B(Star), R(8), //
+ B(CallRuntime), U16(Runtime::kResolvePossiblyDirectEval), R(4), //
+ /* */ U8(5), //
+ B(Star), R(1), //
+ B(Call), R(1), R(2), U8(2), U8(0), //
+ B(Return), //
},
2,
{"eval", "1;"}},
};
+ // clang-format on
for (size_t i = 0; i < arraysize(snippets); i++) {
Handle<BytecodeArray> bytecode_array =
@@ -6290,125 +7489,127 @@
BytecodeGeneratorHelper helper;
int closure = Register::function_closure().index();
+ int context = Register::current_context().index();
int first_context_slot = Context::MIN_CONTEXT_SLOTS;
- int context = Register::function_context().index();
int new_target = Register::new_target().index();
+ // clang-format off
ExpectedSnippet<const char*> snippets[] = {
{"eval('var x = 10;'); return x;",
9 * kPointerSize,
1,
- 69,
+ 67,
{
- B(CallRuntime), U16(Runtime::kNewFunctionContext), R(closure), //
- U8(1), //
- B(PushContext), R(0), //
- B(Ldar), THIS(1), //
- B(StaContextSlot), R(0), U8(first_context_slot), //
- B(CreateMappedArguments), //
- B(StaContextSlot), R(0), U8(first_context_slot + 1), //
- B(Ldar), R(new_target), //
- B(StaContextSlot), R(0), U8(first_context_slot + 2), //
- B(Mov), R(context), R(3), //
- B(LdaConstant), U8(0), //
- B(Star), R(4), //
- B(CallRuntimeForPair), U16(Runtime::kLoadLookupSlot), //
- R(3), U8(2), R(1), //
- B(LdaConstant), U8(1), //
- B(Star), R(3), //
- B(Mov), R(1), R(4), //
- B(Mov), R(3), R(5), //
- B(Mov), R(closure), R(6), //
- B(LdaZero), //
- B(Star), R(7), //
- B(LdaSmi8), U8(10), //
- B(Star), R(8), //
- B(CallRuntime), U16(Runtime::kResolvePossiblyDirectEval), R(4), //
- U8(5), //
- B(Star), R(1), //
- B(Call), R(1), R(2), U8(1), U8(0), //
- B(LdaLookupSlot), U8(2), //
- B(Return), //
+ B(CallRuntime), U16(Runtime::kNewFunctionContext), R(closure), //
+ /* */ U8(1), //
+ B(PushContext), R(0), //
+ B(Ldar), THIS(1), //
+ B(StaContextSlot), R(context), U8(first_context_slot), //
+ B(CreateMappedArguments), //
+ B(StaContextSlot), R(context), U8(first_context_slot + 1), //
+ B(Ldar), R(new_target), //
+ B(StaContextSlot), R(context), U8(first_context_slot + 2), //
+ B(StackCheck), //
+ B(LdaConstant), U8(0), //
+ B(Star), R(3), //
+ B(CallRuntimeForPair), U16(Runtime::kLoadLookupSlotForCall), //
+ R(3), U8(1), R(1), //
+ B(LdaConstant), U8(1), //
+ B(Star), R(3), //
+ B(Mov), R(1), R(4), //
+ B(Mov), R(3), R(5), //
+ B(Mov), R(closure), R(6), //
+ B(LdaZero), //
+ B(Star), R(7), //
+ B(LdaSmi8), U8(10), //
+ B(Star), R(8), //
+ B(CallRuntime), U16(Runtime::kResolvePossiblyDirectEval), R(4), //
+ U8(5), //
+ B(Star), R(1), //
+ B(Call), R(1), R(2), U8(2), U8(0), //
+ B(LdaLookupSlot), U8(2), //
+ B(Return), //
},
3,
{"eval", "var x = 10;", "x"}},
{"eval('var x = 10;'); return typeof x;",
- 9 * kPointerSize,
- 1,
- 70,
- {
- B(CallRuntime), U16(Runtime::kNewFunctionContext), R(closure), //
- U8(1), //
- B(PushContext), R(0), //
- B(Ldar), THIS(1), //
- B(StaContextSlot), R(0), U8(first_context_slot), //
- B(CreateMappedArguments), //
- B(StaContextSlot), R(0), U8(first_context_slot + 1), //
- B(Ldar), R(new_target), //
- B(StaContextSlot), R(0), U8(first_context_slot + 2), //
- B(Mov), R(context), R(3), //
- B(LdaConstant), U8(0), //
- B(Star), R(4), //
- B(CallRuntimeForPair), U16(Runtime::kLoadLookupSlot), //
- R(3), U8(2), R(1), //
- B(LdaConstant), U8(1), //
- B(Star), R(3), //
- B(Mov), R(1), R(4), //
- B(Mov), R(3), R(5), //
- B(Mov), R(closure), R(6), //
- B(LdaZero), //
- B(Star), R(7), //
- B(LdaSmi8), U8(10), //
- B(Star), R(8), //
- B(CallRuntime), U16(Runtime::kResolvePossiblyDirectEval), R(4), //
- U8(5), //
- B(Star), R(1), //
- B(Call), R(1), R(2), U8(1), U8(0), //
- B(LdaLookupSlotInsideTypeof), U8(2), //
- B(TypeOf), //
- B(Return), //
+ 9 * kPointerSize,
+ 1,
+ 68,
+ {
+ B(CallRuntime), U16(Runtime::kNewFunctionContext), R(closure), //
+ /* */ U8(1), //
+ B(PushContext), R(0), //
+ B(Ldar), THIS(1), //
+ B(StaContextSlot), R(context), U8(first_context_slot), //
+ B(CreateMappedArguments), //
+ B(StaContextSlot), R(context), U8(first_context_slot + 1), //
+ B(Ldar), R(new_target), //
+ B(StaContextSlot), R(context), U8(first_context_slot + 2), //
+ B(StackCheck), //
+ B(LdaConstant), U8(0), //
+ B(Star), R(3), //
+ B(CallRuntimeForPair), U16(Runtime::kLoadLookupSlotForCall), //
+ /* */ R(3), U8(1), R(1), //
+ B(LdaConstant), U8(1), //
+ B(Star), R(3), //
+ B(Mov), R(1), R(4), //
+ B(Mov), R(3), R(5), //
+ B(Mov), R(closure), R(6), //
+ B(LdaZero), //
+ B(Star), R(7), //
+ B(LdaSmi8), U8(10), //
+ B(Star), R(8), //
+ B(CallRuntime), U16(Runtime::kResolvePossiblyDirectEval), R(4), //
+ /* */ U8(5), //
+ B(Star), R(1), //
+ B(Call), R(1), R(2), U8(2), U8(0), //
+ B(LdaLookupSlotInsideTypeof), U8(2), //
+ B(TypeOf), //
+ B(Return), //
},
3,
{"eval", "var x = 10;", "x"}},
{"x = 20; return eval('');",
9 * kPointerSize,
1,
- 71,
+ 69,
{
- B(CallRuntime), U16(Runtime::kNewFunctionContext), R(closure), //
- U8(1), //
- B(PushContext), R(0), //
- B(Ldar), THIS(1), //
- B(StaContextSlot), R(0), U8(first_context_slot), //
- B(CreateMappedArguments), //
- B(StaContextSlot), R(0), U8(first_context_slot + 1), //
- B(Ldar), R(new_target), //
- B(StaContextSlot), R(0), U8(first_context_slot + 2), //
- B(LdaSmi8), U8(20), //
- B(StaLookupSlotSloppy), U8(0), //
- B(Mov), R(context), R(3), //
- B(LdaConstant), U8(1), //
- B(Star), R(4), //
- B(CallRuntimeForPair), U16(Runtime::kLoadLookupSlot), //
- R(3), U8(2), R(1), //
- B(LdaConstant), U8(2), //
- B(Star), R(3), //
- B(Mov), R(1), R(4), //
- B(Mov), R(3), R(5), //
- B(Mov), R(closure), R(6), //
- B(LdaZero), //
- B(Star), R(7), //
- B(LdaSmi8), U8(10), //
- B(Star), R(8), //
- B(CallRuntime), U16(Runtime::kResolvePossiblyDirectEval), R(4), //
- U8(5), //
- B(Star), R(1), //
- B(Call), R(1), R(2), U8(1), U8(0), //
- B(Return), //
+ B(CallRuntime), U16(Runtime::kNewFunctionContext), R(closure), //
+ U8(1), //
+ B(PushContext), R(0), //
+ B(Ldar), THIS(1), //
+ B(StaContextSlot), R(context), U8(first_context_slot), //
+ B(CreateMappedArguments), //
+ B(StaContextSlot), R(context), U8(first_context_slot + 1), //
+ B(Ldar), R(new_target), //
+ B(StaContextSlot), R(context), U8(first_context_slot + 2), //
+ B(StackCheck), //
+ B(LdaSmi8), U8(20), //
+ B(StaLookupSlotSloppy), U8(0), //
+ B(LdaConstant), U8(1), //
+ B(Star), R(3), //
+ B(CallRuntimeForPair), U16(Runtime::kLoadLookupSlotForCall), //
+ /* */ R(3), U8(1), R(1), //
+ B(LdaConstant), U8(2), //
+ B(Star), R(3), //
+ B(Mov), R(1), R(4), //
+ B(Mov), R(3), R(5), //
+ B(Mov), R(closure), R(6), //
+ B(LdaZero), //
+ B(Star), R(7), //
+ B(LdaSmi8), U8(10), //
+ B(Star), R(8), //
+ B(CallRuntime), U16(Runtime::kResolvePossiblyDirectEval), R(4), //
+ /* */ U8(5), //
+ B(Star), R(1), //
+ B(Call), R(1), R(2), U8(2), U8(0), //
+ B(Return), //
},
3,
{"x", "eval", ""}},
};
+ // clang-format on
for (size_t i = 0; i < arraysize(snippets); i++) {
Handle<BytecodeArray> bytecode_array =
@@ -6432,31 +7633,32 @@
i::NewTypeFeedbackVector(helper.isolate(), &feedback_spec);
int closure = Register::function_closure().index();
- int context = Register::function_context().index();
+ int context = Register::current_context().index();
int new_target = Register::new_target().index();
+ // clang-format off
ExpectedSnippet<InstanceType> snippets[] = {
{"g = function(){}; eval(''); return g();",
9 * kPointerSize,
1,
- 90,
+ 85,
{
B(CallRuntime), U16(Runtime::kNewFunctionContext), R(closure), //
- U8(1), //
+ /* */ U8(1), //
B(PushContext), R(0), //
B(Ldar), THIS(1), //
- B(StaContextSlot), R(0), U8(4), //
+ B(StaContextSlot), R(context), U8(4), //
B(CreateMappedArguments), //
- B(StaContextSlot), R(0), U8(5), //
+ B(StaContextSlot), R(context), U8(5), //
B(Ldar), R(new_target), //
- B(StaContextSlot), R(0), U8(6), //
+ B(StaContextSlot), R(context), U8(6), //
+ B(StackCheck), //
B(CreateClosure), U8(0), U8(0), //
B(StaLookupSlotSloppy), U8(1), //
- B(Mov), R(context), R(3), //
B(LdaConstant), U8(2), //
- B(Star), R(4), //
- B(CallRuntimeForPair), U16(Runtime::kLoadLookupSlot), //
- R(3), U8(2), R(1), //
+ B(Star), R(3), //
+ B(CallRuntimeForPair), U16(Runtime::kLoadLookupSlotForCall), //
+ R(3), U8(1), R(1), //
B(LdaConstant), U8(3), //
B(Star), R(3), //
B(Mov), R(1), R(4), //
@@ -6469,13 +7671,12 @@
B(CallRuntime), U16(Runtime::kResolvePossiblyDirectEval), R(4), //
U8(5), //
B(Star), R(1), //
- B(Call), R(1), R(2), U8(1), U8(0), //
- B(Mov), R(context), R(3), //
+ B(Call), R(1), R(2), U8(2), U8(0), //
B(LdaConstant), U8(1), //
- B(Star), R(4), //
- B(CallRuntimeForPair), U16(Runtime::kLoadLookupSlot), //
- R(3), U8(2), R(1), //
- B(Call), R(1), R(2), U8(0), U8(vector->GetIndex(slot2)), //
+ B(Star), R(3), //
+ B(CallRuntimeForPair), U16(Runtime::kLoadLookupSlotForCall), //
+ R(3), U8(1), R(1), //
+ B(Call), R(1), R(2), U8(1), U8(vector->GetIndex(slot2)), //
B(Return), //
},
4,
@@ -6484,6 +7685,7 @@
InstanceType::ONE_BYTE_INTERNALIZED_STRING_TYPE,
InstanceType::ONE_BYTE_INTERNALIZED_STRING_TYPE}},
};
+ // clang-format on
for (size_t i = 0; i < arraysize(snippets); i++) {
Handle<BytecodeArray> bytecode_array =
@@ -6493,6 +7695,8 @@
}
+// TODO(mythria): tests for variable/function declaration in lookup slots.
+
TEST(LookupSlotInEval) {
InitializedHandleScope handle_scope;
BytecodeGeneratorHelper helper;
@@ -6505,12 +7709,14 @@
"}"
"f1();";
+ // clang-format off
ExpectedSnippet<const char*> snippets[] = {
{"return x;",
0 * kPointerSize,
1,
- 3,
+ 4,
{
+ B(StackCheck), //
B(LdaLookupSlot), U8(0), //
B(Return) //
},
@@ -6519,8 +7725,9 @@
{"x = 10;",
0 * kPointerSize,
1,
- 6,
+ 7,
{
+ B(StackCheck), //
B(LdaSmi8), U8(10), //
B(StaLookupSlotSloppy), U8(0), //
B(LdaUndefined), //
@@ -6531,8 +7738,9 @@
{"'use strict'; x = 10;",
0 * kPointerSize,
1,
- 6,
+ 7,
{
+ B(StackCheck), //
B(LdaSmi8), U8(10), //
B(StaLookupSlotStrict), U8(0), //
B(LdaUndefined), //
@@ -6543,8 +7751,9 @@
{"return typeof x;",
0 * kPointerSize,
1,
- 4,
+ 5,
{
+ B(StackCheck), //
B(LdaLookupSlotInsideTypeof), U8(0), //
B(TypeOf), //
B(Return), //
@@ -6552,15 +7761,14 @@
1,
{"x"}},
};
+ // clang-format on
for (size_t i = 0; i < arraysize(snippets); i++) {
std::string script = std::string(function_prologue) +
std::string(snippets[i].code_snippet) +
std::string(function_epilogue);
- // TODO(mythria): use * as filter when function declarations are supported
- // inside eval.
Handle<BytecodeArray> bytecode_array =
- helper.MakeBytecode(script.c_str(), "t", "f");
+ helper.MakeBytecode(script.c_str(), "*", "f");
CheckBytecodeArrayEqual(snippets[i], bytecode_array);
}
}
@@ -6581,13 +7789,15 @@
"f1();";
int const_count[] = {0, 0, 0, 0};
+ // clang-format off
ExpectedSnippet<InstanceType, 257> snippets[] = {
{REPEAT_256(SPACE, "var y = 2.3;")
"return x;",
1 * kPointerSize,
1,
- 1028,
+ 1029,
{
+ B(StackCheck), //
REPEAT_256(SPACE, //
B(LdaConstant), U8(const_count[0]++), //
B(Star), R(0), ) //
@@ -6601,8 +7811,9 @@
"return typeof x;",
1 * kPointerSize,
1,
- 1029,
+ 1030,
{
+ B(StackCheck), //
REPEAT_256(SPACE, //
B(LdaConstant), U8(const_count[1]++), //
B(Star), R(0), ) //
@@ -6617,8 +7828,9 @@
"x = 10;",
1 * kPointerSize,
1,
- 1031,
+ 1032,
{
+ B(StackCheck), //
REPEAT_256(SPACE, //
B(LdaConstant), U8(const_count[2]++), //
B(Star), R(0), ) //
@@ -6635,9 +7847,10 @@
"x = 10;",
1 * kPointerSize,
1,
- 1031,
+ 1032,
{
- REPEAT_256(SPACE,
+ B(StackCheck), //
+ REPEAT_256(SPACE, //
B(LdaConstant), U8(const_count[3]++), //
B(Star), R(0), ) //
B(LdaSmi8), U8(10), //
@@ -6649,15 +7862,14 @@
{REPEAT_256(COMMA, InstanceType::HEAP_NUMBER_TYPE),
InstanceType::ONE_BYTE_INTERNALIZED_STRING_TYPE}},
};
+ // clang-format on
for (size_t i = 0; i < arraysize(snippets); i++) {
std::string script = std::string(function_prologue) +
std::string(snippets[i].code_snippet) +
std::string(function_epilogue);
- // TODO(mythria): use * as filter when function declarations are supported
- // inside eval.
Handle<BytecodeArray> bytecode_array =
- helper.MakeBytecode(script.c_str(), "t", "f");
+ helper.MakeBytecode(script.c_str(), "*", "f");
CheckBytecodeArrayEqual(snippets[i], bytecode_array);
}
}
@@ -6677,51 +7889,1215 @@
"}"
"f1();";
+ // clang-format off
ExpectedSnippet<const char*> snippets[] = {
{"delete x;",
- 0 * kPointerSize,
+ 1 * kPointerSize,
1,
- 5,
+ 12,
{
- B(LdaConstant), U8(0), //
- B(DeleteLookupSlot), //
- B(LdaUndefined), //
- B(Return) //
+ B(StackCheck), //
+ B(LdaConstant), U8(0), //
+ B(Star), R(0), //
+ B(CallRuntime), U16(Runtime::kDeleteLookupSlot), R(0), U8(1), //
+ B(LdaUndefined), //
+ B(Return) //
},
1,
{"x"}},
{"return delete y;",
0 * kPointerSize,
1,
- 2,
+ 3,
{
+ B(StackCheck), //
B(LdaFalse), //
B(Return) //
},
0},
{"return delete z;",
- 0 * kPointerSize,
+ 1 * kPointerSize,
1,
- 4,
+ 11,
{
- B(LdaConstant), U8(0), //
- B(DeleteLookupSlot), //
- B(Return) //
+ B(StackCheck), //
+ B(LdaConstant), U8(0), //
+ B(Star), R(0), //
+ B(CallRuntime), U16(Runtime::kDeleteLookupSlot), R(0), U8(1), //
+ B(Return) //
},
1,
{"z"}},
};
+ // clang-format on
for (size_t i = 0; i < arraysize(snippets); i++) {
std::string script = std::string(function_prologue) +
std::string(snippets[i].code_snippet) +
std::string(function_epilogue);
Handle<BytecodeArray> bytecode_array =
- helper.MakeBytecode(script.c_str(), "t", "f");
+ helper.MakeBytecode(script.c_str(), "*", "f");
CheckBytecodeArrayEqual(snippets[i], bytecode_array);
}
}
+TEST(WideRegisters) {
+ // Prepare prologue that creates frame for lots of registers.
+ std::ostringstream os;
+ for (size_t i = 0; i < 157; ++i) {
+ os << "var x" << i << ";\n";
+ }
+ std::string prologue(os.str());
+
+ // clang-format off
+ ExpectedSnippet<int> snippets[] = {
+ {"x0 = x127;\n"
+ "return x0;\n",
+ 161 * kPointerSize,
+ 1,
+ 11,
+ {
+ B(StackCheck), //
+ B(MovWide), R16(131), R16(125), //
+ B(Ldar), R(125), //
+ B(Star), R(0), //
+ B(Return), //
+ }},
+ {"x127 = x126;\n"
+ "return x127;\n",
+ 161 * kPointerSize,
+ 1,
+ 23,
+ {
+ B(StackCheck), //
+ B(MovWide), R16(130), R16(125), //
+ B(Ldar), R(125), //
+ B(Star), R(125), //
+ B(MovWide), R16(125), R16(131), //
+ B(MovWide), R16(131), R16(125), //
+ B(Ldar), R(125), //
+ B(Return), //
+ }},
+ {"if (x2 > 3) { return x129; }\n"
+ "return x128;\n",
+ 162 * kPointerSize,
+ 1,
+ 37,
+ {
+ B(StackCheck), //
+ B(Ldar), R(2), //
+ B(Star), R(125), //
+ B(MovWide), R16(125), R16(161), //
+ B(LdaSmi8), U8(3), //
+ B(MovWide), R16(161), R16(125), //
+ B(TestGreaterThan), R(125), //
+ B(JumpIfFalse), U8(10), //
+ B(MovWide), R16(133), R16(125), //
+ B(Ldar), R(125), //
+ B(Return), //
+ B(MovWide), R16(132), R16(125), //
+ B(Ldar), R(125), //
+ B(Return), //
+ }},
+ {"var x0 = 0;\n"
+ "if (x129 == 3) { var x129 = x0; }\n"
+ "if (x2 > 3) { return x0; }\n"
+ "return x129;\n",
+ 162 * kPointerSize,
+ 1,
+ 69,
+ {
+ B(StackCheck), //
+ B(LdaZero), //
+ B(Star), R(0), //
+ B(MovWide), R16(133), R16(125), //
+ B(Ldar), R(125), //
+ B(Star), R(125), //
+ B(MovWide), R16(125), R16(161), //
+ B(LdaSmi8), U8(3), //
+ B(MovWide), R16(161), R16(125), //
+ B(TestEqual), R(125), //
+ B(JumpIfFalse), U8(11), //
+ B(Ldar), R(0), //
+ B(Star), R(125), //
+ B(MovWide), R16(125), R16(133), //
+ B(Ldar), R(2), //
+ B(Star), R(125), //
+ B(MovWide), R16(125), R16(161), //
+ B(LdaSmi8), U8(3), //
+ B(MovWide), R16(161), R16(125), //
+ B(TestGreaterThan), R(125), //
+ B(JumpIfFalse), U8(5), //
+ B(Ldar), R(0), //
+ B(Return), //
+ B(MovWide), R16(133), R16(125), //
+ B(Ldar), R(125), //
+ B(Return), //
+ }},
+ {"var x0 = 0;\n"
+ "var x1 = 0;\n"
+ "for (x128 = 0; x128 < 64; x128++) {"
+ " x1 += x128;"
+ "}"
+ "return x128;\n",
+ 162 * kPointerSize,
+ 1,
+ 99,
+ {
+ B(StackCheck), //
+ B(LdaZero), //
+ B(Star), R(0), //
+ B(LdaZero), //
+ B(Star), R(1), //
+ B(LdaZero), //
+ B(Star), R(125), //
+ B(MovWide), R16(125), R16(132), //
+ B(MovWide), R16(132), R16(125), //
+ B(Ldar), R(125), //
+ B(Star), R(125), //
+ B(MovWide), R16(125), R16(161), //
+ B(LdaSmi8), U8(64), //
+ B(MovWide), R16(161), R16(125), //
+ B(TestLessThan), R(125), //
+ B(JumpIfFalse), U8(53), //
+ B(StackCheck), //
+ B(Ldar), R(1), //
+ B(Star), R(125), //
+ B(MovWide), R16(125), R16(161), //
+ B(MovWide), R16(132), R16(125), //
+ B(Ldar), R(125), //
+ B(MovWide), R16(161), R16(125), //
+ B(Add), R(125), //
+ B(Star), R(1), //
+ B(MovWide), R16(132), R16(125), //
+ B(Ldar), R(125), //
+ B(ToNumber), //
+ B(Star), R(125), //
+ B(MovWide), R16(125), R16(161), //
+ B(Inc), //
+ B(Star), R(125), //
+ B(MovWide), R16(125), R16(132), //
+ B(Jump), U8(-74), //
+ B(MovWide), R16(132), R16(125), //
+ B(Ldar), R(125), //
+ B(Return), //
+ }},
+ {"var x0 = 1234;\n"
+ "var x1 = 0;\n"
+ "for (x128 in x0) {"
+ " x1 += x128;"
+ "}"
+ "return x1;\n",
+ 167 * kPointerSize,
+ 1,
+ 111,
+ {
+ B(StackCheck), //
+ B(LdaConstant), U8(0), //
+ B(Star), R(0), //
+ B(LdaZero), //
+ B(Star), R(1), //
+ B(Ldar), R(0), //
+ B(JumpIfUndefined), U8(98), //
+ B(JumpIfNull), U8(96), //
+ B(ToObject), //
+ B(JumpIfNull), U8(93), //
+ B(Star), R(125), //
+ B(MovWide), R16(125), R16(161), //
+ B(ForInPrepareWide), R16(162), //
+ B(LdaZero), //
+ B(Star), R(125), //
+ B(MovWide), R16(125), R16(165), //
+ B(MovWide), R16(165), R16(125), //
+ B(MovWide), R16(164), R16(126), //
+ B(ForInDone), R(125), R(126), //
+ B(JumpIfTrue), U8(60), //
+ B(ForInNextWide), R16(161), R16(165), R16(162), //
+ B(JumpIfUndefined), U8(35), //
+ B(Star), R(125), //
+ B(MovWide), R16(125), R16(132), //
+ B(StackCheck), //
+ B(Ldar), R(1), //
+ B(Star), R(125), //
+ B(MovWide), R16(125), R16(166), //
+ B(MovWide), R16(132), R16(125), //
+ B(Ldar), R(125), //
+ B(MovWide), R16(166), R16(125), //
+ B(Add), R(125), //
+ B(Star), R(1), //
+ B(MovWide), R16(165), R16(125), //
+ B(ForInStep), R(125), //
+ B(Star), R(125), //
+ B(MovWide), R16(125), R16(165), //
+ B(Jump), U8(-71), //
+ B(Ldar), R(1), //
+ B(Return), //
+ },
+ 1,
+ {1234}},
+ {"x0 = %Add(x64, x63);\n"
+ "x1 = %Add(x27, x143);\n"
+ "%TheHole();\n"
+ "return x1;\n",
+ 163 * kPointerSize,
+ 1,
+ 66,
+ {
+ B(StackCheck), //
+ B(Ldar), R(64), //
+ B(Star), R(125), //
+ B(MovWide), R16(125), R16(161), //
+ B(Ldar), R(63), //
+ B(Star), R(125), //
+ B(MovWide), R16(125), R16(162), //
+ B(CallRuntimeWide), U16(Runtime::kAdd), R16(161), U8(2), //
+ B(Star), R(0), //
+ B(Ldar), R(27), //
+ B(Star), R(125), //
+ B(MovWide), R16(125), R16(161), //
+ B(MovWide), R16(147), R16(125), //
+ B(Ldar), R(125), //
+ B(Star), R(125), //
+ B(MovWide), R16(125), R16(162), //
+ B(CallRuntimeWide), U16(Runtime::kAdd), R16(161), U8(2), //
+ B(Star), R(1), //
+ B(CallRuntime), U16(Runtime::kTheHole), R(0), U8(0), //
+ B(Ldar), R(1), //
+ B(Return), //
+ }}
+ };
+ // clang-format on
+
+ InitializedHandleScope handle_scope;
+ BytecodeGeneratorHelper helper;
+
+ for (size_t i = 0; i < arraysize(snippets); ++i) {
+ std::string body = prologue + snippets[i].code_snippet;
+ Handle<BytecodeArray> bytecode_array =
+ helper.MakeBytecodeForFunctionBody(body.c_str());
+ CheckBytecodeArrayEqual(snippets[i], bytecode_array);
+ }
+}
+
+TEST(ConstVariable) {
+ InitializedHandleScope handle_scope;
+ BytecodeGeneratorHelper helper;
+ // clang-format off
+ ExpectedSnippet<const char*> snippets[] = {
+ {"const x = 10;",
+ 1 * kPointerSize,
+ 1,
+ 10,
+ {
+ B(LdaTheHole), //
+ B(Star), R(0), //
+ B(StackCheck), //
+ B(LdaSmi8), U8(10), //
+ B(Star), R(0), //
+ B(LdaUndefined), //
+ B(Return) //
+ },
+ 0},
+ {"const x = 10; return x;",
+ 2 * kPointerSize,
+ 1,
+ 20,
+ {
+ B(LdaTheHole), //
+ B(Star), R(0), //
+ B(StackCheck), //
+ B(LdaSmi8), U8(10), //
+ B(Star), R(0), //
+ B(JumpIfNotHole), U8(11), //
+ B(LdaConstant), U8(0), //
+ B(Star), R(1), //
+ B(CallRuntime), U16(Runtime::kThrowReferenceError), R(1), U8(1), //
+ B(Return) //
+ },
+ 1,
+ {"x"}},
+ {"const x = ( x = 20);",
+ 3 * kPointerSize,
+ 1,
+ 32,
+ {
+ B(LdaTheHole), //
+ B(Star), R(0), //
+ B(StackCheck), //
+ B(LdaSmi8), U8(20), //
+ B(Star), R(1), //
+ B(Ldar), R(0), //
+ B(JumpIfNotHole), U8(11), //
+ B(LdaConstant), U8(0), //
+ B(Star), R(2), //
+ B(CallRuntime), U16(Runtime::kThrowReferenceError), R(2), U8(1), //
+ B(CallRuntime), U16(Runtime::kThrowConstAssignError), R(0), //
+ /* */ U8(0), //
+ B(Ldar), R(1), //
+ B(Star), R(0), //
+ B(LdaUndefined), //
+ B(Return) //
+ },
+ 1,
+ {"x"}},
+ {"const x = 10; x = 20;",
+ 3 * kPointerSize,
+ 1,
+ 36,
+ {
+ B(LdaTheHole), //
+ B(Star), R(0), //
+ B(StackCheck), //
+ B(LdaSmi8), U8(10), //
+ B(Star), R(0), //
+ B(LdaSmi8), U8(20), //
+ B(Star), R(1), //
+ B(Ldar), R(0), //
+ B(JumpIfNotHole), U8(11), //
+ B(LdaConstant), U8(0), //
+ B(Star), R(2), //
+ B(CallRuntime), U16(Runtime::kThrowReferenceError), R(2), U8(1), //
+ B(CallRuntime), U16(Runtime::kThrowConstAssignError), R(0), //
+ /* */ U8(0), //
+ B(Ldar), R(1), //
+ B(Star), R(0), //
+ B(LdaUndefined), //
+ B(Return) //
+ },
+ 1,
+ {"x"}},
+ };
+ // clang-format on
+
+ for (size_t i = 0; i < arraysize(snippets); i++) {
+ Handle<BytecodeArray> bytecode_array =
+ helper.MakeBytecodeForFunctionBody(snippets[i].code_snippet);
+ CheckBytecodeArrayEqual(snippets[i], bytecode_array);
+ }
+}
+
+TEST(LetVariable) {
+ InitializedHandleScope handle_scope;
+ BytecodeGeneratorHelper helper;
+
+ // clang-format off
+ ExpectedSnippet<const char*> snippets[] = {
+ {"let x = 10;",
+ 1 * kPointerSize,
+ 1,
+ 10,
+ {
+ B(LdaTheHole), //
+ B(Star), R(0), //
+ B(StackCheck), //
+ B(LdaSmi8), U8(10), //
+ B(Star), R(0), //
+ B(LdaUndefined), //
+ B(Return) //
+ },
+ 0},
+ {"let x = 10; return x;",
+ 2 * kPointerSize,
+ 1,
+ 20,
+ {
+ B(LdaTheHole), //
+ B(Star), R(0), //
+ B(StackCheck), //
+ B(LdaSmi8), U8(10), //
+ B(Star), R(0), //
+ B(JumpIfNotHole), U8(11), //
+ B(LdaConstant), U8(0), //
+ B(Star), R(1), //
+ B(CallRuntime), U16(Runtime::kThrowReferenceError), R(1), U8(1), //
+ B(Return) //
+ },
+ 1,
+ {"x"}},
+ {"let x = (x = 20);",
+ 3 * kPointerSize,
+ 1,
+ 27,
+ {
+ B(LdaTheHole), //
+ B(Star), R(0), //
+ B(StackCheck), //
+ B(LdaSmi8), U8(20), //
+ B(Star), R(1), //
+ B(Ldar), R(0), //
+ B(JumpIfNotHole), U8(11), //
+ B(LdaConstant), U8(0), //
+ B(Star), R(2), //
+ B(CallRuntime), U16(Runtime::kThrowReferenceError), R(2), U8(1), //
+ B(Ldar), R(1), //
+ B(Star), R(0), //
+ B(LdaUndefined), //
+ B(Return) //
+ },
+ 1,
+ {"x"}},
+ {"let x = 10; x = 20;",
+ 3 * kPointerSize,
+ 1,
+ 31,
+ {
+ B(LdaTheHole), //
+ B(Star), R(0), //
+ B(StackCheck), //
+ B(LdaSmi8), U8(10), //
+ B(Star), R(0), //
+ B(LdaSmi8), U8(20), //
+ B(Star), R(1), //
+ B(Ldar), R(0), //
+ B(JumpIfNotHole), U8(11), //
+ B(LdaConstant), U8(0), //
+ B(Star), R(2), //
+ B(CallRuntime), U16(Runtime::kThrowReferenceError), R(2), U8(1), //
+ B(Ldar), R(1), //
+ B(Star), R(0), //
+ B(LdaUndefined), //
+ B(Return) //
+ },
+ 1,
+ {"x"}},
+ };
+ // clang-format on
+
+ for (size_t i = 0; i < arraysize(snippets); i++) {
+ Handle<BytecodeArray> bytecode_array =
+ helper.MakeBytecodeForFunctionBody(snippets[i].code_snippet);
+ CheckBytecodeArrayEqual(snippets[i], bytecode_array);
+ }
+}
+
+TEST(LegacyConstVariable) {
+ bool old_legacy_const_flag = FLAG_legacy_const;
+ FLAG_legacy_const = true;
+
+ InitializedHandleScope handle_scope;
+ BytecodeGeneratorHelper helper;
+
+ // clang-format off
+ ExpectedSnippet<const char*> snippets[] = {
+ {"const x = 10;",
+ 2 * kPointerSize,
+ 1,
+ 19,
+ {
+ B(LdaTheHole), //
+ B(Star), R(0), //
+ B(StackCheck), //
+ B(LdaSmi8), U8(10), //
+ B(Star), R(1), //
+ B(Ldar), R(0), //
+ B(JumpIfNotHole), U8(5), //
+ B(Mov), R(1), R(0), //
+ B(Ldar), R(1), //
+ B(LdaUndefined), //
+ B(Return) //
+ },
+ 0},
+ {"const x = 10; return x;",
+ 2 * kPointerSize,
+ 1,
+ 23,
+ {
+ B(LdaTheHole), //
+ B(Star), R(0), //
+ B(StackCheck), //
+ B(LdaSmi8), U8(10), //
+ B(Star), R(1), //
+ B(Ldar), R(0), //
+ B(JumpIfNotHole), U8(5), //
+ B(Mov), R(1), R(0), //
+ B(Ldar), R(1), //
+ B(Ldar), R(0), //
+ B(JumpIfNotHole), U8(3), //
+ B(LdaUndefined), //
+ B(Return) //
+ },
+ 0},
+ {"const x = ( x = 20);",
+ 2 * kPointerSize,
+ 1,
+ 23,
+ {
+ B(LdaTheHole), //
+ B(Star), R(0), //
+ B(StackCheck), //
+ B(LdaSmi8), U8(20), //
+ B(Star), R(1), //
+ B(Ldar), R(0), //
+ B(Ldar), R(1), //
+ B(Ldar), R(0), //
+ B(JumpIfNotHole), U8(5), //
+ B(Mov), R(1), R(0), //
+ B(Ldar), R(1), //
+ B(LdaUndefined), //
+ B(Return) //
+ },
+ 0},
+ {"const x = 10; x = 20;",
+ 2 * kPointerSize,
+ 1,
+ 27,
+ {
+ B(LdaTheHole), //
+ B(Star), R(0), //
+ B(StackCheck), //
+ B(LdaSmi8), U8(10), //
+ B(Star), R(1), //
+ B(Ldar), R(0), //
+ B(JumpIfNotHole), U8(5), //
+ B(Mov), R(1), R(0), //
+ B(Ldar), R(1), //
+ B(LdaSmi8), U8(20), //
+ B(Star), R(1), //
+ B(Ldar), R(0), //
+ B(Ldar), R(1), //
+ B(LdaUndefined), //
+ B(Return) //
+ },
+ 0},
+ };
+ // clang-format on
+
+ for (size_t i = 0; i < arraysize(snippets); i++) {
+ Handle<BytecodeArray> bytecode_array =
+ helper.MakeBytecodeForFunctionBody(snippets[i].code_snippet);
+ CheckBytecodeArrayEqual(snippets[i], bytecode_array);
+ }
+
+ FLAG_legacy_const = old_legacy_const_flag;
+}
+
+TEST(ConstVariableContextSlot) {
+ InitializedHandleScope handle_scope;
+ BytecodeGeneratorHelper helper;
+
+ int closure = Register::function_closure().index();
+ int context = Register::current_context().index();
+
+ // TODO(mythria): Add tests for initialization of this via super calls.
+ // TODO(mythria): Add tests that walk the context chain.
+ // clang-format off
+ ExpectedSnippet<InstanceType> snippets[] = {
+ {"const x = 10; function f1() {return x;}",
+ 2 * kPointerSize,
+ 1,
+ 24,
+ {
+ B(CallRuntime), U16(Runtime::kNewFunctionContext), R(closure), //
+ U8(1), //
+ B(PushContext), R(1), //
+ B(LdaTheHole), //
+ B(StaContextSlot), R(context), U8(4), //
+ B(CreateClosure), U8(0), U8(0), //
+ B(Star), R(0), //
+ B(StackCheck), //
+ B(LdaSmi8), U8(10), //
+ B(StaContextSlot), R(context), U8(4), //
+ B(LdaUndefined), //
+ B(Return) //
+ },
+ 1,
+ {InstanceType::SHARED_FUNCTION_INFO_TYPE}},
+ {"const x = 10; function f1() {return x;} return x;",
+ 3 * kPointerSize,
+ 1,
+ 37,
+ {
+ B(CallRuntime), U16(Runtime::kNewFunctionContext), R(closure), //
+ U8(1), //
+ B(PushContext), R(1), //
+ B(LdaTheHole), //
+ B(StaContextSlot), R(context), U8(4), //
+ B(CreateClosure), U8(0), U8(0), //
+ B(Star), R(0), //
+ B(StackCheck), //
+ B(LdaSmi8), U8(10), //
+ B(StaContextSlot), R(context), U8(4), //
+ B(LdaContextSlot), R(context), U8(4), //
+ B(JumpIfNotHole), U8(11), //
+ B(LdaConstant), U8(1), //
+ B(Star), R(2), //
+ B(CallRuntime), U16(Runtime::kThrowReferenceError), R(2), U8(1), //
+ B(Return) //
+ },
+ 2,
+ {InstanceType::SHARED_FUNCTION_INFO_TYPE,
+ InstanceType::ONE_BYTE_INTERNALIZED_STRING_TYPE}},
+ {"const x = (x = 20); function f1() {return x;}",
+ 4 * kPointerSize,
+ 1,
+ 50,
+ {
+ B(CallRuntime), U16(Runtime::kNewFunctionContext), R(closure), //
+ /* */ U8(1), //
+ B(PushContext), R(1), //
+ B(LdaTheHole), //
+ B(StaContextSlot), R(context), U8(4), //
+ B(CreateClosure), U8(0), U8(0), //
+ B(Star), R(0), //
+ B(StackCheck), //
+ B(LdaSmi8), U8(20), //
+ B(Star), R(2), //
+ B(LdaContextSlot), R(context), U8(4), //
+ B(JumpIfNotHole), U8(11), //
+ B(LdaConstant), U8(1), //
+ B(Star), R(3), //
+ B(CallRuntime), U16(Runtime::kThrowReferenceError), R(3), U8(1), //
+ B(CallRuntime), U16(Runtime::kThrowConstAssignError), R(0), //
+ U8(0), //
+ B(Ldar), R(2), //
+ B(StaContextSlot), R(context), U8(4), //
+ B(StaContextSlot), R(context), U8(4), //
+ B(LdaUndefined), //
+ B(Return) //
+ },
+ 2,
+ {InstanceType::SHARED_FUNCTION_INFO_TYPE,
+ InstanceType::ONE_BYTE_INTERNALIZED_STRING_TYPE}},
+ {"const x = 10; x = 20; function f1() {return x;}",
+ 4 * kPointerSize,
+ 1,
+ 52,
+ {
+ B(CallRuntime), U16(Runtime::kNewFunctionContext), R(closure), //
+ /* */ U8(1), //
+ B(PushContext), R(1), //
+ B(LdaTheHole), //
+ B(StaContextSlot), R(context), U8(4), //
+ B(CreateClosure), U8(0), U8(0), //
+ B(Star), R(0), //
+ B(StackCheck), //
+ B(LdaSmi8), U8(10), //
+ B(StaContextSlot), R(context), U8(4), //
+ B(LdaSmi8), U8(20), //
+ B(Star), R(2), //
+ B(LdaContextSlot), R(context), U8(4), //
+ B(JumpIfNotHole), U8(11), //
+ B(LdaConstant), U8(1), //
+ B(Star), R(3), //
+ B(CallRuntime), U16(Runtime::kThrowReferenceError), R(3), U8(1), //
+ B(CallRuntime), U16(Runtime::kThrowConstAssignError), R(0), //
+ U8(0), //
+ B(Ldar), R(2), //
+ B(StaContextSlot), R(context), U8(4), //
+ B(LdaUndefined), //
+ B(Return) //
+ },
+ 2,
+ {InstanceType::SHARED_FUNCTION_INFO_TYPE,
+ InstanceType::ONE_BYTE_INTERNALIZED_STRING_TYPE}},
+ };
+ // clang-format on
+
+ for (size_t i = 0; i < arraysize(snippets); i++) {
+ Handle<BytecodeArray> bytecode_array =
+ helper.MakeBytecodeForFunctionBody(snippets[i].code_snippet);
+ CheckBytecodeArrayEqual(snippets[i], bytecode_array);
+ }
+}
+
+TEST(LetVariableContextSlot) {
+ InitializedHandleScope handle_scope;
+ BytecodeGeneratorHelper helper;
+
+ int closure = Register::function_closure().index();
+ int context = Register::current_context().index();
+
+ // clang-format off
+ ExpectedSnippet<InstanceType> snippets[] = {
+ {"let x = 10; function f1() {return x;}",
+ 2 * kPointerSize,
+ 1,
+ 24,
+ {
+ B(CallRuntime), U16(Runtime::kNewFunctionContext), R(closure), //
+ /* */ U8(1), //
+ B(PushContext), R(1), //
+ B(LdaTheHole), //
+ B(StaContextSlot), R(context), U8(4), //
+ B(CreateClosure), U8(0), U8(0), //
+ B(Star), R(0), //
+ B(StackCheck), //
+ B(LdaSmi8), U8(10), //
+ B(StaContextSlot), R(context), U8(4), //
+ B(LdaUndefined), //
+ B(Return) //
+ },
+ 1,
+ {InstanceType::SHARED_FUNCTION_INFO_TYPE}},
+ {"let x = 10; function f1() {return x;} return x;",
+ 3 * kPointerSize,
+ 1,
+ 37,
+ {
+ B(CallRuntime), U16(Runtime::kNewFunctionContext), R(closure), //
+ /* */ U8(1), //
+ B(PushContext), R(1), //
+ B(LdaTheHole), //
+ B(StaContextSlot), R(context), U8(4), //
+ B(CreateClosure), U8(0), U8(0), //
+ B(Star), R(0), //
+ B(StackCheck), //
+ B(LdaSmi8), U8(10), //
+ B(StaContextSlot), R(context), U8(4), //
+ B(LdaContextSlot), R(context), U8(4), //
+ B(JumpIfNotHole), U8(11), //
+ B(LdaConstant), U8(1), //
+ B(Star), R(2), //
+ B(CallRuntime), U16(Runtime::kThrowReferenceError), R(2), U8(1), //
+ B(Return) //
+ },
+ 2,
+ {InstanceType::SHARED_FUNCTION_INFO_TYPE,
+ InstanceType::ONE_BYTE_INTERNALIZED_STRING_TYPE}},
+ {"let x = (x = 20); function f1() {return x;}",
+ 4 * kPointerSize,
+ 1,
+ 45,
+ {
+ B(CallRuntime), U16(Runtime::kNewFunctionContext), R(closure), //
+ /* */ U8(1), //
+ B(PushContext), R(1), //
+ B(LdaTheHole), //
+ B(StaContextSlot), R(context), U8(4), //
+ B(CreateClosure), U8(0), U8(0), //
+ B(Star), R(0), //
+ B(StackCheck), //
+ B(LdaSmi8), U8(20), //
+ B(Star), R(2), //
+ B(LdaContextSlot), R(context), U8(4), //
+ B(JumpIfNotHole), U8(11), //
+ B(LdaConstant), U8(1), //
+ B(Star), R(3), //
+ B(CallRuntime), U16(Runtime::kThrowReferenceError), R(3), U8(1), //
+ B(Ldar), R(2), //
+ B(StaContextSlot), R(context), U8(4), //
+ B(StaContextSlot), R(context), U8(4), //
+ B(LdaUndefined), //
+ B(Return) //
+ },
+ 2,
+ {InstanceType::SHARED_FUNCTION_INFO_TYPE,
+ InstanceType::ONE_BYTE_INTERNALIZED_STRING_TYPE}},
+ {"let x = 10; x = 20; function f1() {return x;}",
+ 4 * kPointerSize,
+ 1,
+ 47,
+ {
+ B(CallRuntime), U16(Runtime::kNewFunctionContext), R(closure), //
+ /* */ U8(1), //
+ B(PushContext), R(1), //
+ B(LdaTheHole), //
+ B(StaContextSlot), R(context), U8(4), //
+ B(CreateClosure), U8(0), U8(0), //
+ B(Star), R(0), //
+ B(StackCheck), //
+ B(LdaSmi8), U8(10), //
+ B(StaContextSlot), R(context), U8(4), //
+ B(LdaSmi8), U8(20), //
+ B(Star), R(2), //
+ B(LdaContextSlot), R(context), U8(4), //
+ B(JumpIfNotHole), U8(11), //
+ B(LdaConstant), U8(1), //
+ B(Star), R(3), //
+ B(CallRuntime), U16(Runtime::kThrowReferenceError), R(3), U8(1), //
+ B(Ldar), R(2), //
+ B(StaContextSlot), R(context), U8(4), //
+ B(LdaUndefined), //
+ B(Return) //
+ },
+ 2,
+ {InstanceType::SHARED_FUNCTION_INFO_TYPE,
+ InstanceType::ONE_BYTE_INTERNALIZED_STRING_TYPE}},
+ };
+ // clang-format on
+
+ for (size_t i = 0; i < arraysize(snippets); i++) {
+ Handle<BytecodeArray> bytecode_array =
+ helper.MakeBytecodeForFunctionBody(snippets[i].code_snippet);
+ CheckBytecodeArrayEqual(snippets[i], bytecode_array);
+ }
+}
+
+TEST(DoExpression) {
+ bool old_flag = FLAG_harmony_do_expressions;
+ FLAG_harmony_do_expressions = true;
+
+ InitializedHandleScope handle_scope;
+ BytecodeGeneratorHelper helper;
+
+ // clang-format off
+ ExpectedSnippet<const char*> snippets[] = {
+ {"var a = do { }; return a;",
+ 2 * kPointerSize,
+ 1,
+ 6,
+ {
+ B(StackCheck), //
+ B(Ldar), R(0), //
+ B(Star), R(1), //
+ B(Return) //
+ },
+ 0},
+ {"var a = do { var x = 100; }; return a;",
+ 3 * kPointerSize,
+ 1,
+ 11,
+ {
+ B(StackCheck), //
+ B(LdaSmi8), U8(100), //
+ B(Star), R(1), //
+ B(LdaUndefined), //
+ B(Star), R(0), //
+ B(Star), R(2), //
+ B(Return) //
+ },
+ 0},
+ {"while(true) { var a = 10; a = do { ++a; break; }; a = 20; }",
+ 2 * kPointerSize,
+ 1,
+ 26,
+ {
+ B(StackCheck), //
+ B(StackCheck), //
+ B(LdaSmi8), U8(10), //
+ B(Star), R(1), //
+ B(ToNumber), //
+ B(Inc), //
+ B(Star), R(1), //
+ B(Star), R(0), //
+ B(Jump), U8(12), //
+ B(Ldar), R(0), //
+ B(Star), R(1), //
+ B(LdaSmi8), U8(20), //
+ B(Star), R(1), //
+ B(Jump), U8(-21), //
+ B(LdaUndefined), //
+ B(Return), //
+ },
+ 0},
+ };
+ // clang-format on
+
+ for (size_t i = 0; i < arraysize(snippets); i++) {
+ Handle<BytecodeArray> bytecode_array =
+ helper.MakeBytecodeForFunctionBody(snippets[i].code_snippet);
+ CheckBytecodeArrayEqual(snippets[i], bytecode_array);
+ }
+ FLAG_harmony_do_expressions = old_flag;
+}
+
+TEST(WithStatement) {
+ InitializedHandleScope handle_scope;
+ BytecodeGeneratorHelper helper;
+
+ int deep_elements_flags =
+ ObjectLiteral::kFastElements | ObjectLiteral::kDisableMementos;
+ int context = Register::current_context().index();
+ int closure = Register::function_closure().index();
+ int new_target = Register::new_target().index();
+
+ // clang-format off
+ ExpectedSnippet<InstanceType> snippets[] = {
+ {"with ({x:42}) { return x; }",
+ 5 * kPointerSize,
+ 1,
+ 47,
+ {
+ B(CallRuntime), U16(Runtime::kNewFunctionContext), R(closure), //
+ /* */ U8(1), //
+ B(PushContext), R(0), //
+ B(Ldar), THIS(1), //
+ B(StaContextSlot), R(context), U8(4), //
+ B(CreateMappedArguments), //
+ B(StaContextSlot), R(context), U8(5), //
+ B(Ldar), R(new_target), //
+ B(StaContextSlot), R(context), U8(6), //
+ B(StackCheck), //
+ B(CreateObjectLiteral), U8(0), U8(0), U8(deep_elements_flags), //
+ B(Star), R(2), //
+ B(ToObject), //
+ B(Star), R(3), //
+ B(Ldar), R(closure), //
+ B(Star), R(4), //
+ B(CallRuntime), U16(Runtime::kPushWithContext), R(3), U8(2), //
+ B(PushContext), R(1), //
+ B(LdaLookupSlot), U8(1), //
+ B(PopContext), R(0), //
+ B(Return), //
+ },
+ 2,
+ {InstanceType::FIXED_ARRAY_TYPE,
+ InstanceType::ONE_BYTE_INTERNALIZED_STRING_TYPE}},
+ };
+ // clang-format on
+
+ for (size_t i = 0; i < arraysize(snippets); i++) {
+ Handle<BytecodeArray> bytecode_array =
+ helper.MakeBytecodeForFunctionBody(snippets[i].code_snippet);
+ CheckBytecodeArrayEqual(snippets[i], bytecode_array);
+ }
+}
+
+TEST(DoDebugger) {
+ InitializedHandleScope handle_scope;
+ BytecodeGeneratorHelper helper;
+
+ // clang-format off
+ ExpectedSnippet<const char*> snippet = {
+ "debugger;",
+ 0,
+ 1,
+ 4,
+ {
+ B(StackCheck), //
+ B(Debugger), //
+ B(LdaUndefined), //
+ B(Return) //
+ },
+ 0
+ };
+ // clang-format on
+
+ Handle<BytecodeArray> bytecode_array =
+ helper.MakeBytecodeForFunctionBody(snippet.code_snippet);
+ CheckBytecodeArrayEqual(snippet, bytecode_array);
+}
+
+// TODO(rmcilroy): Update expectations after switch to
+// Runtime::kDefineDataPropertyInLiteral.
+TEST(ClassDeclarations) {
+ InitializedHandleScope handle_scope;
+ BytecodeGeneratorHelper helper;
+
+ int closure = Register::function_closure().index();
+ int context = Register::current_context().index();
+
+ // clang-format off
+ ExpectedSnippet<InstanceType, 12> snippets[] = {
+ {"class Person {\n"
+ " constructor(name) { this.name = name; }\n"
+ " speak() { console.log(this.name + ' is speaking.'); }\n"
+ "}\n",
+ 9 * kPointerSize,
+ 1,
+ 71,
+ {
+ B(LdaTheHole), //
+ B(Star), R(1), //
+ B(StackCheck), //
+ B(LdaTheHole), //
+ B(Star), R(0), //
+ B(LdaTheHole), //
+ B(Star), R(2), //
+ B(CreateClosure), U8(0), U8(0), //
+ B(Star), R(3), //
+ B(LdaSmi8), U8(15), //
+ B(Star), R(4), //
+ B(LdaConstant), U8(1), //
+ B(Star), R(5), //
+ B(CallRuntime), U16(Runtime::kDefineClass), R(2), U8(4), //
+ B(Star), R(2), //
+ B(LoadIC), R(2), U8(2), U8(1), //
+ B(Star), R(3), //
+ B(Mov), R(3), R(4), //
+ B(LdaConstant), U8(3), //
+ B(Star), R(5), //
+ B(CreateClosure), U8(4), U8(0), //
+ B(Star), R(6), //
+ B(LdaSmi8), U8(2), //
+ B(Star), R(7), //
+ B(LdaZero), //
+ B(Star), R(8), //
+ B(CallRuntime), U16(Runtime::kDefineDataPropertyInLiteral), R(4), U8(5),
+ B(CallRuntime), U16(Runtime::kFinalizeClassDefinition), R(2), U8(2), //
+ B(Star), R(0), //
+ B(Star), R(1), //
+ B(LdaUndefined), //
+ B(Return) //
+ },
+ 5,
+ { InstanceType::SHARED_FUNCTION_INFO_TYPE, kInstanceTypeDontCare,
+ InstanceType::ONE_BYTE_INTERNALIZED_STRING_TYPE,
+ InstanceType::ONE_BYTE_INTERNALIZED_STRING_TYPE,
+ InstanceType::SHARED_FUNCTION_INFO_TYPE}},
+ {"class person {\n"
+ " constructor(name) { this.name = name; }\n"
+ " speak() { console.log(this.name + ' is speaking.'); }\n"
+ "}\n",
+ 9 * kPointerSize,
+ 1,
+ 71,
+ {
+ B(LdaTheHole), //
+ B(Star), R(1), //
+ B(StackCheck), //
+ B(LdaTheHole), //
+ B(Star), R(0), //
+ B(LdaTheHole), //
+ B(Star), R(2), //
+ B(CreateClosure), U8(0), U8(0), //
+ B(Star), R(3), //
+ B(LdaSmi8), U8(15), //
+ B(Star), R(4), //
+ B(LdaConstant), U8(1), //
+ B(Star), R(5), //
+ B(CallRuntime), U16(Runtime::kDefineClass), R(2), U8(4), //
+ B(Star), R(2), //
+ B(LoadIC), R(2), U8(2), U8(1), //
+ B(Star), R(3), //
+ B(Mov), R(3), R(4), //
+ B(LdaConstant), U8(3), //
+ B(Star), R(5), //
+ B(CreateClosure), U8(4), U8(0), //
+ B(Star), R(6), //
+ B(LdaSmi8), U8(2), //
+ B(Star), R(7), //
+ B(LdaZero), //
+ B(Star), R(8), //
+ B(CallRuntime), U16(Runtime::kDefineDataPropertyInLiteral), R(4), U8(5),
+ B(CallRuntime), U16(Runtime::kFinalizeClassDefinition), R(2), U8(2), //
+ B(Star), R(0), //
+ B(Star), R(1), //
+ B(LdaUndefined), //
+ B(Return) //
+ },
+ 5,
+ { InstanceType::SHARED_FUNCTION_INFO_TYPE, kInstanceTypeDontCare,
+ InstanceType::ONE_BYTE_INTERNALIZED_STRING_TYPE,
+ InstanceType::ONE_BYTE_INTERNALIZED_STRING_TYPE,
+ InstanceType::SHARED_FUNCTION_INFO_TYPE}},
+ {"var n0 = 'a';"
+ "var n1 = 'b';"
+ "class N {\n"
+ " [n0]() { return n0; }\n"
+ " static [n1]() { return n1; }\n"
+ "}\n",
+ 10 * kPointerSize,
+ 1,
+ 125,
+ {
+ B(CallRuntime), U16(Runtime::kNewFunctionContext), R(closure), //
+ /* */ U8(1), //
+ B(PushContext), R(2), //
+ B(LdaTheHole), //
+ B(Star), R(1), //
+ B(StackCheck), //
+ B(LdaConstant), U8(0), //
+ B(StaContextSlot), R(context), U8(4), //
+ B(LdaConstant), U8(1), //
+ B(StaContextSlot), R(context), U8(5), //
+ B(LdaTheHole), //
+ B(Star), R(0), //
+ B(LdaTheHole), //
+ B(Star), R(3), //
+ B(CreateClosure), U8(2), U8(0), //
+ B(Star), R(4), //
+ B(LdaSmi8), U8(41), //
+ B(Star), R(5), //
+ B(LdaSmi8), U8(107), //
+ B(Star), R(6), //
+ B(CallRuntime), U16(Runtime::kDefineClass), R(3), U8(4), //
+ B(Star), R(3), //
+ B(LoadIC), R(3), U8(3), U8(1), //
+ B(Star), R(4), //
+ B(Mov), R(4), R(5), //
+ B(LdaContextSlot), R(context), U8(4), //
+ B(ToName), //
+ B(Star), R(6), //
+ B(CreateClosure), U8(4), U8(0), //
+ B(Star), R(7), //
+ B(LdaSmi8), U8(2), //
+ B(Star), R(8), //
+ B(LdaSmi8), U8(1), //
+ B(Star), R(9), //
+ B(CallRuntime), U16(Runtime::kDefineDataPropertyInLiteral), R(5), U8(5),
+ B(Mov), R(3), R(5), //
+ B(LdaContextSlot), R(context), U8(5), //
+ B(ToName), //
+ B(Star), R(6), //
+ B(LdaConstant), U8(3), //
+ B(TestEqualStrict), R(6), //
+ B(JumpIfFalse), U8(7), //
+ B(CallRuntime), U16(Runtime::kThrowStaticPrototypeError), //
+ /* */ R(0), U8(0), //
+ B(CreateClosure), U8(5), U8(0), //
+ B(Star), R(7), //
+ B(LdaSmi8), U8(1), //
+ B(Star), R(9), //
+ B(CallRuntime), U16(Runtime::kDefineDataPropertyInLiteral), R(5), U8(5),
+ B(CallRuntime), U16(Runtime::kFinalizeClassDefinition), R(3), U8(2), //
+ B(Star), R(0), //
+ B(Star), R(1), //
+ B(LdaUndefined), //
+ B(Return), //
+ },
+ 6,
+ { InstanceType::ONE_BYTE_INTERNALIZED_STRING_TYPE,
+ InstanceType::ONE_BYTE_INTERNALIZED_STRING_TYPE,
+ InstanceType::SHARED_FUNCTION_INFO_TYPE,
+ InstanceType::ONE_BYTE_INTERNALIZED_STRING_TYPE,
+ InstanceType::SHARED_FUNCTION_INFO_TYPE,
+ InstanceType::SHARED_FUNCTION_INFO_TYPE}},
+ {"var count = 0;\n"
+ "class C { constructor() { count++; }}\n"
+ "return new C();\n",
+ 10 * kPointerSize,
+ 1,
+ 74,
+ {
+ B(CallRuntime), U16(Runtime::kNewFunctionContext), R(closure), U8(1), //
+ B(PushContext), R(2), //
+ B(LdaTheHole), //
+ B(Star), R(1), //
+ B(StackCheck), //
+ B(LdaZero), //
+ B(StaContextSlot), R(context), U8(4), //
+ B(LdaTheHole), //
+ B(Star), R(0), //
+ B(LdaTheHole), //
+ B(Star), R(3), //
+ B(CreateClosure), U8(0), U8(0), //
+ B(Star), R(4), //
+ B(LdaSmi8), U8(30), //
+ B(Star), R(5), //
+ B(LdaSmi8), U8(67), //
+ B(Star), R(6), //
+ B(CallRuntime), U16(Runtime::kDefineClass), R(3), U8(4), //
+ B(Star), R(3), //
+ B(LoadIC), R(3), U8(1), U8(1), //
+ B(Star), R(4), //
+ B(CallRuntime), U16(Runtime::kFinalizeClassDefinition), R(3), U8(2), //
+ B(Star), R(0), //
+ B(Star), R(1), //
+ B(JumpIfNotHole), U8(11), //
+ B(LdaConstant), U8(2), //
+ B(Star), R(4), //
+ B(CallRuntime), U16(Runtime::kThrowReferenceError), R(4), U8(1), //
+ B(Star), R(3), //
+ B(New), R(3), R(0), U8(0), //
+ B(Return), //
+ },
+ 3,
+ { InstanceType::SHARED_FUNCTION_INFO_TYPE,
+ InstanceType::ONE_BYTE_INTERNALIZED_STRING_TYPE,
+ InstanceType::ONE_BYTE_INTERNALIZED_STRING_TYPE}},
+ };
+ // clang-format on
+
+ for (size_t i = 0; i < arraysize(snippets); i++) {
+ Handle<BytecodeArray> bytecode_array =
+ helper.MakeBytecodeForFunctionBody(snippets[i].code_snippet);
+ CheckBytecodeArrayEqual(snippets[i], bytecode_array);
+ }
+}
+
+// TODO(oth): Add tests for super keyword.
+
} // namespace interpreter
} // namespace internal
} // namespace v8
diff --git a/test/cctest/interpreter/test-interpreter.cc b/test/cctest/interpreter/test-interpreter.cc
index 506cf00..69cf0e1 100644
--- a/test/cctest/interpreter/test-interpreter.cc
+++ b/test/cctest/interpreter/test-interpreter.cc
@@ -65,8 +65,6 @@
bytecode_(bytecode),
feedback_vector_(feedback_vector) {
i::FLAG_ignition = true;
- i::FLAG_ignition_fake_try_catch = true;
- i::FLAG_ignition_fallback_on_eval_and_catch = false;
i::FLAG_always_opt = false;
// Set ignition filter flag via SetFlagsFromString to avoid double-free
// (or potential leak with StrDup() based on ownership confusion).
@@ -98,6 +96,18 @@
return InterpreterCallable<A...>(isolate_, GetBytecodeFunction<A...>());
}
+ Local<Message> CheckThrowsReturnMessage() {
+ TryCatch try_catch(reinterpret_cast<v8::Isolate*>(isolate_));
+ auto callable = GetCallable<>();
+ MaybeHandle<Object> no_result = callable();
+ CHECK(isolate_->has_pending_exception());
+ CHECK(try_catch.HasCaught());
+ CHECK(no_result.is_null());
+ isolate_->OptionalRescheduleException(true);
+ CHECK(!try_catch.Message().IsEmpty());
+ return try_catch.Message();
+ }
+
static Handle<Object> NewObject(const char* script) {
return v8::Utils::OpenHandle(*CompileRun(script));
}
@@ -165,10 +175,8 @@
Handle<Object> undefined_value =
handles.main_isolate()->factory()->undefined_value();
- BytecodeArrayBuilder builder(handles.main_isolate(), handles.main_zone());
- builder.set_locals_count(0);
- builder.set_context_count(0);
- builder.set_parameter_count(1);
+ BytecodeArrayBuilder builder(handles.main_isolate(), handles.main_zone(), 1,
+ 0, 0);
builder.Return();
Handle<BytecodeArray> bytecode_array = builder.ToBytecodeArray();
@@ -184,10 +192,8 @@
Handle<Object> undefined_value =
handles.main_isolate()->factory()->undefined_value();
- BytecodeArrayBuilder builder(handles.main_isolate(), handles.main_zone());
- builder.set_locals_count(0);
- builder.set_context_count(0);
- builder.set_parameter_count(1);
+ BytecodeArrayBuilder builder(handles.main_isolate(), handles.main_zone(), 1,
+ 0, 0);
builder.LoadUndefined().Return();
Handle<BytecodeArray> bytecode_array = builder.ToBytecodeArray();
@@ -202,10 +208,8 @@
HandleAndZoneScope handles;
Handle<Object> null_value = handles.main_isolate()->factory()->null_value();
- BytecodeArrayBuilder builder(handles.main_isolate(), handles.main_zone());
- builder.set_locals_count(0);
- builder.set_context_count(0);
- builder.set_parameter_count(1);
+ BytecodeArrayBuilder builder(handles.main_isolate(), handles.main_zone(), 1,
+ 0, 0);
builder.LoadNull().Return();
Handle<BytecodeArray> bytecode_array = builder.ToBytecodeArray();
@@ -221,10 +225,8 @@
Handle<Object> the_hole_value =
handles.main_isolate()->factory()->the_hole_value();
- BytecodeArrayBuilder builder(handles.main_isolate(), handles.main_zone());
- builder.set_locals_count(0);
- builder.set_context_count(0);
- builder.set_parameter_count(1);
+ BytecodeArrayBuilder builder(handles.main_isolate(), handles.main_zone(), 1,
+ 0, 0);
builder.LoadTheHole().Return();
Handle<BytecodeArray> bytecode_array = builder.ToBytecodeArray();
@@ -239,10 +241,8 @@
HandleAndZoneScope handles;
Handle<Object> true_value = handles.main_isolate()->factory()->true_value();
- BytecodeArrayBuilder builder(handles.main_isolate(), handles.main_zone());
- builder.set_locals_count(0);
- builder.set_context_count(0);
- builder.set_parameter_count(1);
+ BytecodeArrayBuilder builder(handles.main_isolate(), handles.main_zone(), 1,
+ 0, 0);
builder.LoadTrue().Return();
Handle<BytecodeArray> bytecode_array = builder.ToBytecodeArray();
@@ -257,10 +257,8 @@
HandleAndZoneScope handles;
Handle<Object> false_value = handles.main_isolate()->factory()->false_value();
- BytecodeArrayBuilder builder(handles.main_isolate(), handles.main_zone());
- builder.set_locals_count(0);
- builder.set_context_count(0);
- builder.set_parameter_count(1);
+ BytecodeArrayBuilder builder(handles.main_isolate(), handles.main_zone(), 1,
+ 0, 0);
builder.LoadFalse().Return();
Handle<BytecodeArray> bytecode_array = builder.ToBytecodeArray();
@@ -277,10 +275,8 @@
// Small Smis.
for (int i = -128; i < 128; i++) {
- BytecodeArrayBuilder builder(handles.main_isolate(), handles.main_zone());
- builder.set_locals_count(0);
- builder.set_context_count(0);
- builder.set_parameter_count(1);
+ BytecodeArrayBuilder builder(handles.main_isolate(), handles.main_zone(), 1,
+ 0, 0);
builder.LoadLiteral(Smi::FromInt(i)).Return();
Handle<BytecodeArray> bytecode_array = builder.ToBytecodeArray();
@@ -292,10 +288,8 @@
// Large Smis.
{
- BytecodeArrayBuilder builder(handles.main_isolate(), handles.main_zone());
- builder.set_locals_count(0);
- builder.set_context_count(0);
- builder.set_parameter_count(1);
+ BytecodeArrayBuilder builder(handles.main_isolate(), handles.main_zone(), 1,
+ 0, 0);
builder.LoadLiteral(Smi::FromInt(0x12345678)).Return();
Handle<BytecodeArray> bytecode_array = builder.ToBytecodeArray();
@@ -307,10 +301,8 @@
// Heap numbers.
{
- BytecodeArrayBuilder builder(handles.main_isolate(), handles.main_zone());
- builder.set_locals_count(0);
- builder.set_context_count(0);
- builder.set_parameter_count(1);
+ BytecodeArrayBuilder builder(handles.main_isolate(), handles.main_zone(), 1,
+ 0, 0);
builder.LoadLiteral(factory->NewHeapNumber(-2.1e19)).Return();
Handle<BytecodeArray> bytecode_array = builder.ToBytecodeArray();
@@ -322,10 +314,8 @@
// Strings.
{
- BytecodeArrayBuilder builder(handles.main_isolate(), handles.main_zone());
- builder.set_locals_count(0);
- builder.set_context_count(0);
- builder.set_parameter_count(1);
+ BytecodeArrayBuilder builder(handles.main_isolate(), handles.main_zone(), 1,
+ 0, 0);
Handle<i::String> string = factory->NewStringFromAsciiChecked("String");
builder.LoadLiteral(string).Return();
Handle<BytecodeArray> bytecode_array = builder.ToBytecodeArray();
@@ -342,10 +332,8 @@
HandleAndZoneScope handles;
Handle<Object> true_value = handles.main_isolate()->factory()->true_value();
for (int i = 0; i <= kMaxInt8; i++) {
- BytecodeArrayBuilder builder(handles.main_isolate(), handles.main_zone());
- builder.set_locals_count(i + 1);
- builder.set_context_count(0);
- builder.set_parameter_count(1);
+ BytecodeArrayBuilder builder(handles.main_isolate(), handles.main_zone(), 1,
+ 0, i + 1);
Register reg(i);
builder.LoadTrue()
.StoreAccumulatorInRegister(reg)
@@ -362,117 +350,6 @@
}
-TEST(InterpreterExchangeRegisters) {
- for (int locals_count = 2; locals_count < 300; locals_count += 126) {
- HandleAndZoneScope handles;
- for (int exchanges = 1; exchanges < 4; exchanges++) {
- BytecodeArrayBuilder builder(handles.main_isolate(), handles.main_zone());
- builder.set_locals_count(locals_count);
- builder.set_context_count(0);
- builder.set_parameter_count(0);
-
- Register r0(0);
- Register r1(locals_count - 1);
- builder.LoadTrue();
- builder.StoreAccumulatorInRegister(r0);
- builder.ExchangeRegisters(r0, r1);
- builder.LoadFalse();
- builder.StoreAccumulatorInRegister(r0);
-
- bool expected = false;
- for (int i = 0; i < exchanges; i++) {
- builder.ExchangeRegisters(r0, r1);
- expected = !expected;
- }
- builder.LoadAccumulatorWithRegister(r0);
- builder.Return();
- Handle<BytecodeArray> bytecode_array = builder.ToBytecodeArray();
- InterpreterTester tester(handles.main_isolate(), bytecode_array);
- auto callable = tester.GetCallable<>();
- Handle<Object> return_val = callable().ToHandleChecked();
- Handle<Object> expected_val =
- handles.main_isolate()->factory()->ToBoolean(expected);
- CHECK(return_val.is_identical_to(expected_val));
- }
- }
-}
-
-
-TEST(InterpreterExchangeRegistersWithParameter) {
- for (int locals_count = 2; locals_count < 300; locals_count += 126) {
- HandleAndZoneScope handles;
- for (int exchanges = 1; exchanges < 4; exchanges++) {
- BytecodeArrayBuilder builder(handles.main_isolate(), handles.main_zone());
- builder.set_locals_count(locals_count);
- builder.set_context_count(0);
- builder.set_parameter_count(3);
-
- Register r0 = Register::FromParameterIndex(2, 3);
- Register r1(locals_count - 1);
- builder.LoadTrue();
- builder.StoreAccumulatorInRegister(r0);
- builder.ExchangeRegisters(r0, r1);
- builder.LoadFalse();
- builder.StoreAccumulatorInRegister(r0);
-
- bool expected = false;
- for (int i = 0; i < exchanges; i++) {
- builder.ExchangeRegisters(r0, r1);
- expected = !expected;
- }
- builder.LoadAccumulatorWithRegister(r0);
- builder.Return();
- Handle<BytecodeArray> bytecode_array = builder.ToBytecodeArray();
- InterpreterTester tester(handles.main_isolate(), bytecode_array);
- auto callable = tester.GetCallable<>();
- Handle<Object> return_val = callable().ToHandleChecked();
- Handle<Object> expected_val =
- handles.main_isolate()->factory()->ToBoolean(expected);
- CHECK(return_val.is_identical_to(expected_val));
- }
- }
-}
-
-
-TEST(InterpreterExchangeWideRegisters) {
- for (int locals_count = 3; locals_count < 300; locals_count += 126) {
- HandleAndZoneScope handles;
- for (int exchanges = 0; exchanges < 7; exchanges++) {
- BytecodeArrayBuilder builder(handles.main_isolate(), handles.main_zone());
- builder.set_locals_count(locals_count);
- builder.set_context_count(0);
- builder.set_parameter_count(0);
-
- Register r0(0);
- Register r1(locals_count - 1);
- Register r2(locals_count - 2);
- builder.LoadLiteral(Smi::FromInt(200));
- builder.StoreAccumulatorInRegister(r0);
- builder.ExchangeRegisters(r0, r1);
- builder.LoadLiteral(Smi::FromInt(100));
- builder.StoreAccumulatorInRegister(r0);
- builder.ExchangeRegisters(r0, r2);
- builder.LoadLiteral(Smi::FromInt(0));
- builder.StoreAccumulatorInRegister(r0);
- for (int i = 0; i < exchanges; i++) {
- builder.ExchangeRegisters(r1, r2);
- builder.ExchangeRegisters(r0, r1);
- }
- builder.LoadAccumulatorWithRegister(r0);
- builder.Return();
- Handle<BytecodeArray> bytecode_array = builder.ToBytecodeArray();
- InterpreterTester tester(handles.main_isolate(), bytecode_array);
- auto callable = tester.GetCallable<>();
- Handle<Object> return_val = callable().ToHandleChecked();
- Handle<Object> expected_val =
- handles.main_isolate()->factory()->NewNumberFromInt(100 *
- (exchanges % 3));
- CHECK(return_val.is_identical_to(expected_val));
- }
- }
-}
-
-
static const Token::Value kShiftOperators[] = {
Token::Value::SHL, Token::Value::SAR, Token::Value::SHR};
@@ -539,17 +416,14 @@
HandleAndZoneScope handles;
i::Factory* factory = handles.main_isolate()->factory();
BytecodeArrayBuilder builder(handles.main_isolate(),
- handles.main_zone());
- builder.set_locals_count(1);
- builder.set_context_count(0);
- builder.set_parameter_count(1);
+ handles.main_zone(), 1, 0, 1);
Register reg(0);
int lhs = lhs_inputs[l];
int rhs = rhs_inputs[r];
builder.LoadLiteral(Smi::FromInt(lhs))
.StoreAccumulatorInRegister(reg)
.LoadLiteral(Smi::FromInt(rhs))
- .BinaryOperation(kShiftOperators[o], reg, Strength::WEAK)
+ .BinaryOperation(kShiftOperators[o], reg)
.Return();
Handle<BytecodeArray> bytecode_array = builder.ToBytecodeArray();
@@ -574,17 +448,14 @@
HandleAndZoneScope handles;
i::Factory* factory = handles.main_isolate()->factory();
BytecodeArrayBuilder builder(handles.main_isolate(),
- handles.main_zone());
- builder.set_locals_count(1);
- builder.set_context_count(0);
- builder.set_parameter_count(1);
+ handles.main_zone(), 1, 0, 1);
Register reg(0);
int lhs = lhs_inputs[l];
int rhs = rhs_inputs[r];
builder.LoadLiteral(Smi::FromInt(lhs))
.StoreAccumulatorInRegister(reg)
.LoadLiteral(Smi::FromInt(rhs))
- .BinaryOperation(kArithmeticOperators[o], reg, Strength::WEAK)
+ .BinaryOperation(kArithmeticOperators[o], reg)
.Return();
Handle<BytecodeArray> bytecode_array = builder.ToBytecodeArray();
@@ -610,17 +481,14 @@
HandleAndZoneScope handles;
i::Factory* factory = handles.main_isolate()->factory();
BytecodeArrayBuilder builder(handles.main_isolate(),
- handles.main_zone());
- builder.set_locals_count(1);
- builder.set_context_count(0);
- builder.set_parameter_count(1);
+ handles.main_zone(), 1, 0, 1);
Register reg(0);
double lhs = lhs_inputs[l];
double rhs = rhs_inputs[r];
builder.LoadLiteral(factory->NewNumber(lhs))
.StoreAccumulatorInRegister(reg)
.LoadLiteral(factory->NewNumber(rhs))
- .BinaryOperation(kArithmeticOperators[o], reg, Strength::WEAK)
+ .BinaryOperation(kArithmeticOperators[o], reg)
.Return();
Handle<BytecodeArray> bytecode_array = builder.ToBytecodeArray();
@@ -669,15 +537,13 @@
};
for (size_t i = 0; i < arraysize(test_cases); i++) {
- BytecodeArrayBuilder builder(handles.main_isolate(), handles.main_zone());
- builder.set_locals_count(1);
- builder.set_context_count(0);
- builder.set_parameter_count(1);
+ BytecodeArrayBuilder builder(handles.main_isolate(), handles.main_zone(), 1,
+ 0, 1);
Register reg(0);
builder.LoadLiteral(test_cases[i].lhs)
.StoreAccumulatorInRegister(reg)
.LoadLiteral(test_cases[i].rhs)
- .BinaryOperation(Token::Value::ADD, reg, Strength::WEAK)
+ .BinaryOperation(Token::Value::ADD, reg)
.Return();
Handle<BytecodeArray> bytecode_array = builder.ToBytecodeArray();
@@ -691,10 +557,8 @@
TEST(InterpreterParameter1) {
HandleAndZoneScope handles;
- BytecodeArrayBuilder builder(handles.main_isolate(), handles.main_zone());
- builder.set_locals_count(0);
- builder.set_context_count(0);
- builder.set_parameter_count(1);
+ BytecodeArrayBuilder builder(handles.main_isolate(), handles.main_zone(), 1,
+ 0, 0);
builder.LoadAccumulatorWithRegister(builder.Parameter(0)).Return();
Handle<BytecodeArray> bytecode_array = builder.ToBytecodeArray();
@@ -715,18 +579,16 @@
TEST(InterpreterParameter8) {
HandleAndZoneScope handles;
- BytecodeArrayBuilder builder(handles.main_isolate(), handles.main_zone());
- builder.set_locals_count(0);
- builder.set_context_count(0);
- builder.set_parameter_count(8);
+ BytecodeArrayBuilder builder(handles.main_isolate(), handles.main_zone(), 8,
+ 0, 0);
builder.LoadAccumulatorWithRegister(builder.Parameter(0))
- .BinaryOperation(Token::Value::ADD, builder.Parameter(1), Strength::WEAK)
- .BinaryOperation(Token::Value::ADD, builder.Parameter(2), Strength::WEAK)
- .BinaryOperation(Token::Value::ADD, builder.Parameter(3), Strength::WEAK)
- .BinaryOperation(Token::Value::ADD, builder.Parameter(4), Strength::WEAK)
- .BinaryOperation(Token::Value::ADD, builder.Parameter(5), Strength::WEAK)
- .BinaryOperation(Token::Value::ADD, builder.Parameter(6), Strength::WEAK)
- .BinaryOperation(Token::Value::ADD, builder.Parameter(7), Strength::WEAK)
+ .BinaryOperation(Token::Value::ADD, builder.Parameter(1))
+ .BinaryOperation(Token::Value::ADD, builder.Parameter(2))
+ .BinaryOperation(Token::Value::ADD, builder.Parameter(3))
+ .BinaryOperation(Token::Value::ADD, builder.Parameter(4))
+ .BinaryOperation(Token::Value::ADD, builder.Parameter(5))
+ .BinaryOperation(Token::Value::ADD, builder.Parameter(6))
+ .BinaryOperation(Token::Value::ADD, builder.Parameter(7))
.Return();
Handle<BytecodeArray> bytecode_array = builder.ToBytecodeArray();
@@ -752,10 +614,8 @@
TEST(InterpreterParameter1Assign) {
HandleAndZoneScope handles;
- BytecodeArrayBuilder builder(handles.main_isolate(), handles.main_zone());
- builder.set_locals_count(0);
- builder.set_context_count(0);
- builder.set_parameter_count(1);
+ BytecodeArrayBuilder builder(handles.main_isolate(), handles.main_zone(), 1,
+ 0, 0);
builder.LoadLiteral(Smi::FromInt(5))
.StoreAccumulatorInRegister(builder.Parameter(0))
.LoadAccumulatorWithRegister(builder.Parameter(0))
@@ -882,12 +742,9 @@
Handle<i::String> name = factory->NewStringFromAsciiChecked("val");
name = factory->string_table()->LookupString(isolate, name);
- BytecodeArrayBuilder builder(handles.main_isolate(), handles.main_zone());
- builder.set_locals_count(0);
- builder.set_context_count(0);
- builder.set_parameter_count(1);
- builder.LoadNamedProperty(builder.Parameter(0), name, vector->GetIndex(slot),
- i::SLOPPY)
+ BytecodeArrayBuilder builder(handles.main_isolate(), handles.main_zone(), 1,
+ 0, 0);
+ builder.LoadNamedProperty(builder.Parameter(0), name, vector->GetIndex(slot))
.Return();
Handle<BytecodeArray> bytecode_array = builder.ToBytecodeArray();
@@ -938,13 +795,10 @@
Handle<i::String> key = factory->NewStringFromAsciiChecked("key");
key = factory->string_table()->LookupString(isolate, key);
- BytecodeArrayBuilder builder(handles.main_isolate(), handles.main_zone());
- builder.set_locals_count(1);
- builder.set_context_count(0);
- builder.set_parameter_count(1);
+ BytecodeArrayBuilder builder(handles.main_isolate(), handles.main_zone(), 1,
+ 0, 1);
builder.LoadLiteral(key)
- .LoadKeyedProperty(builder.Parameter(0), vector->GetIndex(slot),
- i::STRICT)
+ .LoadKeyedProperty(builder.Parameter(0), vector->GetIndex(slot))
.Return();
Handle<BytecodeArray> bytecode_array = builder.ToBytecodeArray();
@@ -983,10 +837,8 @@
Handle<i::String> name = factory->NewStringFromAsciiChecked("val");
name = factory->string_table()->LookupString(isolate, name);
- BytecodeArrayBuilder builder(handles.main_isolate(), handles.main_zone());
- builder.set_locals_count(0);
- builder.set_context_count(0);
- builder.set_parameter_count(1);
+ BytecodeArrayBuilder builder(handles.main_isolate(), handles.main_zone(), 1,
+ 0, 0);
builder.LoadLiteral(Smi::FromInt(999))
.StoreNamedProperty(builder.Parameter(0), name, vector->GetIndex(slot),
i::STRICT)
@@ -1044,10 +896,8 @@
Handle<i::String> name = factory->NewStringFromAsciiChecked("val");
name = factory->string_table()->LookupString(isolate, name);
- BytecodeArrayBuilder builder(handles.main_isolate(), handles.main_zone());
- builder.set_locals_count(1);
- builder.set_context_count(0);
- builder.set_parameter_count(1);
+ BytecodeArrayBuilder builder(handles.main_isolate(), handles.main_zone(), 1,
+ 0, 1);
builder.LoadLiteral(name)
.StoreAccumulatorInRegister(Register(0))
.LoadLiteral(Smi::FromInt(999))
@@ -1078,8 +928,7 @@
CHECK_EQ(Smi::cast(*result), Smi::FromInt(999));
}
-
-TEST(InterpreterCall) {
+static void TestInterpreterCall(TailCallMode tail_call_mode) {
HandleAndZoneScope handles;
i::Isolate* isolate = handles.main_isolate();
i::Factory* factory = isolate->factory();
@@ -1097,13 +946,11 @@
// Check with no args.
{
- BytecodeArrayBuilder builder(handles.main_isolate(), handles.main_zone());
- builder.set_locals_count(1);
- builder.set_context_count(0);
- builder.set_parameter_count(1);
- builder.LoadNamedProperty(builder.Parameter(0), name, slot_index, i::SLOPPY)
+ BytecodeArrayBuilder builder(handles.main_isolate(), handles.main_zone(), 1,
+ 0, 1);
+ builder.LoadNamedProperty(builder.Parameter(0), name, slot_index)
.StoreAccumulatorInRegister(Register(0))
- .Call(Register(0), builder.Parameter(0), 0, 0)
+ .Call(Register(0), builder.Parameter(0), 1, 0, tail_call_mode)
.Return();
Handle<BytecodeArray> bytecode_array = builder.ToBytecodeArray();
@@ -1118,13 +965,11 @@
// Check that receiver is passed properly.
{
- BytecodeArrayBuilder builder(handles.main_isolate(), handles.main_zone());
- builder.set_locals_count(1);
- builder.set_context_count(0);
- builder.set_parameter_count(1);
- builder.LoadNamedProperty(builder.Parameter(0), name, slot_index, i::SLOPPY)
+ BytecodeArrayBuilder builder(handles.main_isolate(), handles.main_zone(), 1,
+ 0, 1);
+ builder.LoadNamedProperty(builder.Parameter(0), name, slot_index)
.StoreAccumulatorInRegister(Register(0))
- .Call(Register(0), builder.Parameter(0), 0, 0)
+ .Call(Register(0), builder.Parameter(0), 1, 0, tail_call_mode)
.Return();
Handle<BytecodeArray> bytecode_array = builder.ToBytecodeArray();
@@ -1142,11 +987,9 @@
// Check with two parameters (+ receiver).
{
- BytecodeArrayBuilder builder(handles.main_isolate(), handles.main_zone());
- builder.set_locals_count(4);
- builder.set_context_count(0);
- builder.set_parameter_count(1);
- builder.LoadNamedProperty(builder.Parameter(0), name, slot_index, i::SLOPPY)
+ BytecodeArrayBuilder builder(handles.main_isolate(), handles.main_zone(), 1,
+ 0, 4);
+ builder.LoadNamedProperty(builder.Parameter(0), name, slot_index)
.StoreAccumulatorInRegister(Register(0))
.LoadAccumulatorWithRegister(builder.Parameter(0))
.StoreAccumulatorInRegister(Register(1))
@@ -1154,7 +997,7 @@
.StoreAccumulatorInRegister(Register(2))
.LoadLiteral(Smi::FromInt(11))
.StoreAccumulatorInRegister(Register(3))
- .Call(Register(0), Register(1), 2, 0)
+ .Call(Register(0), Register(1), 3, 0, tail_call_mode)
.Return();
Handle<BytecodeArray> bytecode_array = builder.ToBytecodeArray();
@@ -1171,11 +1014,9 @@
// Check with 10 parameters (+ receiver).
{
- BytecodeArrayBuilder builder(handles.main_isolate(), handles.main_zone());
- builder.set_locals_count(12);
- builder.set_context_count(0);
- builder.set_parameter_count(1);
- builder.LoadNamedProperty(builder.Parameter(0), name, slot_index, i::SLOPPY)
+ BytecodeArrayBuilder builder(handles.main_isolate(), handles.main_zone(), 1,
+ 0, 12);
+ builder.LoadNamedProperty(builder.Parameter(0), name, slot_index)
.StoreAccumulatorInRegister(Register(0))
.LoadAccumulatorWithRegister(builder.Parameter(0))
.StoreAccumulatorInRegister(Register(1))
@@ -1199,7 +1040,7 @@
.StoreAccumulatorInRegister(Register(10))
.LoadLiteral(factory->NewStringFromAsciiChecked("j"))
.StoreAccumulatorInRegister(Register(11))
- .Call(Register(0), Register(1), 10, 0)
+ .Call(Register(0), Register(1), 11, 0, tail_call_mode)
.Return();
Handle<BytecodeArray> bytecode_array = builder.ToBytecodeArray();
@@ -1220,6 +1061,9 @@
}
}
+TEST(InterpreterCall) { TestInterpreterCall(TailCallMode::kDisallow); }
+
+TEST(InterpreterTailCall) { TestInterpreterCall(TailCallMode::kAllow); }
static BytecodeArrayBuilder& SetRegister(BytecodeArrayBuilder& builder,
Register reg, int value,
@@ -1236,7 +1080,7 @@
Register scratch) {
return builder.StoreAccumulatorInRegister(scratch)
.LoadLiteral(Smi::FromInt(value))
- .BinaryOperation(Token::Value::ADD, reg, Strength::WEAK)
+ .BinaryOperation(Token::Value::ADD, reg)
.StoreAccumulatorInRegister(reg)
.LoadAccumulatorWithRegister(scratch);
}
@@ -1244,10 +1088,8 @@
TEST(InterpreterJumps) {
HandleAndZoneScope handles;
- BytecodeArrayBuilder builder(handles.main_isolate(), handles.main_zone());
- builder.set_locals_count(2);
- builder.set_context_count(0);
- builder.set_parameter_count(0);
+ BytecodeArrayBuilder builder(handles.main_isolate(), handles.main_zone(), 0,
+ 0, 2);
Register reg(0), scratch(1);
BytecodeLabel label[3];
@@ -1273,10 +1115,8 @@
TEST(InterpreterConditionalJumps) {
HandleAndZoneScope handles;
- BytecodeArrayBuilder builder(handles.main_isolate(), handles.main_zone());
- builder.set_locals_count(2);
- builder.set_context_count(0);
- builder.set_parameter_count(0);
+ BytecodeArrayBuilder builder(handles.main_isolate(), handles.main_zone(), 0,
+ 0, 2);
Register reg(0), scratch(1);
BytecodeLabel label[2];
BytecodeLabel done, done1;
@@ -1309,10 +1149,8 @@
TEST(InterpreterConditionalJumps2) {
// TODO(oth): Add tests for all conditional jumps near and far.
HandleAndZoneScope handles;
- BytecodeArrayBuilder builder(handles.main_isolate(), handles.main_zone());
- builder.set_locals_count(2);
- builder.set_context_count(0);
- builder.set_parameter_count(0);
+ BytecodeArrayBuilder builder(handles.main_isolate(), handles.main_zone(), 0,
+ 0, 2);
Register reg(0), scratch(1);
BytecodeLabel label[2];
BytecodeLabel done, done1;
@@ -1397,15 +1235,12 @@
for (size_t j = 0; j < arraysize(inputs); j++) {
HandleAndZoneScope handles;
BytecodeArrayBuilder builder(handles.main_isolate(),
- handles.main_zone());
+ handles.main_zone(), 0, 0, 1);
Register r0(0);
- builder.set_locals_count(1);
- builder.set_context_count(0);
- builder.set_parameter_count(0);
builder.LoadLiteral(Smi::FromInt(inputs[i]))
.StoreAccumulatorInRegister(r0)
.LoadLiteral(Smi::FromInt(inputs[j]))
- .CompareOperation(comparison, r0, Strength::WEAK)
+ .CompareOperation(comparison, r0)
.Return();
Handle<BytecodeArray> bytecode_array = builder.ToBytecodeArray();
@@ -1436,15 +1271,12 @@
HandleAndZoneScope handles;
i::Factory* factory = handles.main_isolate()->factory();
BytecodeArrayBuilder builder(handles.main_isolate(),
- handles.main_zone());
+ handles.main_zone(), 0, 0, 1);
Register r0(0);
- builder.set_locals_count(1);
- builder.set_context_count(0);
- builder.set_parameter_count(0);
builder.LoadLiteral(factory->NewHeapNumber(inputs[i]))
.StoreAccumulatorInRegister(r0)
.LoadLiteral(factory->NewHeapNumber(inputs[j]))
- .CompareOperation(comparison, r0, Strength::WEAK)
+ .CompareOperation(comparison, r0)
.Return();
Handle<BytecodeArray> bytecode_array = builder.ToBytecodeArray();
@@ -1472,15 +1304,12 @@
HandleAndZoneScope handles;
i::Factory* factory = handles.main_isolate()->factory();
BytecodeArrayBuilder builder(handles.main_isolate(),
- handles.main_zone());
+ handles.main_zone(), 0, 0, 1);
Register r0(0);
- builder.set_locals_count(1);
- builder.set_context_count(0);
- builder.set_parameter_count(0);
builder.LoadLiteral(factory->NewStringFromAsciiChecked(lhs))
.StoreAccumulatorInRegister(r0)
.LoadLiteral(factory->NewStringFromAsciiChecked(rhs))
- .CompareOperation(comparison, r0, Strength::WEAK)
+ .CompareOperation(comparison, r0)
.Return();
Handle<BytecodeArray> bytecode_array = builder.ToBytecodeArray();
@@ -1519,24 +1348,21 @@
HandleAndZoneScope handles;
i::Factory* factory = handles.main_isolate()->factory();
BytecodeArrayBuilder builder(handles.main_isolate(),
- handles.main_zone());
+ handles.main_zone(), 0, 0, 1);
Register r0(0);
- builder.set_locals_count(1);
- builder.set_context_count(0);
- builder.set_parameter_count(0);
if (pass == 0) {
// Comparison with HeapNumber on the lhs and String on the rhs
builder.LoadLiteral(factory->NewNumber(lhs))
.StoreAccumulatorInRegister(r0)
.LoadLiteral(factory->NewStringFromAsciiChecked(rhs_cstr))
- .CompareOperation(comparison, r0, Strength::WEAK)
+ .CompareOperation(comparison, r0)
.Return();
} else {
// Comparison with HeapNumber on the rhs and String on the lhs
builder.LoadLiteral(factory->NewStringFromAsciiChecked(lhs_cstr))
.StoreAccumulatorInRegister(r0)
.LoadLiteral(factory->NewNumber(rhs))
- .CompareOperation(comparison, r0, Strength::WEAK)
+ .CompareOperation(comparison, r0)
.Return();
}
@@ -1564,15 +1390,13 @@
Handle<i::Object> cases[] = {Handle<i::Object>::cast(instance), other};
for (size_t i = 0; i < arraysize(cases); i++) {
bool expected_value = (i == 0);
- BytecodeArrayBuilder builder(handles.main_isolate(), handles.main_zone());
+ BytecodeArrayBuilder builder(handles.main_isolate(), handles.main_zone(), 0,
+ 0, 1);
Register r0(0);
- builder.set_locals_count(1);
- builder.set_context_count(0);
- builder.set_parameter_count(0);
builder.LoadLiteral(cases[i]);
builder.StoreAccumulatorInRegister(r0)
.LoadLiteral(func)
- .CompareOperation(Token::Value::INSTANCEOF, r0, Strength::WEAK)
+ .CompareOperation(Token::Value::INSTANCEOF, r0)
.Return();
Handle<BytecodeArray> bytecode_array = builder.ToBytecodeArray();
@@ -1590,20 +1414,18 @@
i::Factory* factory = handles.main_isolate()->factory();
// Allocate an array
Handle<i::JSArray> array =
- factory->NewJSArray(i::ElementsKind::FAST_SMI_ELEMENTS);
+ factory->NewJSArray(0, i::ElementsKind::FAST_SMI_ELEMENTS);
// Check for these properties on the array object
const char* properties[] = {"length", "fuzzle", "x", "0"};
for (size_t i = 0; i < arraysize(properties); i++) {
bool expected_value = (i == 0);
- BytecodeArrayBuilder builder(handles.main_isolate(), handles.main_zone());
+ BytecodeArrayBuilder builder(handles.main_isolate(), handles.main_zone(), 0,
+ 0, 1);
Register r0(0);
- builder.set_locals_count(1);
- builder.set_context_count(0);
- builder.set_parameter_count(0);
builder.LoadLiteral(factory->NewStringFromAsciiChecked(properties[i]))
.StoreAccumulatorInRegister(r0)
.LoadLiteral(Handle<Object>::cast(array))
- .CompareOperation(Token::Value::IN, r0, Strength::WEAK)
+ .CompareOperation(Token::Value::IN, r0)
.Return();
Handle<BytecodeArray> bytecode_array = builder.ToBytecodeArray();
@@ -1620,11 +1442,9 @@
HandleAndZoneScope handles;
for (size_t i = 1; i < 10; i++) {
bool expected_value = ((i & 1) == 1);
- BytecodeArrayBuilder builder(handles.main_isolate(), handles.main_zone());
+ BytecodeArrayBuilder builder(handles.main_isolate(), handles.main_zone(), 0,
+ 0, 0);
Register r0(0);
- builder.set_locals_count(0);
- builder.set_context_count(0);
- builder.set_parameter_count(0);
builder.LoadFalse();
for (size_t j = 0; j < i; j++) {
builder.LogicalNot();
@@ -1683,11 +1503,9 @@
};
for (size_t i = 0; i < arraysize(object_type_tuples); i++) {
- BytecodeArrayBuilder builder(handles.main_isolate(), handles.main_zone());
+ BytecodeArrayBuilder builder(handles.main_isolate(), handles.main_zone(), 0,
+ 0, 0);
Register r0(0);
- builder.set_locals_count(0);
- builder.set_context_count(0);
- builder.set_parameter_count(0);
LoadAny(&builder, factory, object_type_tuples[i].first);
builder.LogicalNot();
builder.Return();
@@ -1731,10 +1549,8 @@
TEST(InterpreterCallRuntime) {
HandleAndZoneScope handles;
- BytecodeArrayBuilder builder(handles.main_isolate(), handles.main_zone());
- builder.set_locals_count(2);
- builder.set_context_count(0);
- builder.set_parameter_count(1);
+ BytecodeArrayBuilder builder(handles.main_isolate(), handles.main_zone(), 1,
+ 0, 2);
builder.LoadLiteral(Smi::FromInt(15))
.StoreAccumulatorInRegister(Register(0))
.LoadLiteral(Smi::FromInt(40))
@@ -2133,29 +1949,76 @@
TEST(InterpreterTryCatch) {
HandleAndZoneScope handles;
+ i::Isolate* isolate = handles.main_isolate();
- // TODO(rmcilroy): modify tests when we have real try catch support.
- std::string source(InterpreterTester::SourceForBody(
- "var a = 1; try { a = a + 1; } catch(e) { a = a + 2; }; return a;"));
- InterpreterTester tester(handles.main_isolate(), source.c_str());
- auto callable = tester.GetCallable<>();
+ std::pair<const char*, Handle<Object>> catches[] = {
+ std::make_pair("var a = 1; try { a = 2 } catch(e) { a = 3 }; return a;",
+ handle(Smi::FromInt(2), isolate)),
+ std::make_pair("var a; try { undef.x } catch(e) { a = 2 }; return a;",
+ handle(Smi::FromInt(2), isolate)),
+ std::make_pair("var a; try { throw 1 } catch(e) { a = e + 2 }; return a;",
+ handle(Smi::FromInt(3), isolate)),
+ std::make_pair("var a; try { throw 1 } catch(e) { a = e + 2 };"
+ " try { throw a } catch(e) { a = e + 3 }; return a;",
+ handle(Smi::FromInt(6), isolate)),
+ };
- Handle<Object> return_val = callable().ToHandleChecked();
- CHECK_EQ(Smi::cast(*return_val), Smi::FromInt(2));
+ for (size_t i = 0; i < arraysize(catches); i++) {
+ std::string source(InterpreterTester::SourceForBody(catches[i].first));
+ InterpreterTester tester(handles.main_isolate(), source.c_str());
+ auto callable = tester.GetCallable<>();
+
+ Handle<i::Object> return_value = callable().ToHandleChecked();
+ CHECK(return_value->SameValue(*catches[i].second));
+ }
}
TEST(InterpreterTryFinally) {
HandleAndZoneScope handles;
+ i::Isolate* isolate = handles.main_isolate();
+ i::Factory* factory = isolate->factory();
- // TODO(rmcilroy): modify tests when we have real try finally support.
- std::string source(InterpreterTester::SourceForBody(
- "var a = 1; try { a = a + 1; } finally { a = a + 2; }; return a;"));
- InterpreterTester tester(handles.main_isolate(), source.c_str());
- auto callable = tester.GetCallable<>();
+ std::pair<const char*, Handle<Object>> finallies[] = {
+ std::make_pair(
+ "var a = 1; try { a = a + 1; } finally { a = a + 2; }; return a;",
+ factory->NewStringFromStaticChars("R4")),
+ std::make_pair(
+ "var a = 1; try { a = 2; return 23; } finally { a = 3 }; return a;",
+ factory->NewStringFromStaticChars("R23")),
+ std::make_pair(
+ "var a = 1; try { a = 2; throw 23; } finally { a = 3 }; return a;",
+ factory->NewStringFromStaticChars("E23")),
+ std::make_pair(
+ "var a = 1; try { a = 2; throw 23; } finally { return a; };",
+ factory->NewStringFromStaticChars("R2")),
+ std::make_pair(
+ "var a = 1; try { a = 2; throw 23; } finally { throw 42; };",
+ factory->NewStringFromStaticChars("E42")),
+ std::make_pair("var a = 1; for (var i = 10; i < 20; i += 5) {"
+ " try { a = 2; break; } finally { a = 3; }"
+ "} return a + i;",
+ factory->NewStringFromStaticChars("R13")),
+ std::make_pair("var a = 1; for (var i = 10; i < 20; i += 5) {"
+ " try { a = 2; continue; } finally { a = 3; }"
+ "} return a + i;",
+ factory->NewStringFromStaticChars("R23")),
+ std::make_pair("var a = 1; try { a = 2;"
+ " try { a = 3; throw 23; } finally { a = 4; }"
+ "} catch(e) { a = a + e; } return a;",
+ factory->NewStringFromStaticChars("R27")),
+ };
- Handle<Object> return_val = callable().ToHandleChecked();
- CHECK_EQ(Smi::cast(*return_val), Smi::FromInt(4));
+ const char* try_wrapper =
+ "(function() { try { return 'R' + f() } catch(e) { return 'E' + e }})()";
+
+ for (size_t i = 0; i < arraysize(finallies); i++) {
+ std::string source(InterpreterTester::SourceForBody(finallies[i].first));
+ InterpreterTester tester(handles.main_isolate(), source.c_str());
+ tester.GetCallable<>();
+ Handle<Object> wrapped = v8::Utils::OpenHandle(*CompileRun(try_wrapper));
+ CHECK(wrapped->SameValue(*finallies[i].second));
+ }
}
@@ -2164,7 +2027,6 @@
i::Isolate* isolate = handles.main_isolate();
i::Factory* factory = isolate->factory();
- // TODO(rmcilroy): modify tests when we have real try catch support.
std::pair<const char*, Handle<Object>> throws[] = {
std::make_pair("throw undefined;\n",
factory->undefined_value()),
@@ -2364,6 +2226,15 @@
std::make_pair("function f(a, b, c, d) {"
" 'use strict'; c = b; return arguments[2]; }",
2),
+ // check rest parameters
+ std::make_pair("function f(...restArray) { return restArray[0]; }", 0),
+ std::make_pair("function f(a, ...restArray) { return restArray[0]; }", 1),
+ std::make_pair("function f(a, ...restArray) { return arguments[0]; }", 0),
+ std::make_pair("function f(a, ...restArray) { return arguments[1]; }", 1),
+ std::make_pair("function f(a, ...restArray) { return restArray[1]; }", 2),
+ std::make_pair("function f(a, ...arguments) { return arguments[0]; }", 1),
+ std::make_pair("function f(a, b, ...restArray) { return restArray[0]; }",
+ 2),
};
// Test passing no arguments.
@@ -2698,211 +2569,301 @@
TEST(InterpreterForIn) {
- HandleAndZoneScope handles;
-
std::pair<const char*, int> for_in_samples[] = {
- {"function f() {\n"
- " var r = -1;\n"
- " for (var a in null) { r = a; }\n"
- " return r;\n"
- "}",
+ {"var r = -1;\n"
+ "for (var a in null) { r = a; }\n"
+ "return r;\n",
-1},
- {"function f() {\n"
- " var r = -1;\n"
- " for (var a in undefined) { r = a; }\n"
- " return r;\n"
- "}",
+ {"var r = -1;\n"
+ "for (var a in undefined) { r = a; }\n"
+ "return r;\n",
-1},
- {"function f() {\n"
- " var r = 0;\n"
- " for (var a in [0,6,7,9]) { r = r + (1 << a); }\n"
- " return r;\n"
- "}",
+ {"var r = 0;\n"
+ "for (var a in [0,6,7,9]) { r = r + (1 << a); }\n"
+ "return r;\n",
0xf},
- {"function f() {\n"
- " var r = 0;\n"
- " for (var a in [0,6,7,9]) { r = r + (1 << a); }\n"
- " var r = 0;\n"
- " for (var a in [0,6,7,9]) { r = r + (1 << a); }\n"
- " return r;\n"
- "}",
- 0xf},
- {"function f() {\n"
- " var r = 0;\n"
- " for (var a in 'foobar') { r = r + (1 << a); }\n"
- " return r;\n"
- "}",
- 0x3f},
- {"function f() {\n"
- " var r = 0;\n"
- " for (var a in {1:0, 10:1, 100:2, 1000:3}) {\n"
- " r = r + Number(a);\n"
- " }\n"
- " return r;\n"
- "}",
- 1111},
- {"function f() {\n"
- " var r = 0;\n"
- " var data = {1:0, 10:1, 100:2, 1000:3};\n"
- " for (var a in data) {\n"
- " if (a == 1) delete data[1];\n"
- " r = r + Number(a);\n"
- " }\n"
- " return r;\n"
- "}",
- 1111},
- {"function f() {\n"
- " var r = 0;\n"
- " var data = {1:0, 10:1, 100:2, 1000:3};\n"
- " for (var a in data) {\n"
- " if (a == 10) delete data[100];\n"
- " r = r + Number(a);\n"
- " }\n"
- " return r;\n"
- "}",
- 1011},
- {"function f() {\n"
- " var r = 0;\n"
- " var data = {1:0, 10:1, 100:2, 1000:3};\n"
- " for (var a in data) {\n"
- " if (a == 10) data[10000] = 4;\n"
- " r = r + Number(a);\n"
- " }\n"
- " return r;\n"
- "}",
- 1111},
- {"function f() {\n"
- " var r = 0;\n"
- " var input = 'foobar';\n"
- " for (var a in input) {\n"
- " if (input[a] == 'b') break;\n"
- " r = r + (1 << a);\n"
- " }\n"
- " return r;\n"
- "}",
- 0x7},
- {"function f() {\n"
+ {"var r = 0;\n"
+ "for (var a in [0,6,7,9]) { r = r + (1 << a); }\n"
"var r = 0;\n"
+ "for (var a in [0,6,7,9]) { r = r + (1 << a); }\n"
+ "return r;\n",
+ 0xf},
+ {"var r = 0;\n"
+ "for (var a in 'foobar') { r = r + (1 << a); }\n"
+ "return r;\n",
+ 0x3f},
+ {"var r = 0;\n"
+ "for (var a in {1:0, 10:1, 100:2, 1000:3}) {\n"
+ " r = r + Number(a);\n"
+ " }\n"
+ " return r;\n",
+ 1111},
+ {"var r = 0;\n"
+ "var data = {1:0, 10:1, 100:2, 1000:3};\n"
+ "for (var a in data) {\n"
+ " if (a == 1) delete data[1];\n"
+ " r = r + Number(a);\n"
+ " }\n"
+ " return r;\n",
+ 1111},
+ {"var r = 0;\n"
+ "var data = {1:0, 10:1, 100:2, 1000:3};\n"
+ "for (var a in data) {\n"
+ " if (a == 10) delete data[100];\n"
+ " r = r + Number(a);\n"
+ " }\n"
+ " return r;\n",
+ 1011},
+ {"var r = 0;\n"
+ "var data = {1:0, 10:1, 100:2, 1000:3};\n"
+ "for (var a in data) {\n"
+ " if (a == 10) data[10000] = 4;\n"
+ " r = r + Number(a);\n"
+ " }\n"
+ " return r;\n",
+ 1111},
+ {"var r = 0;\n"
"var input = 'foobar';\n"
"for (var a in input) {\n"
- " if (input[a] == 'b') continue;\n"
- " r = r + (1 << a);\n"
+ " if (input[a] == 'b') break;\n"
+ " r = r + (1 << a);\n"
"}\n"
- "return r;\n"
- "}",
+ "return r;\n",
+ 0x7},
+ {"var r = 0;\n"
+ "var input = 'foobar';\n"
+ "for (var a in input) {\n"
+ " if (input[a] == 'b') continue;\n"
+ " r = r + (1 << a);\n"
+ "}\n"
+ "return r;\n",
0x37},
+ {"var r = 0;\n"
+ "var data = {1:0, 10:1, 100:2, 1000:3};\n"
+ "for (var a in data) {\n"
+ " if (a == 10) {\n"
+ " data[10000] = 4;\n"
+ " }\n"
+ " r = r + Number(a);\n"
+ "}\n"
+ "return r;\n",
+ 1111},
+ {"var r = [ 3 ];\n"
+ "var data = {1:0, 10:1, 100:2, 1000:3};\n"
+ "for (r[10] in data) {\n"
+ "}\n"
+ "return Number(r[10]);\n",
+ 1000},
+ {"var r = [ 3 ];\n"
+ "var data = {1:0, 10:1, 100:2, 1000:3};\n"
+ "for (r['100'] in data) {\n"
+ "}\n"
+ "return Number(r['100']);\n",
+ 1000},
+ {"var obj = {}\n"
+ "var descObj = new Boolean(false);\n"
+ "var accessed = 0;\n"
+ "descObj.enumerable = true;\n"
+ "Object.defineProperties(obj, { prop:descObj });\n"
+ "for (var p in obj) {\n"
+ " if (p === 'prop') { accessed = 1; }\n"
+ "}\n"
+ "return accessed;",
+ 1},
+ {"var appointment = {};\n"
+ "Object.defineProperty(appointment, 'startTime', {\n"
+ " value: 1001,\n"
+ " writable: false,\n"
+ " enumerable: false,\n"
+ " configurable: true\n"
+ "});\n"
+ "Object.defineProperty(appointment, 'name', {\n"
+ " value: 'NAME',\n"
+ " writable: false,\n"
+ " enumerable: false,\n"
+ " configurable: true\n"
+ "});\n"
+ "var meeting = Object.create(appointment);\n"
+ "Object.defineProperty(meeting, 'conferenceCall', {\n"
+ " value: 'In-person meeting',\n"
+ " writable: false,\n"
+ " enumerable: false,\n"
+ " configurable: true\n"
+ "});\n"
+ "\n"
+ "var teamMeeting = Object.create(meeting);\n"
+ "\n"
+ "var flags = 0;\n"
+ "for (var p in teamMeeting) {\n"
+ " if (p === 'startTime') {\n"
+ " flags |= 1;\n"
+ " }\n"
+ " if (p === 'name') {\n"
+ " flags |= 2;\n"
+ " }\n"
+ " if (p === 'conferenceCall') {\n"
+ " flags |= 4;\n"
+ " }\n"
+ "}\n"
+ "\n"
+ "var hasOwnProperty = !teamMeeting.hasOwnProperty('name') &&\n"
+ " !teamMeeting.hasOwnProperty('startTime') &&\n"
+ " !teamMeeting.hasOwnProperty('conferenceCall');\n"
+ "if (!hasOwnProperty) {\n"
+ " flags |= 8;\n"
+ "}\n"
+ "return flags;\n",
+ 0},
+ {"var data = {x:23, y:34};\n"
+ " var result = 0;\n"
+ "var o = {};\n"
+ "var arr = [o];\n"
+ "for (arr[0].p in data)\n" // This is to test if value is loaded
+ " result += data[arr[0].p];\n" // back from accumulator before storing
+ "return result;\n", // named properties.
+ 57},
+ {"var data = {x:23, y:34};\n"
+ "var result = 0;\n"
+ "var o = {};\n"
+ "var i = 0;\n"
+ "for (o[i++] in data)\n" // This is to test if value is loaded
+ " result += data[o[i-1]];\n" // back from accumulator before
+ "return result;\n", // storing keyed properties.
+ 57}};
+
+ // Two passes are made for this test. On the first, 8-bit register
+ // operands are employed, and on the 16-bit register operands are
+ // used.
+ for (int pass = 0; pass < 2; pass++) {
+ HandleAndZoneScope handles;
+ std::ostringstream wide_os;
+ if (pass == 1) {
+ for (int i = 0; i < 200; i++) {
+ wide_os << "var local" << i << " = 0;\n";
+ }
+ }
+
+ for (size_t i = 0; i < arraysize(for_in_samples); i++) {
+ std::ostringstream body_os;
+ body_os << wide_os.str() << for_in_samples[i].first;
+ std::string body(body_os.str());
+ std::string function = InterpreterTester::SourceForBody(body.c_str());
+ InterpreterTester tester(handles.main_isolate(), function.c_str());
+ auto callable = tester.GetCallable<>();
+ Handle<Object> return_val = callable().ToHandleChecked();
+ CHECK_EQ(Handle<Smi>::cast(return_val)->value(),
+ for_in_samples[i].second);
+ }
+ }
+}
+
+
+TEST(InterpreterForOf) {
+ HandleAndZoneScope handles;
+ i::Isolate* isolate = handles.main_isolate();
+ i::Factory* factory = isolate->factory();
+
+ std::pair<const char*, Handle<Object>> for_of[] = {
{"function f() {\n"
" var r = 0;\n"
- " var data = {1:0, 10:1, 100:2, 1000:3};\n"
- " for (var a in data) {\n"
- " if (a == 10) {\n"
- " data[10000] = 4;\n"
- " }\n"
- " r = r + Number(a);\n"
+ " for (var a of [0,6,7,9]) { r += a; }\n"
+ " return r;\n"
+ "}",
+ handle(Smi::FromInt(22), isolate)},
+ {"function f() {\n"
+ " var r = '';\n"
+ " for (var a of 'foobar') { r = a + r; }\n"
+ " return r;\n"
+ "}",
+ factory->NewStringFromStaticChars("raboof")},
+ {"function f() {\n"
+ " var a = [1, 2, 3];\n"
+ " a.name = 4;\n"
+ " var r = 0;\n"
+ " for (var x of a) { r += x; }\n"
+ " return r;\n"
+ "}",
+ handle(Smi::FromInt(6), isolate)},
+ {"function f() {\n"
+ " var r = '';\n"
+ " var data = [1, 2, 3]; \n"
+ " for (a of data) { delete data[0]; r += a; } return r; }",
+ factory->NewStringFromStaticChars("123")},
+ {"function f() {\n"
+ " var r = '';\n"
+ " var data = [1, 2, 3]; \n"
+ " for (a of data) { delete data[2]; r += a; } return r; }",
+ factory->NewStringFromStaticChars("12undefined")},
+ {"function f() {\n"
+ " var r = '';\n"
+ " var data = [1, 2, 3]; \n"
+ " for (a of data) { delete data; r += a; } return r; }",
+ factory->NewStringFromStaticChars("123")},
+ {"function f() {\n"
+ " var r = '';\n"
+ " var input = 'foobar';\n"
+ " for (var a of input) {\n"
+ " if (a == 'b') break;\n"
+ " r += a;\n"
" }\n"
" return r;\n"
"}",
- 1111},
+ factory->NewStringFromStaticChars("foo")},
{"function f() {\n"
- " var r = [ 3 ];\n"
- " var data = {1:0, 10:1, 100:2, 1000:3};\n"
- " for (r[10] in data) {\n"
+ " var r = '';\n"
+ " var input = 'foobar';\n"
+ " for (var a of input) {\n"
+ " if (a == 'b') continue;\n"
+ " r += a;\n"
" }\n"
- " return Number(r[10]);\n"
+ " return r;\n"
"}",
- 1000},
+ factory->NewStringFromStaticChars("fooar")},
{"function f() {\n"
- " var r = [ 3 ];\n"
- " var data = {1:0, 10:1, 100:2, 1000:3};\n"
- " for (r['100'] in data) {\n"
- " }\n"
- " return Number(r['100']);\n"
+ " var r = '';\n"
+ " var data = [1, 2, 3, 4]; \n"
+ " for (a of data) { data[2] = 567; r += a; }\n"
+ " return r;\n"
"}",
- 1000},
+ factory->NewStringFromStaticChars("125674")},
{"function f() {\n"
- " var obj = {}\n"
- " var descObj = new Boolean(false);\n"
- " var accessed = 0;\n"
- " descObj.enumerable = true;\n"
- " Object.defineProperties(obj, { prop:descObj });\n"
- " for (var p in obj) {\n"
- " if (p === 'prop') { accessed = 1; }\n"
- " }\n"
- " return accessed;"
+ " var r = '';\n"
+ " var data = [1, 2, 3, 4]; \n"
+ " for (a of data) { data[4] = 567; r += a; }\n"
+ " return r;\n"
"}",
- 1},
+ factory->NewStringFromStaticChars("1234567")},
{"function f() {\n"
- " var appointment = {};\n"
- " Object.defineProperty(appointment, 'startTime', {\n"
- " value: 1001,\n"
- " writable: false,\n"
- " enumerable: false,\n"
- " configurable: true\n"
- " });\n"
- " Object.defineProperty(appointment, 'name', {\n"
- " value: 'NAME',\n"
- " writable: false,\n"
- " enumerable: false,\n"
- " configurable: true\n"
- " });\n"
- " var meeting = Object.create(appointment);\n"
- " Object.defineProperty(meeting, 'conferenceCall', {\n"
- " value: 'In-person meeting',\n"
- " writable: false,\n"
- " enumerable: false,\n"
- " configurable: true\n"
- " });\n"
- "\n"
- " var teamMeeting = Object.create(meeting);\n"
- "\n"
- " var flags = 0;\n"
- " for (var p in teamMeeting) {\n"
- " if (p === 'startTime') {\n"
- " flags |= 1;\n"
+ " var r = '';\n"
+ " var data = [1, 2, 3, 4]; \n"
+ " for (a of data) { data[5] = 567; r += a; }\n"
+ " return r;\n"
+ "}",
+ factory->NewStringFromStaticChars("1234undefined567")},
+ {"function f() {\n"
+ " var r = '';\n"
+ " var obj = new Object();\n"
+ " obj[Symbol.iterator] = function() { return {\n"
+ " index: 3,\n"
+ " data: ['a', 'b', 'c', 'd'],"
+ " next: function() {"
+ " return {"
+ " done: this.index == -1,\n"
+ " value: this.index < 0 ? undefined : this.data[this.index--]\n"
" }\n"
- " if (p === 'name') {\n"
- " flags |= 2;\n"
- " }\n"
- " if (p === 'conferenceCall') {\n"
- " flags |= 4;\n"
- " }\n"
- " }\n"
- "\n"
- " var hasOwnProperty = !teamMeeting.hasOwnProperty('name') &&\n"
- " !teamMeeting.hasOwnProperty('startTime') &&\n"
- " !teamMeeting.hasOwnProperty('conferenceCall');\n"
- " if (!hasOwnProperty) {\n"
- " flags |= 8;\n"
- " }\n"
- " return flags;\n"
- " }",
- 0},
- {"function f() {\n"
- " var data = {x:23, y:34};\n"
- " var result = 0;\n"
- " var o = {};\n"
- " var arr = [o];\n"
- " for (arr[0].p in data)\n" // This is to test if value is loaded
- " result += data[arr[0].p];\n" // back from accumulator before storing
- " return result;\n" // named properties.
+ " }\n"
+ " }}\n"
+ " for (a of obj) { r += a }\n"
+ " return r;\n"
"}",
- 57},
- {"function f() {\n"
- " var data = {x:23, y:34};\n"
- " var result = 0;\n"
- " var o = {};\n"
- " var i = 0;\n"
- " for (o[i++] in data)\n" // This is to test if value is loaded
- " result += data[o[i-1]];\n" // back from accumulator before
- " return result;\n" // storing keyed properties.
- "}",
- 57}};
+ factory->NewStringFromStaticChars("dcba")},
+ };
- for (size_t i = 0; i < arraysize(for_in_samples); i++) {
- InterpreterTester tester(handles.main_isolate(), for_in_samples[i].first);
+ for (size_t i = 0; i < arraysize(for_of); i++) {
+ InterpreterTester tester(handles.main_isolate(), for_of[i].first);
auto callable = tester.GetCallable<>();
Handle<Object> return_val = callable().ToHandleChecked();
- CHECK_EQ(Handle<Smi>::cast(return_val)->value(), for_in_samples[i].second);
+ CHECK(return_val->SameValue(*for_of[i].second));
}
}
@@ -3422,10 +3383,10 @@
TEST(JumpWithConstantsAndWideConstants) {
HandleAndZoneScope handles;
- auto isolate = handles.main_isolate();
- auto factory = isolate->factory();
const int kStep = 13;
- for (int constants = 3; constants < 256 + 3 * kStep; constants += kStep) {
+ for (int constants = 11; constants < 256 + 3 * kStep; constants += kStep) {
+ auto isolate = handles.main_isolate();
+ auto factory = isolate->factory();
std::ostringstream filler_os;
// Generate a string that consumes constant pool entries and
// spread out branch distances in script below.
@@ -3448,8 +3409,8 @@
for (int a = 0; a < 3; a++) {
InterpreterTester tester(handles.main_isolate(), script.c_str());
auto callable = tester.GetCallable<Handle<Object>>();
- Handle<Object> return_val =
- callable(factory->NewNumberFromInt(a)).ToHandleChecked();
+ Handle<Object> argument = factory->NewNumberFromInt(a);
+ Handle<Object> return_val = callable(argument).ToHandleChecked();
static const int results[] = {11, 12, 2};
CHECK_EQ(Handle<Smi>::cast(return_val)->value(), results[a]);
}
@@ -3500,7 +3461,6 @@
std::string source(InterpreterTester::SourceForBody(eval[i].first));
InterpreterTester tester(handles.main_isolate(), source.c_str());
auto callable = tester.GetCallable<>();
-
Handle<i::Object> return_value = callable().ToHandleChecked();
CHECK(return_value->SameValue(*eval[i].second));
}
@@ -3562,6 +3522,646 @@
}
}
+
+TEST(InterpreterEvalVariableDecl) {
+ HandleAndZoneScope handles;
+ i::Isolate* isolate = handles.main_isolate();
+ i::Factory* factory = isolate->factory();
+
+ std::pair<const char*, Handle<Object>> eval_global[] = {
+ {"function f() { eval('var x = 10; x++;'); return x; }",
+ handle(Smi::FromInt(11), isolate)},
+ {"function f() { var x = 20; eval('var x = 10; x++;'); return x; }",
+ handle(Smi::FromInt(11), isolate)},
+ {"function f() {"
+ " var x = 20;"
+ " eval('\"use strict\"; var x = 10; x++;');"
+ " return x; }",
+ handle(Smi::FromInt(20), isolate)},
+ {"function f() {"
+ " var y = 30;"
+ " eval('var x = {1:20}; x[2]=y;');"
+ " return x[2]; }",
+ handle(Smi::FromInt(30), isolate)},
+ {"function f() {"
+ " eval('var x = {name:\"test\"};');"
+ " return x.name; }",
+ factory->NewStringFromStaticChars("test")},
+ {"function f() {"
+ " eval('var x = [{name:\"test\"}, {type:\"cc\"}];');"
+ " return x[1].type+x[0].name; }",
+ factory->NewStringFromStaticChars("cctest")},
+ {"function f() {\n"
+ " var x = 3;\n"
+ " var get_eval_x;\n"
+ " eval('\"use strict\"; "
+ " var x = 20; "
+ " get_eval_x = function func() {return x;};');\n"
+ " return get_eval_x() + x;\n"
+ "}",
+ handle(Smi::FromInt(23), isolate)},
+ // TODO(mythria): Add tests with const declarations.
+ };
+
+ for (size_t i = 0; i < arraysize(eval_global); i++) {
+ InterpreterTester tester(handles.main_isolate(), eval_global[i].first, "*");
+ auto callable = tester.GetCallable<>();
+
+ Handle<i::Object> return_value = callable().ToHandleChecked();
+ CHECK(return_value->SameValue(*eval_global[i].second));
+ }
+}
+
+
+TEST(InterpreterEvalFunctionDecl) {
+ HandleAndZoneScope handles;
+ i::Isolate* isolate = handles.main_isolate();
+
+ std::pair<const char*, Handle<Object>> eval_func_decl[] = {
+ {"function f() {\n"
+ " var x = 3;\n"
+ " eval('var x = 20;"
+ " function get_x() {return x;};');\n"
+ " return get_x() + x;\n"
+ "}",
+ handle(Smi::FromInt(40), isolate)},
+ };
+
+ for (size_t i = 0; i < arraysize(eval_func_decl); i++) {
+ InterpreterTester tester(handles.main_isolate(), eval_func_decl[i].first,
+ "*");
+ auto callable = tester.GetCallable<>();
+
+ Handle<i::Object> return_value = callable().ToHandleChecked();
+ CHECK(return_value->SameValue(*eval_func_decl[i].second));
+ }
+}
+
+TEST(InterpreterWideRegisterArithmetic) {
+ HandleAndZoneScope handles;
+ i::Isolate* isolate = handles.main_isolate();
+
+ static const size_t kMaxRegisterForTest = 150;
+ std::ostringstream os;
+ os << "function " << InterpreterTester::function_name() << "(arg) {\n";
+ os << " var retval = -77;\n";
+ for (size_t i = 0; i < kMaxRegisterForTest; i++) {
+ os << " var x" << i << " = " << i << ";\n";
+ }
+ for (size_t i = 0; i < kMaxRegisterForTest / 2; i++) {
+ size_t j = kMaxRegisterForTest - i - 1;
+ os << " var tmp = x" << j << ";\n";
+ os << " var x" << j << " = x" << i << ";\n";
+ os << " var x" << i << " = tmp;\n";
+ }
+ for (size_t i = 0; i < kMaxRegisterForTest / 2; i++) {
+ size_t j = kMaxRegisterForTest - i - 1;
+ os << " var tmp = x" << j << ";\n";
+ os << " var x" << j << " = x" << i << ";\n";
+ os << " var x" << i << " = tmp;\n";
+ }
+ for (size_t i = 0; i < kMaxRegisterForTest; i++) {
+ os << " if (arg == " << i << ") {\n" //
+ << " retval = x" << i << ";\n" //
+ << " }\n"; //
+ }
+ os << " return retval;\n";
+ os << "}\n";
+
+ std::string source = os.str();
+ InterpreterTester tester(handles.main_isolate(), source.c_str());
+ auto callable = tester.GetCallable<Handle<Object>>();
+ for (size_t i = 0; i < kMaxRegisterForTest; i++) {
+ Handle<Object> arg = handle(Smi::FromInt(static_cast<int>(i)), isolate);
+ Handle<Object> return_value = callable(arg).ToHandleChecked();
+ CHECK(return_value->SameValue(*arg));
+ }
+}
+
+TEST(InterpreterCallWideRegisters) {
+ static const int kPeriod = 25;
+ static const int kLength = 512;
+ static const int kStartChar = 65;
+
+ for (int pass = 0; pass < 3; pass += 1) {
+ std::ostringstream os;
+ for (int i = 0; i < pass * 97; i += 1) {
+ os << "var x" << i << " = " << i << "\n";
+ }
+ os << "return String.fromCharCode(";
+ os << kStartChar;
+ for (int i = 1; i < kLength; i += 1) {
+ os << "," << kStartChar + (i % kPeriod);
+ }
+ os << ");";
+ std::string source = InterpreterTester::SourceForBody(os.str().c_str());
+ HandleAndZoneScope handles;
+ InterpreterTester tester(handles.main_isolate(), source.c_str());
+ auto callable = tester.GetCallable();
+ Handle<Object> return_val = callable().ToHandleChecked();
+ Handle<String> return_string = Handle<String>::cast(return_val);
+ CHECK_EQ(return_string->length(), kLength);
+ for (int i = 0; i < kLength; i += 1) {
+ CHECK_EQ(return_string->Get(i), 65 + (i % kPeriod));
+ }
+ }
+}
+
+TEST(InterpreterWideParametersPickOne) {
+ static const int kParameterCount = 130;
+ for (int parameter = 0; parameter < 10; parameter++) {
+ HandleAndZoneScope handles;
+ i::Isolate* isolate = handles.main_isolate();
+ std::ostringstream os;
+ os << "function " << InterpreterTester::function_name() << "(arg) {\n";
+ os << " function selector(i";
+ for (int i = 0; i < kParameterCount; i++) {
+ os << ","
+ << "a" << i;
+ }
+ os << ") {\n";
+ os << " return a" << parameter << ";\n";
+ os << " };\n";
+ os << " return selector(arg";
+ for (int i = 0; i < kParameterCount; i++) {
+ os << "," << i;
+ }
+ os << ");";
+ os << "}\n";
+
+ std::string source = os.str();
+ InterpreterTester tester(handles.main_isolate(), source.c_str(), "*");
+ auto callable = tester.GetCallable<Handle<Object>>();
+ Handle<Object> arg = handle(Smi::FromInt(0xaa55), isolate);
+ Handle<Object> return_value = callable(arg).ToHandleChecked();
+ Handle<Smi> actual = Handle<Smi>::cast(return_value);
+ CHECK_EQ(actual->value(), parameter);
+ }
+}
+
+TEST(InterpreterWideParametersSummation) {
+ static int kParameterCount = 200;
+ static int kBaseValue = 17000;
+ HandleAndZoneScope handles;
+ i::Isolate* isolate = handles.main_isolate();
+ std::ostringstream os;
+ os << "function " << InterpreterTester::function_name() << "(arg) {\n";
+ os << " function summation(i";
+ for (int i = 0; i < kParameterCount; i++) {
+ os << ","
+ << "a" << i;
+ }
+ os << ") {\n";
+ os << " var sum = " << kBaseValue << ";\n";
+ os << " switch(i) {\n";
+ for (int i = 0; i < kParameterCount; i++) {
+ int j = kParameterCount - i - 1;
+ os << " case " << j << ": sum += a" << j << ";\n";
+ }
+ os << " }\n";
+ os << " return sum;\n";
+ os << " };\n";
+ os << " return summation(arg";
+ for (int i = 0; i < kParameterCount; i++) {
+ os << "," << i;
+ }
+ os << ");";
+ os << "}\n";
+
+ std::string source = os.str();
+ InterpreterTester tester(handles.main_isolate(), source.c_str(), "*");
+ auto callable = tester.GetCallable<Handle<Object>>();
+ for (int i = 0; i < kParameterCount; i++) {
+ Handle<Object> arg = handle(Smi::FromInt(i), isolate);
+ Handle<Object> return_value = callable(arg).ToHandleChecked();
+ int expected = kBaseValue + i * (i + 1) / 2;
+ Handle<Smi> actual = Handle<Smi>::cast(return_value);
+ CHECK_EQ(actual->value(), expected);
+ }
+}
+
+TEST(InterpreterDoExpression) {
+ bool old_flag = FLAG_harmony_do_expressions;
+ FLAG_harmony_do_expressions = true;
+
+ HandleAndZoneScope handles;
+ i::Isolate* isolate = handles.main_isolate();
+ Factory* factory = isolate->factory();
+
+ std::pair<const char*, Handle<Object>> do_expr[] = {
+ {"var a = do {}; return a;", factory->undefined_value()},
+ {"var a = do { var x = 100; }; return a;", factory->undefined_value()},
+ {"var a = do { var x = 100; }; return a;", factory->undefined_value()},
+ {"var a = do { var x = 100; x++; }; return a;",
+ handle(Smi::FromInt(100), isolate)},
+ {"var i = 0; for (; i < 5;) { i = do { if (i == 3) { break; }; i + 1; }};"
+ "return i;",
+ handle(Smi::FromInt(3), isolate)},
+ };
+
+ for (size_t i = 0; i < arraysize(do_expr); i++) {
+ std::string source(InterpreterTester::SourceForBody(do_expr[i].first));
+ InterpreterTester tester(handles.main_isolate(), source.c_str());
+ auto callable = tester.GetCallable<>();
+
+ Handle<i::Object> return_value = callable().ToHandleChecked();
+ CHECK(return_value->SameValue(*do_expr[i].second));
+ }
+
+ FLAG_harmony_do_expressions = old_flag;
+}
+
+TEST(InterpreterWithStatement) {
+ HandleAndZoneScope handles;
+ i::Isolate* isolate = handles.main_isolate();
+
+ std::pair<const char*, Handle<Object>> with_stmt[] = {
+ {"with({x:42}) return x;", handle(Smi::FromInt(42), isolate)},
+ {"with({}) { var y = 10; return y;}", handle(Smi::FromInt(10), isolate)},
+ {"var y = {x:42};"
+ " function inner() {"
+ " var x = 20;"
+ " with(y) return x;"
+ "}"
+ "return inner();",
+ handle(Smi::FromInt(42), isolate)},
+ {"var y = {x:42};"
+ " function inner(o) {"
+ " var x = 20;"
+ " with(o) return x;"
+ "}"
+ "return inner(y);",
+ handle(Smi::FromInt(42), isolate)},
+ };
+
+ for (size_t i = 0; i < arraysize(with_stmt); i++) {
+ std::string source(InterpreterTester::SourceForBody(with_stmt[i].first));
+ InterpreterTester tester(handles.main_isolate(), source.c_str());
+ auto callable = tester.GetCallable<>();
+
+ Handle<i::Object> return_value = callable().ToHandleChecked();
+ CHECK(return_value->SameValue(*with_stmt[i].second));
+ }
+}
+
+TEST(InterpreterClassLiterals) {
+ HandleAndZoneScope handles;
+ i::Isolate* isolate = handles.main_isolate();
+ std::pair<const char*, Handle<Object>> examples[] = {
+ {"class C {\n"
+ " constructor(x) { this.x_ = x; }\n"
+ " method() { return this.x_; }\n"
+ "}\n"
+ "return new C(99).method();",
+ handle(Smi::FromInt(99), isolate)},
+ {"class C {\n"
+ " constructor(x) { this.x_ = x; }\n"
+ " static static_method(x) { return x; }\n"
+ "}\n"
+ "return C.static_method(101);",
+ handle(Smi::FromInt(101), isolate)},
+ {"class C {\n"
+ " get x() { return 102; }\n"
+ "}\n"
+ "return new C().x",
+ handle(Smi::FromInt(102), isolate)},
+ {"class C {\n"
+ " static get x() { return 103; }\n"
+ "}\n"
+ "return C.x",
+ handle(Smi::FromInt(103), isolate)},
+ {"class C {\n"
+ " constructor() { this.x_ = 0; }"
+ " set x(value) { this.x_ = value; }\n"
+ " get x() { return this.x_; }\n"
+ "}\n"
+ "var c = new C();"
+ "c.x = 104;"
+ "return c.x;",
+ handle(Smi::FromInt(104), isolate)},
+ {"var x = 0;"
+ "class C {\n"
+ " static set x(value) { x = value; }\n"
+ " static get x() { return x; }\n"
+ "}\n"
+ "C.x = 105;"
+ "return C.x;",
+ handle(Smi::FromInt(105), isolate)},
+ {"var method = 'f';"
+ "class C {\n"
+ " [method]() { return 106; }\n"
+ "}\n"
+ "return new C().f();",
+ handle(Smi::FromInt(106), isolate)},
+ };
+
+ for (size_t i = 0; i < arraysize(examples); ++i) {
+ std::string source(InterpreterTester::SourceForBody(examples[i].first));
+ InterpreterTester tester(handles.main_isolate(), source.c_str());
+ auto callable = tester.GetCallable<>();
+
+ Handle<i::Object> return_value = callable().ToHandleChecked();
+ CHECK(return_value->SameValue(*examples[i].second));
+ }
+}
+
+TEST(InterpreterClassAndSuperClass) {
+ HandleAndZoneScope handles;
+ i::Isolate* isolate = handles.main_isolate();
+ std::pair<const char*, Handle<Object>> examples[] = {
+ {"class A {\n"
+ " constructor(x) { this.x_ = x; }\n"
+ " method() { return this.x_; }\n"
+ "}\n"
+ "class B extends A {\n"
+ " constructor(x, y) { super(x); this.y_ = y; }\n"
+ " method() { return super.method() + 1; }\n"
+ "}\n"
+ "return new B(998, 0).method();\n",
+ handle(Smi::FromInt(999), isolate)},
+ {"class A {\n"
+ " constructor() { this.x_ = 2; this.y_ = 3; }\n"
+ "}\n"
+ "class B extends A {\n"
+ " constructor() { super(); }"
+ " method() { this.x_++; this.y_++; return this.x_ + this.y_; }\n"
+ "}\n"
+ "return new B().method();\n",
+ handle(Smi::FromInt(7), isolate)},
+ {"var calls = 0;\n"
+ "class B {}\n"
+ "B.prototype.x = 42;\n"
+ "class C extends B {\n"
+ " constructor() {\n"
+ " super();\n"
+ " calls++;\n"
+ " }\n"
+ "}\n"
+ "new C;\n"
+ "return calls;\n",
+ handle(Smi::FromInt(1), isolate)},
+ {"class A {\n"
+ " method() { return 1; }\n"
+ " get x() { return 2; }\n"
+ "}\n"
+ "class B extends A {\n"
+ " method() { return super.x === 2 ? super.method() : -1; }\n"
+ "}\n"
+ "return new B().method();\n",
+ handle(Smi::FromInt(1), isolate)},
+ {"var object = { setY(v) { super.y = v; }};\n"
+ "object.setY(10);\n"
+ "return object.y;\n",
+ handle(Smi::FromInt(10), isolate)},
+ };
+
+ for (size_t i = 0; i < arraysize(examples); ++i) {
+ std::string source(InterpreterTester::SourceForBody(examples[i].first));
+ InterpreterTester tester(handles.main_isolate(), source.c_str());
+ auto callable = tester.GetCallable<>();
+ Handle<i::Object> return_value = callable().ToHandleChecked();
+ CHECK(return_value->SameValue(*examples[i].second));
+ }
+}
+
+TEST(InterpreterConstDeclaration) {
+ HandleAndZoneScope handles;
+ i::Isolate* isolate = handles.main_isolate();
+ i::Factory* factory = isolate->factory();
+
+ std::pair<const char*, Handle<Object>> const_decl[] = {
+ {"const x = 3; return x;", handle(Smi::FromInt(3), isolate)},
+ {"let x = 10; x = x + 20; return x;", handle(Smi::FromInt(30), isolate)},
+ {"let x = 10; x = 20; return x;", handle(Smi::FromInt(20), isolate)},
+ {"let x; x = 20; return x;", handle(Smi::FromInt(20), isolate)},
+ {"let x; return x;", factory->undefined_value()},
+ {"var x = 10; { let x = 30; } return x;",
+ handle(Smi::FromInt(10), isolate)},
+ {"let x = 10; { let x = 20; } return x;",
+ handle(Smi::FromInt(10), isolate)},
+ {"var x = 10; eval('let x = 20;'); return x;",
+ handle(Smi::FromInt(10), isolate)},
+ {"var x = 10; eval('const x = 20;'); return x;",
+ handle(Smi::FromInt(10), isolate)},
+ {"var x = 10; { const x = 20; } return x;",
+ handle(Smi::FromInt(10), isolate)},
+ {"var x = 10; { const x = 20; return x;} return -1;",
+ handle(Smi::FromInt(20), isolate)},
+ {"var a = 10;\n"
+ "for (var i = 0; i < 10; ++i) {\n"
+ " const x = i;\n" // const declarations are block scoped.
+ " a = a + x;\n"
+ "}\n"
+ "return a;\n",
+ handle(Smi::FromInt(55), isolate)},
+ };
+
+ // Tests for sloppy mode.
+ for (size_t i = 0; i < arraysize(const_decl); i++) {
+ std::string source(InterpreterTester::SourceForBody(const_decl[i].first));
+ InterpreterTester tester(handles.main_isolate(), source.c_str());
+ auto callable = tester.GetCallable<>();
+
+ Handle<i::Object> return_value = callable().ToHandleChecked();
+ CHECK(return_value->SameValue(*const_decl[i].second));
+ }
+
+ // Tests for strict mode.
+ for (size_t i = 0; i < arraysize(const_decl); i++) {
+ std::string strict_body =
+ "'use strict'; " + std::string(const_decl[i].first);
+ std::string source(InterpreterTester::SourceForBody(strict_body.c_str()));
+ InterpreterTester tester(handles.main_isolate(), source.c_str());
+ auto callable = tester.GetCallable<>();
+
+ Handle<i::Object> return_value = callable().ToHandleChecked();
+ CHECK(return_value->SameValue(*const_decl[i].second));
+ }
+}
+
+TEST(InterpreterConstDeclarationLookupSlots) {
+ HandleAndZoneScope handles;
+ i::Isolate* isolate = handles.main_isolate();
+ i::Factory* factory = isolate->factory();
+
+ std::pair<const char*, Handle<Object>> const_decl[] = {
+ {"const x = 3; function f1() {return x;}; return x;",
+ handle(Smi::FromInt(3), isolate)},
+ {"let x = 10; x = x + 20; function f1() {return x;}; return x;",
+ handle(Smi::FromInt(30), isolate)},
+ {"let x; x = 20; function f1() {return x;}; return x;",
+ handle(Smi::FromInt(20), isolate)},
+ {"let x; function f1() {return x;}; return x;",
+ factory->undefined_value()},
+ };
+
+ // Tests for sloppy mode.
+ for (size_t i = 0; i < arraysize(const_decl); i++) {
+ std::string source(InterpreterTester::SourceForBody(const_decl[i].first));
+ InterpreterTester tester(handles.main_isolate(), source.c_str());
+ auto callable = tester.GetCallable<>();
+
+ Handle<i::Object> return_value = callable().ToHandleChecked();
+ CHECK(return_value->SameValue(*const_decl[i].second));
+ }
+
+ // Tests for strict mode.
+ for (size_t i = 0; i < arraysize(const_decl); i++) {
+ std::string strict_body =
+ "'use strict'; " + std::string(const_decl[i].first);
+ std::string source(InterpreterTester::SourceForBody(strict_body.c_str()));
+ InterpreterTester tester(handles.main_isolate(), source.c_str());
+ auto callable = tester.GetCallable<>();
+
+ Handle<i::Object> return_value = callable().ToHandleChecked();
+ CHECK(return_value->SameValue(*const_decl[i].second));
+ }
+}
+
+TEST(InterpreterConstInLookupContextChain) {
+ HandleAndZoneScope handles;
+ i::Isolate* isolate = handles.main_isolate();
+
+ const char* prologue =
+ "function OuterMost() {\n"
+ " const outerConst = 10;\n"
+ " let outerLet = 20;\n"
+ " function Outer() {\n"
+ " function Inner() {\n"
+ " this.innerFunc = function() { ";
+ const char* epilogue =
+ " }\n"
+ " }\n"
+ " this.getInnerFunc ="
+ " function() {return new Inner().innerFunc;}\n"
+ " }\n"
+ " this.getOuterFunc ="
+ " function() {return new Outer().getInnerFunc();}"
+ "}\n"
+ "var f = new OuterMost().getOuterFunc();\n"
+ "f();\n";
+ std::pair<const char*, Handle<Object>> const_decl[] = {
+ {"return outerConst;", handle(Smi::FromInt(10), isolate)},
+ {"return outerLet;", handle(Smi::FromInt(20), isolate)},
+ {"outerLet = 30; return outerLet;", handle(Smi::FromInt(30), isolate)},
+ {"var outerLet = 40; return outerLet;",
+ handle(Smi::FromInt(40), isolate)},
+ {"var outerConst = 50; return outerConst;",
+ handle(Smi::FromInt(50), isolate)},
+ {"try { outerConst = 30 } catch(e) { return -1; }",
+ handle(Smi::FromInt(-1), isolate)}};
+
+ for (size_t i = 0; i < arraysize(const_decl); i++) {
+ std::string script = std::string(prologue) +
+ std::string(const_decl[i].first) +
+ std::string(epilogue);
+ InterpreterTester tester(handles.main_isolate(), script.c_str(), "*");
+ auto callable = tester.GetCallable<>();
+
+ Handle<i::Object> return_value = callable().ToHandleChecked();
+ CHECK(return_value->SameValue(*const_decl[i].second));
+ }
+
+ // Tests for Legacy constant.
+ bool old_flag_legacy_const = FLAG_legacy_const;
+ FLAG_legacy_const = true;
+
+ std::pair<const char*, Handle<Object>> legacy_const_decl[] = {
+ {"return outerConst = 23;", handle(Smi::FromInt(23), isolate)},
+ {"outerConst = 30; return outerConst;",
+ handle(Smi::FromInt(10), isolate)},
+ };
+
+ for (size_t i = 0; i < arraysize(legacy_const_decl); i++) {
+ std::string script = std::string(prologue) +
+ std::string(legacy_const_decl[i].first) +
+ std::string(epilogue);
+ InterpreterTester tester(handles.main_isolate(), script.c_str(), "*");
+ auto callable = tester.GetCallable<>();
+
+ Handle<i::Object> return_value = callable().ToHandleChecked();
+ CHECK(return_value->SameValue(*legacy_const_decl[i].second));
+ }
+
+ FLAG_legacy_const = old_flag_legacy_const;
+}
+
+TEST(InterpreterIllegalConstDeclaration) {
+ HandleAndZoneScope handles;
+
+ std::pair<const char*, const char*> const_decl[] = {
+ {"const x = x = 10 + 3; return x;",
+ "Uncaught ReferenceError: x is not defined"},
+ {"const x = 10; x = 20; return x;",
+ "Uncaught TypeError: Assignment to constant variable."},
+ {"const x = 10; { x = 20; } return x;",
+ "Uncaught TypeError: Assignment to constant variable."},
+ {"const x = 10; eval('x = 20;'); return x;",
+ "Uncaught TypeError: Assignment to constant variable."},
+ {"let x = x + 10; return x;",
+ "Uncaught ReferenceError: x is not defined"},
+ {"'use strict'; (function f1() { f1 = 123; })() ",
+ "Uncaught TypeError: Assignment to constant variable."},
+ };
+
+ // Tests for sloppy mode.
+ for (size_t i = 0; i < arraysize(const_decl); i++) {
+ std::string source(InterpreterTester::SourceForBody(const_decl[i].first));
+ InterpreterTester tester(handles.main_isolate(), source.c_str());
+ v8::Local<v8::String> message = tester.CheckThrowsReturnMessage()->Get();
+ v8::Local<v8::String> expected_string = v8_str(const_decl[i].second);
+ CHECK(
+ message->Equals(CcTest::isolate()->GetCurrentContext(), expected_string)
+ .FromJust());
+ }
+
+ // Tests for strict mode.
+ for (size_t i = 0; i < arraysize(const_decl); i++) {
+ std::string strict_body =
+ "'use strict'; " + std::string(const_decl[i].first);
+ std::string source(InterpreterTester::SourceForBody(strict_body.c_str()));
+ InterpreterTester tester(handles.main_isolate(), source.c_str());
+ v8::Local<v8::String> message = tester.CheckThrowsReturnMessage()->Get();
+ v8::Local<v8::String> expected_string = v8_str(const_decl[i].second);
+ CHECK(
+ message->Equals(CcTest::isolate()->GetCurrentContext(), expected_string)
+ .FromJust());
+ }
+}
+
+TEST(InterpreterLegacyConstDeclaration) {
+ bool old_flag_legacy_const = FLAG_legacy_const;
+ FLAG_legacy_const = true;
+
+ HandleAndZoneScope handles;
+ i::Isolate* isolate = handles.main_isolate();
+
+ std::pair<const char*, Handle<Object>> const_decl[] = {
+ {"const x = (x = 10) + 3; return x;", handle(Smi::FromInt(13), isolate)},
+ {"const x = 10; x = 20; return x;", handle(Smi::FromInt(10), isolate)},
+ {"var a = 10;\n"
+ "for (var i = 0; i < 10; ++i) {\n"
+ " const x = i;\n" // Legacy constants are not block scoped.
+ " a = a + x;\n"
+ "}\n"
+ "return a;\n",
+ handle(Smi::FromInt(10), isolate)},
+ {"const x = 20; eval('x = 10;'); return x;",
+ handle(Smi::FromInt(20), isolate)},
+ };
+
+ for (size_t i = 0; i < arraysize(const_decl); i++) {
+ std::string source(InterpreterTester::SourceForBody(const_decl[i].first));
+ InterpreterTester tester(handles.main_isolate(), source.c_str());
+ auto callable = tester.GetCallable<>();
+
+ Handle<i::Object> return_value = callable().ToHandleChecked();
+ CHECK(return_value->SameValue(*const_decl[i].second));
+ }
+
+ FLAG_legacy_const = old_flag_legacy_const;
+}
+
} // namespace interpreter
} // namespace internal
} // namespace v8