Commit c5528ac1 authored by rmcilroy's avatar rmcilroy Committed by Commit bot

[Interpreter] Support top-level code.

Adds support for compiling top level code to bytecode to be run in the
interpreter.

Also moves PassesFilter to String:: so that it can be used to filter top
level script names as well as functions (used in
https://codereview.chromium.org/1379093002/)

BUG=v8:4280
LOG=N

Review URL: https://codereview.chromium.org/1372293005

Cr-Commit-Position: refs/heads/master@{#31142}
parent 911384af
......@@ -749,6 +749,10 @@ MUST_USE_RESULT static MaybeHandle<Code> GetUnoptimizedCodeCommon(
// Update the code and feedback vector for the shared function info.
shared->ReplaceCode(*info->code());
shared->set_feedback_vector(*info->feedback_vector());
if (info->has_bytecode_array()) {
DCHECK(shared->function_data()->IsUndefined());
shared->set_function_data(*info->bytecode_array());
}
return info->code();
}
......@@ -1209,9 +1213,20 @@ static Handle<SharedFunctionInfo> CompileToplevel(CompilationInfo* info) {
: info->isolate()->counters()->compile();
HistogramTimerScope timer(rate);
Handle<String> script_name =
script->name()->IsString()
? Handle<String>(String::cast(script->name()))
: isolate->factory()->empty_string();
// Compile the code.
if (!CompileUnoptimizedCode(info)) {
return Handle<SharedFunctionInfo>::null();
if (FLAG_ignition && script_name->PassesFilter(FLAG_ignition_filter)) {
if (!GenerateBytecode(info)) {
return Handle<SharedFunctionInfo>::null();
}
} else {
if (!CompileUnoptimizedCode(info)) {
return Handle<SharedFunctionInfo>::null();
}
}
// Allocate function.
......@@ -1221,6 +1236,10 @@ static Handle<SharedFunctionInfo> CompileToplevel(CompilationInfo* info) {
info->code(),
ScopeInfo::Create(info->isolate(), info->zone(), info->scope()),
info->feedback_vector());
if (info->has_bytecode_array()) {
DCHECK(result->function_data()->IsUndefined());
result->set_function_data(*info->bytecode_array());
}
DCHECK_EQ(RelocInfo::kNoPosition, lit->function_token_position());
SharedFunctionInfo::InitFromFunctionLiteral(result, lit);
......@@ -1231,9 +1250,6 @@ static Handle<SharedFunctionInfo> CompileToplevel(CompilationInfo* info) {
result->set_allows_lazy_compilation_without_context(false);
}
Handle<String> script_name = script->name()->IsString()
? Handle<String>(String::cast(script->name()))
: isolate->factory()->empty_string();
Logger::LogEventsAndTags log_tag = info->is_eval()
? Logger::EVAL_TAG
: Logger::ToNativeByScript(Logger::SCRIPT_TAG, *script);
......
......@@ -174,6 +174,9 @@ class CompilationInfo {
parameter_count_ = parameter_count;
}
bool has_bytecode_array() const { return !bytecode_array_.is_null(); }
Handle<BytecodeArray> bytecode_array() const { return bytecode_array_; }
bool is_tracking_positions() const { return track_positions_; }
bool is_calling() const {
......@@ -283,6 +286,10 @@ class CompilationInfo {
}
void SetCode(Handle<Code> code) { code_ = code; }
void SetBytecodeArray(Handle<BytecodeArray> bytecode_array) {
bytecode_array_ = bytecode_array;
}
bool ShouldTrapOnDeopt() const {
return (FLAG_trap_on_deopt && IsOptimizing()) ||
(FLAG_trap_on_stub_deopt && IsStub());
......@@ -468,6 +475,11 @@ class CompilationInfo {
// data. Keep track which code we patched.
Handle<Code> unoptimized_code_;
// Holds the bytecode array generated by the interpreter.
// TODO(rmcilroy/mstarzinger): Temporary work-around until compiler.cc is
// refactored to avoid us needing to carry the BytcodeArray around.
Handle<BytecodeArray> bytecode_array_;
// The zone from which the compilation pipeline working on this
// CompilationInfo allocates.
Zone* zone_;
......
......@@ -105,9 +105,6 @@ Handle<BytecodeArray> BytecodeGenerator::MakeBytecode(CompilationInfo* info) {
set_info(info);
set_scope(info->scope());
// This a temporary guard (oth).
DCHECK(scope()->is_function_scope());
builder()->set_parameter_count(info->num_parameters_including_this());
builder()->set_locals_count(scope()->num_stack_slots());
......
......@@ -59,8 +59,6 @@ void Interpreter::Initialize() {
bool Interpreter::MakeBytecode(CompilationInfo* info) {
Handle<SharedFunctionInfo> shared_info = info->shared_info();
BytecodeGenerator generator(info->isolate(), info->zone());
info->EnsureFeedbackVector();
Handle<BytecodeArray> bytecodes = generator.MakeBytecode(info);
......@@ -68,12 +66,7 @@ bool Interpreter::MakeBytecode(CompilationInfo* info) {
bytecodes->Print();
}
DCHECK(shared_info->function_data()->IsUndefined());
if (!shared_info->function_data()->IsUndefined()) {
return false;
}
shared_info->set_function_data(*bytecodes);
info->SetBytecodeArray(bytecodes);
info->SetCode(info->isolate()->builtins()->InterpreterEntryTrampoline());
return true;
}
......
......@@ -1552,6 +1552,41 @@ void String::PrintUC16(std::ostream& os, int start, int end) { // NOLINT
}
// The filter is a pattern that matches string names in this way:
// "*" all; the default
// "-name" all but "name"
// "name" only the function "name"
// "name*" only functions starting with "name"
// "~" none; the tilde is not an identifier
bool String::PassesFilter(const char* raw_filter) {
if (*raw_filter == '*') return true;
Vector<const char> filter = CStrVector(raw_filter);
if (filter.length() == 0) return length() == 0;
if (filter[0] == '-') {
// Negative filter.
if (filter.length() == 1) {
return (length() != 0);
} else if (IsUtf8EqualTo(filter.SubVector(1, filter.length()))) {
return false;
}
if (filter[filter.length() - 1] == '*' &&
IsUtf8EqualTo(filter.SubVector(1, filter.length() - 1), true)) {
return false;
}
return true;
} else if (IsUtf8EqualTo(filter)) {
return true;
}
if (filter[filter.length() - 1] == '*' &&
IsUtf8EqualTo(filter.SubVector(0, filter.length() - 1), true)) {
return true;
}
return false;
}
void JSObject::JSObjectShortPrint(StringStream* accumulator) {
switch (map()->instance_type()) {
case JS_ARRAY_TYPE: {
......@@ -10972,31 +11007,8 @@ void JSFunction::PrintName(FILE* out) {
// "name*" only functions starting with "name"
// "~" none; the tilde is not an identifier
bool JSFunction::PassesFilter(const char* raw_filter) {
if (*raw_filter == '*') return true;
String* name = shared()->DebugName();
Vector<const char> filter = CStrVector(raw_filter);
if (filter.length() == 0) return name->length() == 0;
if (filter[0] == '-') {
// Negative filter.
if (filter.length() == 1) {
return (name->length() != 0);
} else if (name->IsUtf8EqualTo(filter.SubVector(1, filter.length()))) {
return false;
}
if (filter[filter.length() - 1] == '*' &&
name->IsUtf8EqualTo(filter.SubVector(1, filter.length() - 1), true)) {
return false;
}
return true;
} else if (name->IsUtf8EqualTo(filter)) {
return true;
}
if (filter[filter.length() - 1] == '*' &&
name->IsUtf8EqualTo(filter.SubVector(0, filter.length() - 1), true)) {
return true;
}
return false;
return name->PassesFilter(raw_filter);
}
......
......@@ -7287,6 +7287,8 @@ class JSFunction: public JSObject {
inline int NumberOfLiterals();
// Used for flags such as --hydrogen-filter.
// TODO(rmcilroy/mstarzinger): Move this back to JSFunction when compiler.cc
// is refactored to allow use of JSFunction::PassesFilter for top-level code.
bool PassesFilter(const char* raw_filter);
// The function's name if it is configured, otherwise shared function info
......@@ -8689,6 +8691,9 @@ class String: public Name {
// For use during stack traces. Performs rudimentary sanity check.
bool LooksValid();
// Used for flags such as --hydrogen-filter.
bool PassesFilter(const char* raw_filter);
// Dispatched behavior.
void StringShortPrint(StringStream* accumulator);
void PrintUC16(std::ostream& os, int start = 0, int end = -1); // NOLINT
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment