Commit 961add84 authored by Franziska Hinkelmann's avatar Franziska Hinkelmann Committed by Commit Bot

[type-profile] Collect types for parameters.

Add the source position to variables if they are parameters.

Collect type information for parameters and return values. 
Index the types by their corresponding source position. For the
types of return values, use the function end as source position.


Sample output for a function with 2 parameters (at source
position 252 and 258, and function end at 443)
*************
Function: testFunction
252:
Object
number
string
number
258:
undefined
boolean
undefined
undefined
443:
Object
number
string
number
*************



BUG=v8:5933

Change-Id: I3b8749afcac706c1834146abf1b5b4a3fd130fb6
Reviewed-on: https://chromium-review.googlesource.com/461919Reviewed-by: 's avatarMichael Starzinger <mstarzinger@chromium.org>
Reviewed-by: 's avatarMarja Hölttä <marja@chromium.org>
Reviewed-by: 's avatarYang Guo <yangguo@chromium.org>
Commit-Queue: Franziska Hinkelmann <franzih@chromium.org>
Cr-Commit-Position: refs/heads/master@{#44299}
parent 2a7ab875
......@@ -1008,7 +1008,7 @@ Variable* Scope::Lookup(const AstRawString* name) {
Variable* DeclarationScope::DeclareParameter(
const AstRawString* name, VariableMode mode, bool is_optional, bool is_rest,
bool* is_duplicate, AstValueFactory* ast_value_factory) {
bool* is_duplicate, AstValueFactory* ast_value_factory, int position) {
DCHECK(!already_resolved_);
DCHECK(is_function_scope() || is_module_scope());
DCHECK(!has_rest_);
......@@ -1025,6 +1025,7 @@ Variable* DeclarationScope::DeclareParameter(
*is_duplicate = IsDeclaredParameter(name);
}
has_rest_ = is_rest;
var->set_initializer_position(position);
params_.Add(var, zone());
if (name == ast_value_factory->arguments_string()) {
has_arguments_parameter_ = true;
......
......@@ -710,7 +710,7 @@ class V8_EXPORT_PRIVATE DeclarationScope : public Scope {
// expects all parameters to be declared and from left to right.
Variable* DeclareParameter(const AstRawString* name, VariableMode mode,
bool is_optional, bool is_rest, bool* is_duplicate,
AstValueFactory* ast_value_factory);
AstValueFactory* ast_value_factory, int position);
// Declares that a parameter with the name exists. Creates a Variable and
// returns it if FLAG_preparser_scope_analysis is on.
......
......@@ -910,26 +910,68 @@ InlineCacheState CollectTypeProfileNexus::StateFromFeedback() const {
return MONOMORPHIC;
}
void CollectTypeProfileNexus::Collect(Handle<Name> type, int position) {
void CollectTypeProfileNexus::Collect(Handle<String> type, int position) {
DCHECK_GT(position, 0);
Isolate* isolate = GetIsolate();
Object* const feedback = GetFeedback();
Handle<ArrayList> types;
// Map source position to collection of types
Handle<UnseededNumberDictionary> types;
if (feedback == *FeedbackVector::UninitializedSentinel(isolate)) {
types = ArrayList::New(isolate, 1);
types = UnseededNumberDictionary::NewEmpty(isolate);
} else {
types = Handle<ArrayList>(ArrayList::cast(feedback), isolate);
types = Handle<UnseededNumberDictionary>(
UnseededNumberDictionary::cast(feedback), isolate);
}
Handle<Tuple2> entry = isolate->factory()->NewTuple2(
type, Handle<Smi>(Smi::FromInt(position), isolate));
Handle<ArrayList> types_for_position;
if (types->Has(position)) {
int entry = types->FindEntry(position);
DCHECK(types->ValueAt(entry)->IsArrayList());
types_for_position =
Handle<ArrayList>(ArrayList::cast(types->ValueAt(entry)));
} else {
types_for_position = ArrayList::New(isolate, 1);
}
// TODO(franzih): Somehow sort this list. Either avoid duplicates
// or use the common base type.
SetFeedback(*ArrayList::Add(types, entry));
types = UnseededNumberDictionary::Set(
types, position, ArrayList::Add(types_for_position, type));
SetFeedback(*types);
}
namespace {
void PrintTypes(Handle<ArrayList> s) {
for (int i = 0; i < s->Length(); i++) {
Object* entry = s->Get(i);
if (entry->IsString()) {
PrintF("%s\n", String::cast(entry)->ToCString().get());
}
}
}
void SortTypes(Isolate* isolate,
Handle<UnseededNumberDictionary> unsorted_types,
std::map<int, Handle<ArrayList>>* types) {
for (int index = UnseededNumberDictionary::kElementsStartIndex;
index < unsorted_types->length();
index += UnseededNumberDictionary::kEntrySize) {
int key_index = index + UnseededNumberDictionary::kEntryKeyIndex;
Object* key = unsorted_types->get(key_index);
if (key->IsSmi()) {
int value_index = index + UnseededNumberDictionary::kEntryValueIndex;
Handle<ArrayList> types_for_position = Handle<ArrayList>(
ArrayList::cast(unsorted_types->get(value_index)), isolate);
(*types)[Smi::cast(key)->value()] = types_for_position;
}
}
}
} // namespace
void CollectTypeProfileNexus::Print() const {
Isolate* isolate = GetIsolate();
......@@ -939,17 +981,16 @@ void CollectTypeProfileNexus::Print() const {
return;
}
Handle<ArrayList> list;
list = Handle<ArrayList>(ArrayList::cast(feedback), isolate);
Handle<UnseededNumberDictionary> unsorted_types =
Handle<UnseededNumberDictionary>(UnseededNumberDictionary::cast(feedback),
isolate);
std::map<int, Handle<ArrayList>> types;
SortTypes(isolate, unsorted_types, &types);
for (int i = 0; i < list->Length(); i++) {
Handle<Object> maybe_entry = Handle<Object>(list->Get(i), isolate);
DCHECK(maybe_entry->IsTuple2());
Handle<Tuple2> entry = Handle<Tuple2>::cast(maybe_entry);
Handle<String> type =
Handle<String>(String::cast(entry->value1()), isolate);
int position = Smi::cast(entry->value2())->value();
PrintF("%d: %s\n", position, type->ToCString().get());
for (const auto& entry : types) {
PrintF("%d:\n", entry.first);
PrintTypes(entry.second);
}
}
......
......@@ -760,7 +760,7 @@ class CollectTypeProfileNexus : public FeedbackNexus {
}
// Add a type to the list of types.
void Collect(Handle<Name> type, int position);
void Collect(Handle<String> type, int position);
// Dump the types to stdout.
// TODO(franzih): pass this information to the debugger protocol instead of
......
......@@ -762,6 +762,16 @@ void BytecodeGenerator::GenerateBytecodeBody() {
// Emit tracing call if requested to do so.
if (FLAG_trace) builder()->CallRuntime(Runtime::kTraceEnter);
// Emit type profile call.
if (info()->literal()->feedback_vector_spec()->HasTypeProfileSlot()) {
int num_parameters = closure_scope()->num_parameters();
for (int i = 0; i < num_parameters; i++) {
Register parameter(builder()->Parameter(i));
builder()->LoadAccumulatorWithRegister(parameter).CollectTypeProfile(
closure_scope()->parameter(i)->initializer_position());
}
}
// Visit declarations within the function scope.
VisitDeclarations(closure_scope()->declarations());
......@@ -2025,7 +2035,7 @@ void BytecodeGenerator::BuildReturn() {
Runtime::kTraceExit, result);
}
if (info()->literal()->feedback_vector_spec()->HasTypeProfileSlot()) {
builder()->CollectTypeProfile(info()->literal()->position());
builder()->CollectTypeProfile(info()->literal()->return_position());
}
builder()->Return();
}
......
......@@ -16754,6 +16754,10 @@ template Handle<SeededNumberDictionary>
Dictionary<SeededNumberDictionary, SeededNumberDictionaryShape,
uint32_t>::NewEmpty(Isolate*, PretenureFlag pretenure);
template Handle<UnseededNumberDictionary>
Dictionary<UnseededNumberDictionary, UnseededNumberDictionaryShape,
uint32_t>::NewEmpty(Isolate*, PretenureFlag pretenure);
template Handle<UnseededNumberDictionary>
Dictionary<UnseededNumberDictionary, UnseededNumberDictionaryShape,
uint32_t>::New(Isolate*, int at_least_space_for,
......
......@@ -192,7 +192,7 @@ FunctionLiteral* Parser::DefaultConstructor(const AstRawString* name,
bool is_optional = false;
Variable* constructor_args = function_scope->DeclareParameter(
constructor_args_name, TEMPORARY, is_optional, is_rest, &is_duplicate,
ast_value_factory());
ast_value_factory(), pos);
ZoneList<Expression*>* args =
new (zone()) ZoneList<Expression*>(1, zone());
......@@ -707,8 +707,9 @@ FunctionLiteral* Parser::DoParseProgram(ParseInfo* info) {
bool is_duplicate;
bool is_rest = false;
bool is_optional = false;
auto var = scope->DeclareParameter(name, VAR, is_optional, is_rest,
&is_duplicate, ast_value_factory());
auto var =
scope->DeclareParameter(name, VAR, is_optional, is_rest,
&is_duplicate, ast_value_factory(), beg_pos);
DCHECK(!is_duplicate);
var->AllocateTo(VariableLocation::PARAMETER, 0);
......@@ -892,7 +893,7 @@ FunctionLiteral* Parser::DoParseFunction(ParseInfo* info,
ParserFormalParameters formals(scope);
{
// Parsing patterns as variable reference expression creates
// NewUnresolved references in current scope. Entrer arrow function
// NewUnresolved references in current scope. Enter arrow function
// scope for formal parameter parsing.
BlockState block_state(&scope_, scope);
if (Check(Token::LPAREN)) {
......
......@@ -133,16 +133,18 @@ class Parser;
struct ParserFormalParameters : FormalParametersBase {
struct Parameter : public ZoneObject {
Parameter(const AstRawString* name, Expression* pattern,
Expression* initializer, int initializer_end_position,
bool is_rest)
Expression* initializer, int position,
int initializer_end_position, bool is_rest)
: name(name),
pattern(pattern),
initializer(initializer),
position(position),
initializer_end_position(initializer_end_position),
is_rest(is_rest) {}
const AstRawString* name;
Expression* pattern;
Expression* initializer;
int position;
int initializer_end_position;
bool is_rest;
Parameter* next_parameter = nullptr;
......@@ -1081,9 +1083,10 @@ class V8_EXPORT_PRIVATE Parser : public NON_EXPORTED_BASE(ParserBase<Parser>) {
const AstRawString* name = has_simple_name
? pattern->AsVariableProxy()->raw_name()
: ast_value_factory()->empty_string();
auto parameter =
new (parameters->scope->zone()) ParserFormalParameters::Parameter(
name, pattern, initializer, initializer_end_position, is_rest);
auto parameter = new (parameters->scope->zone())
ParserFormalParameters::Parameter(name, pattern, initializer,
scanner()->location().beg_pos,
initializer_end_position, is_rest);
parameters->params.Add(parameter);
}
......@@ -1103,7 +1106,7 @@ class V8_EXPORT_PRIVATE Parser : public NON_EXPORTED_BASE(ParserBase<Parser>) {
scope->DeclareParameter(
is_simple ? parameter->name : ast_value_factory()->empty_string(),
is_simple ? VAR : TEMPORARY, is_optional, parameter->is_rest,
&is_duplicate, ast_value_factory());
&is_duplicate, ast_value_factory(), parameter->position);
if (is_duplicate &&
classifier()->is_valid_formal_parameter_list_without_duplicates()) {
classifier()->RecordDuplicateFormalParameterError(
......
......@@ -707,7 +707,7 @@ RUNTIME_FUNCTION(Runtime_CollectTypeProfile) {
DCHECK(FLAG_type_profile);
Handle<Name> type = Object::TypeOf(isolate, value);
Handle<String> type = Object::TypeOf(isolate, value);
if (value->IsJSReceiver()) {
Handle<JSReceiver> object = Handle<JSReceiver>::cast(value);
type = JSReceiver::GetConstructorName(object);
......
......@@ -60,4 +60,11 @@ testReturnOfNonVariable();
function never_call() {}
%PrintTypeProfile(never_call);
throw "throw otherwise test fails with --stress-opt";
function check_param(a, bbb, ccccccccc, dddddddddddddddd) {
//nothing
}
check_param(2, 'foo', {}, new MyClass());
%PrintTypeProfile(check_param);
throw "end";
Function: testFunction
246: Object
246: number
246: string
246: number
247:
Object
number
string
number
254:
undefined
boolean
undefined
undefined
443:
Object
number
string
number
Function: testFunction
246: Object
246: number
246: string
246: number
246: undefined
246: string
246: Object
246: Object
246: MyClass
247:
Object
number
string
number
undefined
string
Object
Object
MyClass
254:
undefined
boolean
undefined
undefined
undefined
boolean
boolean
undefined
undefined
443:
Object
number
string
number
undefined
string
Object
Object
MyClass
Function: try_finally
956: string
1038:
string
Function: fall_off
1105: undefined
1122:
undefined
*%(basename)s:63: throw otherwise test fails with --stress-opt
throw "throw otherwise test fails with --stress-opt";
Function: check_param
1272:
number
1275:
string
1280:
Object
1291:
MyClass
1323:
undefined
*%(basename)s:70: end
throw "end";
^
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