Update V8 to r4588
We're using WebKit r58033, as used by
http://src.chromium.org/svn/releases/5.0.387.0/DEPS
This requires http://v8.googlecode.com/svn/trunk@4465 but this version has a
crashing bug for ARM. Instead we use http://v8.googlecode.com/svn/trunk@4588,
which is used by http://src.chromium.org/svn/releases/6.0.399.0/DEPS
Note that a trivial bug fix was required in arm/codegen-arm.cc. This is guarded
with ANDROID. See http://code.google.com/p/v8/issues/detail?id=703
Change-Id: I459647a8286c4f8c7405f0c5581ecbf051a6f1e8
diff --git a/src/compiler.cc b/src/compiler.cc
index 7b6734a..901f218 100755
--- a/src/compiler.cc
+++ b/src/compiler.cc
@@ -1,4 +1,4 @@
-// Copyright 2009 the V8 project authors. All rights reserved.
+// Copyright 2010 the V8 project authors. All rights reserved.
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are
// met:
@@ -31,14 +31,15 @@
#include "codegen-inl.h"
#include "compilation-cache.h"
#include "compiler.h"
+#include "data-flow.h"
#include "debug.h"
#include "fast-codegen.h"
+#include "flow-graph.h"
#include "full-codegen.h"
+#include "liveedit.h"
#include "oprofile-agent.h"
#include "rewriter.h"
#include "scopes.h"
-#include "usage-analyzer.h"
-#include "liveedit.h"
namespace v8 {
namespace internal {
@@ -48,7 +49,7 @@
FunctionLiteral* function = info->function();
ASSERT(function != NULL);
// Rewrite the AST by introducing .result assignments where needed.
- if (!Rewriter::Process(function) || !AnalyzeVariableUsage(function)) {
+ if (!Rewriter::Process(function)) {
// Signal a stack overflow by returning a null handle. The stack
// overflow exception will be thrown by the caller.
return Handle<Code>::null();
@@ -79,6 +80,27 @@
return Handle<Code>::null();
}
+ if (function->scope()->num_parameters() > 0 ||
+ function->scope()->num_stack_slots()) {
+ AssignedVariablesAnalyzer ava(function);
+ ava.Analyze();
+ if (ava.HasStackOverflow()) {
+ return Handle<Code>::null();
+ }
+ }
+
+ if (FLAG_use_flow_graph) {
+ FlowGraphBuilder builder;
+ FlowGraph* graph = builder.Build(function);
+ USE(graph);
+
+#ifdef DEBUG
+ if (FLAG_print_graph_text && !builder.HasStackOverflow()) {
+ graph->PrintAsText(function->name());
+ }
+#endif
+ }
+
// Generate code and return it. Code generator selection is governed by
// which backends are enabled and whether the function is considered
// run-once code or not:
@@ -117,13 +139,21 @@
}
-static Handle<JSFunction> MakeFunction(bool is_global,
- bool is_eval,
- Compiler::ValidationState validate,
- Handle<Script> script,
- Handle<Context> context,
- v8::Extension* extension,
- ScriptDataImpl* pre_data) {
+#ifdef ENABLE_DEBUGGER_SUPPORT
+Handle<Code> MakeCodeForLiveEdit(CompilationInfo* info) {
+ Handle<Context> context = Handle<Context>::null();
+ return MakeCode(context, info);
+}
+#endif
+
+
+static Handle<SharedFunctionInfo> MakeFunctionInfo(bool is_global,
+ bool is_eval,
+ Compiler::ValidationState validate,
+ Handle<Script> script,
+ Handle<Context> context,
+ v8::Extension* extension,
+ ScriptDataImpl* pre_data) {
CompilationZoneScope zone_scope(DELETE_ON_EXIT);
PostponeInterruptsScope postpone;
@@ -162,10 +192,12 @@
FunctionLiteral* lit =
MakeAST(is_global, script, extension, pre_data, is_json);
+ LiveEditFunctionTracker live_edit_tracker(lit);
+
// Check for parse errors.
if (lit == NULL) {
ASSERT(Top::has_pending_exception());
- return Handle<JSFunction>::null();
+ return Handle<SharedFunctionInfo>::null();
}
// Measure how long it takes to do the compilation; only take the
@@ -183,64 +215,63 @@
// Check for stack-overflow exceptions.
if (code.is_null()) {
Top::StackOverflow();
- return Handle<JSFunction>::null();
+ return Handle<SharedFunctionInfo>::null();
}
-#if defined ENABLE_LOGGING_AND_PROFILING || defined ENABLE_OPROFILE_AGENT
- // Log the code generation for the script. Check explicit whether logging is
- // to avoid allocating when not required.
- if (Logger::is_logging() || OProfileAgent::is_enabled()) {
- if (script->name()->IsString()) {
- SmartPointer<char> data =
- String::cast(script->name())->ToCString(DISALLOW_NULLS);
- LOG(CodeCreateEvent(is_eval ? Logger::EVAL_TAG : Logger::SCRIPT_TAG,
- *code, *data));
- OProfileAgent::CreateNativeCodeRegion(*data,
- code->instruction_start(),
- code->instruction_size());
- } else {
- LOG(CodeCreateEvent(is_eval ? Logger::EVAL_TAG : Logger::SCRIPT_TAG,
- *code, ""));
- OProfileAgent::CreateNativeCodeRegion(is_eval ? "Eval" : "Script",
- code->instruction_start(),
- code->instruction_size());
- }
+ if (script->name()->IsString()) {
+ PROFILE(CodeCreateEvent(
+ is_eval ? Logger::EVAL_TAG :
+ Logger::ToNativeByScript(Logger::SCRIPT_TAG, *script),
+ *code, String::cast(script->name())));
+ OPROFILE(CreateNativeCodeRegion(String::cast(script->name()),
+ code->instruction_start(),
+ code->instruction_size()));
+ } else {
+ PROFILE(CodeCreateEvent(
+ is_eval ? Logger::EVAL_TAG :
+ Logger::ToNativeByScript(Logger::SCRIPT_TAG, *script),
+ *code, ""));
+ OPROFILE(CreateNativeCodeRegion(is_eval ? "Eval" : "Script",
+ code->instruction_start(),
+ code->instruction_size()));
}
-#endif
// Allocate function.
- Handle<JSFunction> fun =
- Factory::NewFunctionBoilerplate(lit->name(),
- lit->materialized_literal_count(),
- code);
+ Handle<SharedFunctionInfo> result =
+ Factory::NewSharedFunctionInfo(lit->name(),
+ lit->materialized_literal_count(),
+ code);
ASSERT_EQ(RelocInfo::kNoPosition, lit->function_token_position());
- Compiler::SetFunctionInfo(fun, lit, true, script);
+ Compiler::SetFunctionInfo(result, lit, true, script);
// Hint to the runtime system used when allocating space for initial
// property space by setting the expected number of properties for
// the instances of the function.
- SetExpectedNofPropertiesFromEstimate(fun, lit->expected_property_count());
+ SetExpectedNofPropertiesFromEstimate(result, lit->expected_property_count());
#ifdef ENABLE_DEBUGGER_SUPPORT
// Notify debugger
- Debugger::OnAfterCompile(script, fun);
+ Debugger::OnAfterCompile(script, Debugger::NO_AFTER_COMPILE_FLAGS);
#endif
- return fun;
+ live_edit_tracker.RecordFunctionInfo(result, lit);
+
+ return result;
}
static StaticResource<SafeStringInputBuffer> safe_string_input_buffer;
-Handle<JSFunction> Compiler::Compile(Handle<String> source,
- Handle<Object> script_name,
- int line_offset, int column_offset,
- v8::Extension* extension,
- ScriptDataImpl* input_pre_data,
- Handle<Object> script_data,
- NativesFlag natives) {
+Handle<SharedFunctionInfo> Compiler::Compile(Handle<String> source,
+ Handle<Object> script_name,
+ int line_offset,
+ int column_offset,
+ v8::Extension* extension,
+ ScriptDataImpl* input_pre_data,
+ Handle<Object> script_data,
+ NativesFlag natives) {
int source_length = source->length();
Counters::total_load_size.Increment(source_length);
Counters::total_compile_size.Increment(source_length);
@@ -249,7 +280,7 @@
VMState state(COMPILER);
// Do a lookup in the compilation cache but not for extensions.
- Handle<JSFunction> result;
+ Handle<SharedFunctionInfo> result;
if (extension == NULL) {
result = CompilationCache::LookupScript(source,
script_name,
@@ -281,13 +312,13 @@
: *script_data);
// Compile the function and add it to the cache.
- result = MakeFunction(true,
- false,
- DONT_VALIDATE_JSON,
- script,
- Handle<Context>::null(),
- extension,
- pre_data);
+ result = MakeFunctionInfo(true,
+ false,
+ DONT_VALIDATE_JSON,
+ script,
+ Handle<Context>::null(),
+ extension,
+ pre_data);
if (extension == NULL && !result.is_null()) {
CompilationCache::PutScript(source, result);
}
@@ -303,10 +334,10 @@
}
-Handle<JSFunction> Compiler::CompileEval(Handle<String> source,
- Handle<Context> context,
- bool is_global,
- ValidationState validate) {
+Handle<SharedFunctionInfo> Compiler::CompileEval(Handle<String> source,
+ Handle<Context> context,
+ bool is_global,
+ ValidationState validate) {
// Note that if validation is required then no path through this
// function is allowed to return a value without validating that
// the input is legal json.
@@ -322,20 +353,20 @@
// invoke the compiler and add the result to the cache. If we're
// evaluating json we bypass the cache since we can't be sure a
// potential value in the cache has been validated.
- Handle<JSFunction> result;
+ Handle<SharedFunctionInfo> result;
if (validate == DONT_VALIDATE_JSON)
result = CompilationCache::LookupEval(source, context, is_global);
if (result.is_null()) {
// Create a script object describing the script to be compiled.
Handle<Script> script = Factory::NewScript(source);
- result = MakeFunction(is_global,
- true,
- validate,
- script,
- context,
- NULL,
- NULL);
+ result = MakeFunctionInfo(is_global,
+ true,
+ validate,
+ script,
+ context,
+ NULL,
+ NULL);
if (!result.is_null() && validate != VALIDATE_JSON) {
// For json it's unlikely that we'll ever see exactly the same
// string again so we don't use the compilation cache.
@@ -393,14 +424,12 @@
return false;
}
-#if defined ENABLE_LOGGING_AND_PROFILING || defined ENABLE_OPROFILE_AGENT
- LogCodeCreateEvent(Logger::LAZY_COMPILE_TAG,
- name,
- Handle<String>(shared->inferred_name()),
- start_position,
- info->script(),
- code);
-#endif
+ RecordFunctionCompilation(Logger::LAZY_COMPILE_TAG,
+ name,
+ Handle<String>(shared->inferred_name()),
+ start_position,
+ info->script(),
+ code);
// Update the shared function info with the compiled code.
shared->set_code(*code);
@@ -420,9 +449,10 @@
}
-Handle<JSFunction> Compiler::BuildBoilerplate(FunctionLiteral* literal,
- Handle<Script> script,
- AstVisitor* caller) {
+Handle<SharedFunctionInfo> Compiler::BuildFunctionInfo(FunctionLiteral* literal,
+ Handle<Script> script,
+ AstVisitor* caller) {
+ LiveEditFunctionTracker live_edit_tracker(literal);
#ifdef DEBUG
// We should not try to compile the same function literal more than
// once.
@@ -445,7 +475,28 @@
// The bodies of function literals have not yet been visited by
// the AST optimizer/analyzer.
if (!Rewriter::Optimize(literal)) {
- return Handle<JSFunction>::null();
+ return Handle<SharedFunctionInfo>::null();
+ }
+
+ if (literal->scope()->num_parameters() > 0 ||
+ literal->scope()->num_stack_slots()) {
+ AssignedVariablesAnalyzer ava(literal);
+ ava.Analyze();
+ if (ava.HasStackOverflow()) {
+ return Handle<SharedFunctionInfo>::null();
+ }
+ }
+
+ if (FLAG_use_flow_graph) {
+ FlowGraphBuilder builder;
+ FlowGraph* graph = builder.Build(literal);
+ USE(graph);
+
+#ifdef DEBUG
+ if (FLAG_print_graph_text && !builder.HasStackOverflow()) {
+ graph->PrintAsText(literal->name());
+ }
+#endif
}
// Generate code and return it. The way that the compilation mode
@@ -483,38 +534,31 @@
// Check for stack-overflow exception.
if (code.is_null()) {
caller->SetStackOverflow();
- return Handle<JSFunction>::null();
+ return Handle<SharedFunctionInfo>::null();
}
// Function compilation complete.
-
-#if defined ENABLE_LOGGING_AND_PROFILING || defined ENABLE_OPROFILE_AGENT
- LogCodeCreateEvent(Logger::FUNCTION_TAG,
- literal->name(),
- literal->inferred_name(),
- literal->start_position(),
- script,
- code);
-#endif
+ RecordFunctionCompilation(Logger::FUNCTION_TAG,
+ literal->name(),
+ literal->inferred_name(),
+ literal->start_position(),
+ script,
+ code);
}
- // Create a boilerplate function.
- Handle<JSFunction> function =
- Factory::NewFunctionBoilerplate(literal->name(),
- literal->materialized_literal_count(),
- code);
- SetFunctionInfo(function, literal, false, script);
-
-#ifdef ENABLE_DEBUGGER_SUPPORT
- // Notify debugger that a new function has been added.
- Debugger::OnNewFunction(function);
-#endif
+ // Create a shared function info object.
+ Handle<SharedFunctionInfo> result =
+ Factory::NewSharedFunctionInfo(literal->name(),
+ literal->materialized_literal_count(),
+ code);
+ SetFunctionInfo(result, literal, false, script);
// Set the expected number of properties for instances and return
// the resulting function.
- SetExpectedNofPropertiesFromEstimate(function,
+ SetExpectedNofPropertiesFromEstimate(result,
literal->expected_property_count());
- return function;
+ live_edit_tracker.RecordFunctionInfo(result, literal);
+ return result;
}
@@ -522,55 +566,58 @@
// The start_position points to the first '(' character after the function name
// in the full script source. When counting characters in the script source the
// the first character is number 0 (not 1).
-void Compiler::SetFunctionInfo(Handle<JSFunction> fun,
+void Compiler::SetFunctionInfo(Handle<SharedFunctionInfo> function_info,
FunctionLiteral* lit,
bool is_toplevel,
Handle<Script> script) {
- fun->shared()->set_length(lit->num_parameters());
- fun->shared()->set_formal_parameter_count(lit->num_parameters());
- fun->shared()->set_script(*script);
- fun->shared()->set_function_token_position(lit->function_token_position());
- fun->shared()->set_start_position(lit->start_position());
- fun->shared()->set_end_position(lit->end_position());
- fun->shared()->set_is_expression(lit->is_expression());
- fun->shared()->set_is_toplevel(is_toplevel);
- fun->shared()->set_inferred_name(*lit->inferred_name());
- fun->shared()->SetThisPropertyAssignmentsInfo(
+ function_info->set_length(lit->num_parameters());
+ function_info->set_formal_parameter_count(lit->num_parameters());
+ function_info->set_script(*script);
+ function_info->set_function_token_position(lit->function_token_position());
+ function_info->set_start_position(lit->start_position());
+ function_info->set_end_position(lit->end_position());
+ function_info->set_is_expression(lit->is_expression());
+ function_info->set_is_toplevel(is_toplevel);
+ function_info->set_inferred_name(*lit->inferred_name());
+ function_info->SetThisPropertyAssignmentsInfo(
lit->has_only_simple_this_property_assignments(),
*lit->this_property_assignments());
- fun->shared()->set_try_full_codegen(lit->try_full_codegen());
+ function_info->set_try_full_codegen(lit->try_full_codegen());
}
-#if defined ENABLE_LOGGING_AND_PROFILING || defined ENABLE_OPROFILE_AGENT
-void Compiler::LogCodeCreateEvent(Logger::LogEventsAndTags tag,
- Handle<String> name,
- Handle<String> inferred_name,
- int start_position,
- Handle<Script> script,
- Handle<Code> code) {
+void Compiler::RecordFunctionCompilation(Logger::LogEventsAndTags tag,
+ Handle<String> name,
+ Handle<String> inferred_name,
+ int start_position,
+ Handle<Script> script,
+ Handle<Code> code) {
// Log the code generation. If source information is available
// include script name and line number. Check explicitly whether
// logging is enabled as finding the line number is not free.
- if (Logger::is_logging() || OProfileAgent::is_enabled()) {
+ if (Logger::is_logging()
+ || OProfileAgent::is_enabled()
+ || CpuProfiler::is_profiling()) {
Handle<String> func_name(name->length() > 0 ? *name : *inferred_name);
if (script->name()->IsString()) {
int line_num = GetScriptLineNumber(script, start_position) + 1;
- LOG(CodeCreateEvent(tag, *code, *func_name,
- String::cast(script->name()), line_num));
- OProfileAgent::CreateNativeCodeRegion(*func_name,
- String::cast(script->name()),
- line_num,
- code->instruction_start(),
- code->instruction_size());
+ USE(line_num);
+ PROFILE(CodeCreateEvent(Logger::ToNativeByScript(tag, *script),
+ *code, *func_name,
+ String::cast(script->name()), line_num));
+ OPROFILE(CreateNativeCodeRegion(*func_name,
+ String::cast(script->name()),
+ line_num,
+ code->instruction_start(),
+ code->instruction_size()));
} else {
- LOG(CodeCreateEvent(tag, *code, *func_name));
- OProfileAgent::CreateNativeCodeRegion(*func_name,
- code->instruction_start(),
- code->instruction_size());
+ PROFILE(CodeCreateEvent(Logger::ToNativeByScript(tag, *script),
+ *code, *func_name));
+ OPROFILE(CreateNativeCodeRegion(*func_name,
+ code->instruction_start(),
+ code->instruction_size()));
}
}
}
-#endif
} } // namespace v8::internal