From 5dc02ef2b81313572a5b8be74e6917ed33f7d38b Mon Sep 17 00:00:00 2001 From: Ross McIlroy Date: Fri, 3 Nov 2017 23:45:32 +0000 Subject: [PATCH] Revert "[Ast] Teach Ast Printer to print raw literal values." This reverts commit c60934e9e4c3d3f1528c8b6cef3b78d8a5e363ec. Reason for revert: breaks nosnap build Original change's description: > [Ast] Teach Ast Printer to print raw literal values. > > Converts the ast prettyprinter to printing literals from the raw values > rather than internalized on-heap strings. This enables ast printing before > internalizing, and means we can avoid use of the isolate in the interpreter's > off-thread phase. > > Also removes --print-builtin-ast and relies on just --print-ast to print > everything. > > Finally, converts FunctionLiteral's debug_name function to return a > char[] which is created from the raw name literal where it exists, rather > than relying on the value having been internalized. > > BUG=v8:5203 > > Change-Id: I0e358d6acc9ae4516ed49e7a763e208fea5fcf66 > Reviewed-on: https://chromium-review.googlesource.com/749261 > Commit-Queue: Ross McIlroy > Reviewed-by: Adam Klein > Cr-Commit-Position: refs/heads/master@{#49119} TBR=rmcilroy@chromium.org,adamk@chromium.org Change-Id: Ic9d511f5107666a2f6a2bf59d8e93643c32d4d2b No-Presubmit: true No-Tree-Checks: true No-Try: true Bug: v8:5203 Reviewed-on: https://chromium-review.googlesource.com/753627 Reviewed-by: Ross McIlroy Commit-Queue: Ross McIlroy Cr-Commit-Position: refs/heads/master@{#49120} --- src/ast/ast-value-factory.cc | 14 --- src/ast/ast-value-factory.h | 4 - src/ast/ast.cc | 29 ------ src/ast/ast.h | 13 ++- src/ast/prettyprinter.cc | 185 +++++++++++++++------------------ src/ast/prettyprinter.h | 16 ++- src/compilation-info.cc | 3 +- src/flag-definitions.h | 1 + src/interpreter/interpreter.cc | 18 +++- src/parsing/parser.cc | 2 +- 10 files changed, 117 insertions(+), 168 deletions(-) diff --git a/src/ast/ast-value-factory.cc b/src/ast/ast-value-factory.cc index 458afb8bc1..9742af0296 100644 --- a/src/ast/ast-value-factory.cc +++ b/src/ast/ast-value-factory.cc @@ -168,20 +168,6 @@ void AstConsString::Internalize(Isolate* isolate) { set_string(tmp); } -std::forward_list AstConsString::ToRawStrings() const { - std::forward_list result; - if (IsEmpty()) { - return result; - } - - result.emplace_front(segment_.string); - for (AstConsString::Segment* current = segment_.next; current != nullptr; - current = current->next) { - result.emplace_front(current->string); - } - return result; -} - AstStringConstants::AstStringConstants(Isolate* isolate, uint32_t hash_seed) : zone_(isolate->allocator(), ZONE_NAME), string_table_(AstRawString::Compare), diff --git a/src/ast/ast-value-factory.h b/src/ast/ast-value-factory.h index f99eb194a8..3e4300503a 100644 --- a/src/ast/ast-value-factory.h +++ b/src/ast/ast-value-factory.h @@ -28,8 +28,6 @@ #ifndef V8_AST_AST_VALUE_FACTORY_H_ #define V8_AST_AST_VALUE_FACTORY_H_ -#include - #include "src/base/hashmap.h" #include "src/conversions.h" #include "src/factory.h" @@ -153,8 +151,6 @@ class AstConsString final : public ZoneObject { return Handle(string_); } - std::forward_list ToRawStrings() const; - private: friend class AstValueFactory; diff --git a/src/ast/ast.cc b/src/ast/ast.cc index 929034df98..84bb9e04f5 100644 --- a/src/ast/ast.cc +++ b/src/ast/ast.cc @@ -5,7 +5,6 @@ #include "src/ast/ast.h" #include // For isfinite. -#include #include "src/ast/compile-time-value.h" #include "src/ast/prettyprinter.h" @@ -249,34 +248,6 @@ bool FunctionLiteral::NeedsHomeObject(Expression* expr) { return expr->AsFunctionLiteral()->scope()->NeedsHomeObject(); } -std::unique_ptr FunctionLiteral::GetDebugName() const { - const AstConsString* cons_string; - if (raw_name_ != nullptr && !raw_name_->IsEmpty()) { - cons_string = raw_name_; - } else if (raw_inferred_name_ != nullptr && !raw_inferred_name_->IsEmpty()) { - cons_string = raw_inferred_name_; - } else if (!inferred_name_.is_null()) { - AllowHandleDereference allow_deref; - return inferred_name_->ToCString(); - } else { - return std::unique_ptr(new char{'\0'}); - } - - // TODO(rmcilroy): Deal with two-character strings. - std::vector result_vec; - std::forward_list strings = cons_string->ToRawStrings(); - for (const AstRawString* string : strings) { - if (!string->is_one_byte()) break; - for (int i = 0; i < string->length(); i++) { - result_vec.push_back(string->raw_data()[i]); - } - } - std::unique_ptr result(new char[result_vec.size() + 1]); - memcpy(result.get(), result_vec.data(), result_vec.size()); - result[result_vec.size()] = '\0'; - return result; -} - ObjectLiteralProperty::ObjectLiteralProperty(Expression* key, Expression* value, Kind kind, bool is_computed_name) : LiteralProperty(key, value, is_computed_name), diff --git a/src/ast/ast.h b/src/ast/ast.h index 240210765b..98d791b9b9 100644 --- a/src/ast/ast.h +++ b/src/ast/ast.h @@ -5,8 +5,6 @@ #ifndef V8_AST_AST_H_ #define V8_AST_AST_H_ -#include - #include "src/ast/ast-value-factory.h" #include "src/ast/modules.h" #include "src/ast/variables.h" @@ -2268,8 +2266,12 @@ class FunctionLiteral final : public Expression { return false; } - // Returns either name or inferred name as a cstring. - std::unique_ptr GetDebugName() const; + Handle debug_name() const { + if (raw_name_ != nullptr && !raw_name_->IsEmpty()) { + return raw_name_->string(); + } + return inferred_name(); + } Handle inferred_name() const { if (!inferred_name_.is_null()) { @@ -2290,8 +2292,6 @@ class FunctionLiteral final : public Expression { raw_inferred_name_ = nullptr; } - const AstConsString* raw_inferred_name() { return raw_inferred_name_; } - void set_raw_inferred_name(const AstConsString* raw_inferred_name) { DCHECK_NOT_NULL(raw_inferred_name); raw_inferred_name_ = raw_inferred_name; @@ -2524,7 +2524,6 @@ class ClassLiteral final : public Expression { class NativeFunctionLiteral final : public Expression { public: Handle name() const { return name_->string(); } - const AstRawString* raw_name() const { return name_; } v8::Extension* extension() const { return extension_; } private: diff --git a/src/ast/prettyprinter.cc b/src/ast/prettyprinter.cc index 87fe78262f..89338ab30c 100644 --- a/src/ast/prettyprinter.cc +++ b/src/ast/prettyprinter.cc @@ -562,66 +562,64 @@ void AstPrinter::PrintLabels(ZoneList* labels) { } } -void AstPrinter::PrintLiteral(Literal* literal, bool quote) { - switch (literal->type()) { - case Literal::kString: - PrintLiteral(literal->AsRawString(), quote); - break; - case Literal::kSymbol: - const char* symbol; - switch (literal->AsSymbol()) { - case AstSymbol::kHomeObjectSymbol: - symbol = "HomeObjectSymbol"; - } - Print("%s", symbol); - break; - case Literal::kSmi: - Print("%d", Smi::ToInt(literal->AsSmiLiteral())); - break; - case Literal::kHeapNumber: - Print("%g", literal->AsNumber()); - break; - case Literal::kBigInt: - Print("%sn", literal->AsBigInt().c_str()); - break; - case Literal::kNull: - Print("null"); - break; - case Literal::kUndefined: - Print("undefined"); - break; - case Literal::kTheHole: - Print("the hole"); - break; - case Literal::kBoolean: - if (literal->ToBooleanIsTrue()) { - Print("true"); - } else { - Print("false"); - } - break; +void AstPrinter::PrintLiteral(MaybeHandle maybe_value, bool quote) { + Handle value; + if (!maybe_value.ToHandle(&value)) { + Print(""); + return; + } + Object* object = *value; + if (object->IsString()) { + String* string = String::cast(object); + if (quote) Print("\""); + for (int i = 0; i < string->length(); i++) { + Print("%c", string->Get(i)); + } + if (quote) Print("\""); + } else if (object->IsNull(isolate_)) { + Print("null"); + } else if (object->IsTrue(isolate_)) { + Print("true"); + } else if (object->IsFalse(isolate_)) { + Print("false"); + } else if (object->IsUndefined(isolate_)) { + Print("undefined"); + } else if (object->IsNumber()) { + Print("%g", object->Number()); + } else if (object->IsJSObject()) { + // regular expression + if (object->IsJSFunction()) { + Print("JS-Function"); + } else if (object->IsJSArray()) { + Print("JS-array[%u]", Smi::ToInt(JSArray::cast(object)->length())); + } else if (object->IsJSObject()) { + Print("JS-Object"); + } else { + Print("?UNKNOWN?"); + } + } else if (object->IsFixedArray()) { + Print("FixedArray"); + } else if (object->IsSymbol()) { + // Symbols can only occur as literals if they were inserted by the parser. + Symbol* symbol = Symbol::cast(object); + if (symbol->name()->IsString()) { + int length = 0; + String* string = String::cast(symbol->name()); + std::unique_ptr desc = string->ToCString( + ALLOW_NULLS, FAST_STRING_TRAVERSAL, 0, string->length(), &length); + Print("Symbol(%*s)", length, desc.get()); + } else { + Print("Symbol()"); + } + } else { + Print("", static_cast(object)); } } void AstPrinter::PrintLiteral(const AstRawString* value, bool quote) { - if (quote) Print("\""); - const char* format = value->is_one_byte() ? "%c" : "%lc"; - const int increment = value->is_one_byte() ? 1 : 2; - const unsigned char* raw_bytes = value->raw_data(); - for (int i = 0; i < value->length(); i += increment) { - Print(format, raw_bytes[i]); - } - if (quote) Print("\""); + PrintLiteral(value->string(), quote); } -void AstPrinter::PrintLiteral(const AstConsString* value, bool quote) { - if (quote) Print("\""); - std::forward_list strings = value->ToRawStrings(); - for (const AstRawString* string : strings) { - PrintLiteral(string, false); - } - if (quote) Print("\""); -} //----------------------------------------------------------------------------- @@ -652,9 +650,9 @@ class IndentedScope BASE_EMBEDDED { //----------------------------------------------------------------------------- -AstPrinter::AstPrinter(uintptr_t stack_limit) - : output_(nullptr), size_(0), pos_(0), indent_(0) { - InitializeAstVisitor(stack_limit); +AstPrinter::AstPrinter(Isolate* isolate) + : isolate_(isolate), output_(nullptr), size_(0), pos_(0), indent_(0) { + InitializeAstVisitor(isolate); } AstPrinter::~AstPrinter() { @@ -670,32 +668,19 @@ void AstPrinter::PrintIndented(const char* txt) { Print("%s", txt); } -void AstPrinter::PrintLiteralIndented(const char* info, Literal* literal, +void AstPrinter::PrintLiteralIndented(const char* info, + MaybeHandle maybe_value, bool quote) { PrintIndented(info); Print(" "); - PrintLiteral(literal, quote); + PrintLiteral(maybe_value, quote); Print("\n"); } -void AstPrinter::PrintLiteralIndented(const char* info, - const AstRawString* value, bool quote) { - PrintIndented(info); - Print(" "); - PrintLiteral(value, quote); - Print("\n"); -} -void AstPrinter::PrintLiteralIndented(const char* info, - const AstConsString* value, bool quote) { - PrintIndented(info); - Print(" "); - PrintLiteral(value, quote); - Print("\n"); -} - -void AstPrinter::PrintLiteralWithModeIndented(const char* info, Variable* var, - const AstRawString* value) { +void AstPrinter::PrintLiteralWithModeIndented(const char* info, + Variable* var, + Handle value) { if (var == nullptr) { PrintLiteralIndented(info, value, true); } else { @@ -730,10 +715,8 @@ const char* AstPrinter::PrintProgram(FunctionLiteral* program) { Print(" %d\n", program->kind()); PrintIndented("SUSPEND COUNT"); Print(" %d\n", program->suspend_count()); - PrintLiteralIndented("NAME", program->raw_name(), true); - if (program->raw_inferred_name()) { - PrintLiteralIndented("INFERRED NAME", program->raw_inferred_name(), true); - } + PrintLiteralIndented("NAME", program->name(), true); + PrintLiteralIndented("INFERRED NAME", program->inferred_name(), true); PrintParameters(program->scope()); PrintDeclarations(program->scope()->declarations()); PrintStatements(program->body()); @@ -743,7 +726,7 @@ const char* AstPrinter::PrintProgram(FunctionLiteral* program) { void AstPrinter::PrintOut(Isolate* isolate, AstNode* node) { - AstPrinter printer(isolate->stack_guard()->real_climit()); + AstPrinter printer(isolate); printer.Init(); printer.Visit(node); PrintF("%s", printer.output_); @@ -761,7 +744,7 @@ void AstPrinter::PrintParameters(DeclarationScope* scope) { IndentedScope indent(this, "PARAMS"); for (int i = 0; i < scope->num_parameters(); i++) { PrintLiteralWithModeIndented("VAR", scope->parameter(i), - scope->parameter(i)->raw_name()); + scope->parameter(i)->name()); } } } @@ -792,16 +775,16 @@ void AstPrinter::VisitBlock(Block* node) { // TODO(svenpanne) Start with IndentedScope. void AstPrinter::VisitVariableDeclaration(VariableDeclaration* node) { PrintLiteralWithModeIndented("VARIABLE", node->proxy()->var(), - node->proxy()->raw_name()); + node->proxy()->name()); } // TODO(svenpanne) Start with IndentedScope. void AstPrinter::VisitFunctionDeclaration(FunctionDeclaration* node) { PrintIndented("FUNCTION "); - PrintLiteral(node->proxy()->raw_name(), true); + PrintLiteral(node->proxy()->name(), true); Print(" = function "); - PrintLiteral(node->fun()->raw_name(), false); + PrintLiteral(node->fun()->name(), false); Print("\n"); } @@ -954,7 +937,7 @@ void AstPrinter::VisitTryCatchStatement(TryCatchStatement* node) { } Print(" %s\n", prediction); PrintLiteralWithModeIndented("CATCHVAR", node->scope()->catch_variable(), - node->scope()->catch_variable()->raw_name()); + node->scope()->catch_variable()->name()); PrintIndentedVisit("CATCH", node->catch_block()); } @@ -971,8 +954,8 @@ void AstPrinter::VisitDebuggerStatement(DebuggerStatement* node) { void AstPrinter::VisitFunctionLiteral(FunctionLiteral* node) { IndentedScope indent(this, "FUNC LITERAL", node->position()); - PrintLiteralIndented("NAME", node->raw_name(), false); - PrintLiteralIndented("INFERRED NAME", node->raw_inferred_name(), false); + PrintLiteralIndented("NAME", node->name(), false); + PrintLiteralIndented("INFERRED NAME", node->inferred_name(), false); PrintParameters(node->scope()); // We don't want to see the function literal in this case: it // will be printed via PrintProgram when the code for it is @@ -983,7 +966,7 @@ void AstPrinter::VisitFunctionLiteral(FunctionLiteral* node) { void AstPrinter::VisitClassLiteral(ClassLiteral* node) { IndentedScope indent(this, "CLASS LITERAL", node->position()); - PrintLiteralIndented("NAME", node->constructor()->raw_name(), false); + PrintLiteralIndented("NAME", node->constructor()->name(), false); if (node->extends() != nullptr) { PrintIndentedVisit("EXTENDS", node->extends()); } @@ -1027,7 +1010,7 @@ void AstPrinter::PrintClassProperties( void AstPrinter::VisitNativeFunctionLiteral(NativeFunctionLiteral* node) { IndentedScope indent(this, "NATIVE FUNC LITERAL", node->position()); - PrintLiteralIndented("NAME", node->raw_name(), false); + PrintLiteralIndented("NAME", node->name(), false); } @@ -1046,13 +1029,15 @@ void AstPrinter::VisitConditional(Conditional* node) { void AstPrinter::VisitLiteral(Literal* node) { - PrintLiteralIndented("LITERAL", node, true); + // TODO(adamk): Teach Literal how to print its values without + // allocating on the heap. + PrintLiteralIndented("LITERAL", node->BuildValue(isolate_), true); } void AstPrinter::VisitRegExpLiteral(RegExpLiteral* node) { IndentedScope indent(this, "REGEXP LITERAL", node->position()); - PrintLiteralIndented("PATTERN", node->raw_pattern(), false); + PrintLiteralIndented("PATTERN", node->pattern(), false); int i = 0; EmbeddedVector buf; if (node->flags() & RegExp::kGlobal) buf[i++] = 'g'; @@ -1126,7 +1111,7 @@ void AstPrinter::VisitVariableProxy(VariableProxy* node) { if (!node->is_resolved()) { SNPrintF(buf + pos, " unresolved"); - PrintLiteralWithModeIndented(buf.start(), nullptr, node->raw_name()); + PrintLiteralWithModeIndented(buf.start(), nullptr, node->name()); } else { Variable* var = node->var(); switch (var->location()) { @@ -1149,7 +1134,7 @@ void AstPrinter::VisitVariableProxy(VariableProxy* node) { SNPrintF(buf + pos, " module"); break; } - PrintLiteralWithModeIndented(buf.start(), var, node->raw_name()); + PrintLiteralWithModeIndented(buf.start(), var, node->name()); } } @@ -1197,13 +1182,13 @@ void AstPrinter::VisitProperty(Property* node) { IndentedScope indent(this, buf.start(), node->position()); Visit(node->obj()); - LhsKind property_kind = Property::GetAssignType(node); - if (property_kind == NAMED_PROPERTY || - property_kind == NAMED_SUPER_PROPERTY) { - PrintLiteralIndented("NAME", node->key()->AsLiteral(), false); + Literal* literal = node->key()->AsLiteral(); + if (literal != nullptr && + literal->BuildValue(isolate_)->IsInternalizedString()) { + // TODO(adamk): Teach Literal how to print its values without + // allocating on the heap. + PrintLiteralIndented("NAME", literal->BuildValue(isolate_), false); } else { - DCHECK(property_kind == KEYED_PROPERTY || - property_kind == KEYED_SUPER_PROPERTY); PrintIndentedVisit("KEY", node->key()); } } diff --git a/src/ast/prettyprinter.h b/src/ast/prettyprinter.h index 97c2437877..58849a6052 100644 --- a/src/ast/prettyprinter.h +++ b/src/ast/prettyprinter.h @@ -64,7 +64,7 @@ class CallPrinter final : public AstVisitor { class AstPrinter final : public AstVisitor { public: - explicit AstPrinter(uintptr_t stack_limit); + explicit AstPrinter(Isolate* isolate); ~AstPrinter(); // The following routines print a node into a string. @@ -89,8 +89,7 @@ class AstPrinter final : public AstVisitor { void PrintLabels(ZoneList* labels); void PrintLiteral(const AstRawString* value, bool quote); - void PrintLiteral(const AstConsString* value, bool quote); - void PrintLiteral(Literal* literal, bool quote); + void PrintLiteral(MaybeHandle maybe_value, bool quote); void PrintIndented(const char* txt); void PrintIndentedVisit(const char* s, AstNode* node); @@ -99,13 +98,11 @@ class AstPrinter final : public AstVisitor { void PrintParameters(DeclarationScope* scope); void PrintArguments(ZoneList* arguments); void PrintCaseClause(CaseClause* clause); - void PrintLiteralIndented(const char* info, Literal* literal, bool quote); - void PrintLiteralIndented(const char* info, const AstRawString* value, + void PrintLiteralIndented(const char* info, MaybeHandle maybe_value, bool quote); - void PrintLiteralIndented(const char* info, const AstConsString* value, - bool quote); - void PrintLiteralWithModeIndented(const char* info, Variable* var, - const AstRawString* value); + void PrintLiteralWithModeIndented(const char* info, + Variable* var, + Handle value); void PrintLabelsIndented(ZoneList* labels); void PrintObjectProperties(ZoneList* properties); void PrintClassProperties(ZoneList* properties); @@ -115,6 +112,7 @@ class AstPrinter final : public AstVisitor { DEFINE_AST_VISITOR_SUBCLASS_MEMBERS(); + Isolate* isolate_; char* output_; // output string buffer int size_; // output_ size int pos_; // current printing position diff --git a/src/compilation-info.cc b/src/compilation-info.cc index 4a6562f200..46128e729b 100644 --- a/src/compilation-info.cc +++ b/src/compilation-info.cc @@ -130,7 +130,8 @@ bool CompilationInfo::has_simple_parameters() { std::unique_ptr CompilationInfo::GetDebugName() const { if (literal()) { - return literal()->GetDebugName(); + AllowHandleDereference allow_deref; + return literal()->debug_name()->ToCString(); } if (!shared_info().is_null()) { return shared_info()->DebugName()->ToCString(); diff --git a/src/flag-definitions.h b/src/flag-definitions.h index b84b9e1105..72ea7544b4 100644 --- a/src/flag-definitions.h +++ b/src/flag-definitions.h @@ -1028,6 +1028,7 @@ DEFINE_BOOL(enable_slow_asserts, false, // codegen-ia32.cc / codegen-arm.cc / macro-assembler-*.cc DEFINE_BOOL(print_ast, false, "print source AST") +DEFINE_BOOL(print_builtin_ast, false, "print source AST for builtins") DEFINE_BOOL(trap_on_abort, false, "replace aborts by breakpoints") // compiler.cc diff --git a/src/interpreter/interpreter.cc b/src/interpreter/interpreter.cc index 363fc6eb6c..744171e8ae 100644 --- a/src/interpreter/interpreter.cc +++ b/src/interpreter/interpreter.cc @@ -137,7 +137,20 @@ void Interpreter::IterateDispatchTable(RootVisitor* v) { namespace { void MaybePrintAst(ParseInfo* parse_info, CompilationInfo* compilation_info) { - if (!FLAG_print_ast) return; + Isolate* isolate = compilation_info->isolate(); + bool print_ast = isolate->bootstrapper()->IsActive() ? FLAG_print_builtin_ast + : FLAG_print_ast; + if (!print_ast) return; + + // Requires internalizing the AST, so make sure we are on the main thread and + // allow handle dereference and allocations. + // TODO(rmcilroy): Make ast-printer print ast raw strings instead of + // internalized strings to avoid internalizing here. + DCHECK(ThreadId::Current().Equals(isolate->thread_id())); + AllowHandleDereference allow_deref; + AllowHandleAllocation allow_handles; + AllowHeapAllocation allow_gc; + parse_info->ast_value_factory()->Internalize(isolate); OFStream os(stdout); std::unique_ptr name = compilation_info->GetDebugName(); @@ -145,8 +158,7 @@ void MaybePrintAst(ParseInfo* parse_info, CompilationInfo* compilation_info) { << compilation_info->GetDebugName().get() << "]" << std::endl; #ifdef DEBUG os << "--- AST ---" << std::endl - << AstPrinter(parse_info->stack_limit()) - .PrintProgram(compilation_info->literal()) + << AstPrinter(isolate).PrintProgram(compilation_info->literal()) << std::endl; #endif // DEBUG } diff --git a/src/parsing/parser.cc b/src/parsing/parser.cc index 5009e3c052..d9243d4015 100644 --- a/src/parsing/parser.cc +++ b/src/parsing/parser.cc @@ -778,7 +778,7 @@ FunctionLiteral* Parser::ParseFunction(Isolate* isolate, ParseInfo* info, double ms = timer.Elapsed().InMillisecondsF(); // We need to make sure that the debug-name is available. ast_value_factory()->Internalize(isolate); - std::unique_ptr name_chars = result->GetDebugName(); + std::unique_ptr name_chars = result->debug_name()->ToCString(); PrintF("[parsing function: %s - took %0.3f ms]\n", name_chars.get(), ms); } return result;