CallNewArray sites need the original feedback cell at crankshaft time.
This CL addresses a TODO in the hydrogen-based array constructor code, to pass through the actual type feedback cell, rather than the contents of the cell. BUG= R=danno@chromium.org Review URL: https://codereview.chromium.org/16408005 git-svn-id: http://v8.googlecode.com/svn/branches/bleeding_edge@15004 ce2b1a6d-e550-0410-aec6-3dcde31c8c00
This commit is contained in:
parent
9595a691b0
commit
1fc6065b38
12
src/ast.cc
12
src/ast.cc
@ -655,17 +655,15 @@ void Call::RecordTypeFeedback(TypeFeedbackOracle* oracle,
|
|||||||
|
|
||||||
|
|
||||||
void CallNew::RecordTypeFeedback(TypeFeedbackOracle* oracle) {
|
void CallNew::RecordTypeFeedback(TypeFeedbackOracle* oracle) {
|
||||||
|
allocation_info_cell_ = oracle->GetCallNewAllocationInfoCell(this);
|
||||||
is_monomorphic_ = oracle->CallNewIsMonomorphic(this);
|
is_monomorphic_ = oracle->CallNewIsMonomorphic(this);
|
||||||
if (is_monomorphic_) {
|
if (is_monomorphic_) {
|
||||||
target_ = oracle->GetCallNewTarget(this);
|
target_ = oracle->GetCallNewTarget(this);
|
||||||
elements_kind_ = oracle->GetCallNewElementsKind(this);
|
Object* value = allocation_info_cell_->value();
|
||||||
|
if (value->IsSmi()) {
|
||||||
|
elements_kind_ = static_cast<ElementsKind>(Smi::cast(value)->value());
|
||||||
|
}
|
||||||
}
|
}
|
||||||
Handle<Object> alloc_elements_kind = oracle->GetInfo(CallNewFeedbackId());
|
|
||||||
// if (alloc_elements_kind->IsSmi())
|
|
||||||
// alloc_elements_kind_ = Handle<Smi>::cast(alloc_elements_kind);
|
|
||||||
alloc_elements_kind_ = alloc_elements_kind->IsSmi()
|
|
||||||
? Handle<Smi>::cast(alloc_elements_kind)
|
|
||||||
: handle(Smi::FromInt(GetInitialFastElementsKind()), oracle->isolate());
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -1765,7 +1765,9 @@ class CallNew: public Expression {
|
|||||||
virtual bool IsMonomorphic() { return is_monomorphic_; }
|
virtual bool IsMonomorphic() { return is_monomorphic_; }
|
||||||
Handle<JSFunction> target() const { return target_; }
|
Handle<JSFunction> target() const { return target_; }
|
||||||
ElementsKind elements_kind() const { return elements_kind_; }
|
ElementsKind elements_kind() const { return elements_kind_; }
|
||||||
Handle<Smi> allocation_elements_kind() const { return alloc_elements_kind_; }
|
Handle<JSGlobalPropertyCell> allocation_info_cell() const {
|
||||||
|
return allocation_info_cell_;
|
||||||
|
}
|
||||||
|
|
||||||
BailoutId ReturnId() const { return return_id_; }
|
BailoutId ReturnId() const { return return_id_; }
|
||||||
|
|
||||||
@ -1790,7 +1792,7 @@ class CallNew: public Expression {
|
|||||||
bool is_monomorphic_;
|
bool is_monomorphic_;
|
||||||
Handle<JSFunction> target_;
|
Handle<JSFunction> target_;
|
||||||
ElementsKind elements_kind_;
|
ElementsKind elements_kind_;
|
||||||
Handle<Smi> alloc_elements_kind_;
|
Handle<JSGlobalPropertyCell> allocation_info_cell_;
|
||||||
|
|
||||||
const BailoutId return_id_;
|
const BailoutId return_id_;
|
||||||
};
|
};
|
||||||
|
@ -8923,18 +8923,7 @@ void HOptimizedGraphBuilder::VisitCallNew(CallNew* expr) {
|
|||||||
CHECK_ALIVE(VisitArgumentList(expr->arguments()));
|
CHECK_ALIVE(VisitArgumentList(expr->arguments()));
|
||||||
HCallNew* call;
|
HCallNew* call;
|
||||||
if (use_call_new_array) {
|
if (use_call_new_array) {
|
||||||
// TODO(mvstanton): It would be better to use the already created global
|
Handle<JSGlobalPropertyCell> cell = expr->allocation_info_cell();
|
||||||
// property cell that is shared by full code gen. That way, any transition
|
|
||||||
// information that happened after crankshaft won't be lost. The right
|
|
||||||
// way to do that is to begin passing the cell to the type feedback oracle
|
|
||||||
// instead of just the value in the cell. Do this in a follow-up checkin.
|
|
||||||
Handle<Smi> feedback = expr->allocation_elements_kind();
|
|
||||||
Handle<JSGlobalPropertyCell> cell =
|
|
||||||
isolate()->factory()->NewJSGlobalPropertyCell(feedback);
|
|
||||||
|
|
||||||
// TODO(mvstanton): Here we should probably insert code to check if the
|
|
||||||
// type cell elements kind is different from when we compiled, and deopt
|
|
||||||
// in that case. Do this in a follow-up checin.
|
|
||||||
call = new(zone()) HCallNewArray(context, constructor, argument_count,
|
call = new(zone()) HCallNewArray(context, constructor, argument_count,
|
||||||
cell);
|
cell);
|
||||||
} else {
|
} else {
|
||||||
|
@ -78,9 +78,28 @@ static uint32_t IdToKey(TypeFeedbackId ast_id) {
|
|||||||
|
|
||||||
Handle<Object> TypeFeedbackOracle::GetInfo(TypeFeedbackId ast_id) {
|
Handle<Object> TypeFeedbackOracle::GetInfo(TypeFeedbackId ast_id) {
|
||||||
int entry = dictionary_->FindEntry(IdToKey(ast_id));
|
int entry = dictionary_->FindEntry(IdToKey(ast_id));
|
||||||
return entry != UnseededNumberDictionary::kNotFound
|
if (entry != UnseededNumberDictionary::kNotFound) {
|
||||||
? Handle<Object>(dictionary_->ValueAt(entry), isolate_)
|
Object* value = dictionary_->ValueAt(entry);
|
||||||
: Handle<Object>::cast(isolate_->factory()->undefined_value());
|
if (value->IsJSGlobalPropertyCell()) {
|
||||||
|
JSGlobalPropertyCell* cell = JSGlobalPropertyCell::cast(value);
|
||||||
|
return Handle<Object>(cell->value(), isolate_);
|
||||||
|
} else {
|
||||||
|
return Handle<Object>(value, isolate_);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return Handle<Object>::cast(isolate_->factory()->undefined_value());
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
Handle<JSGlobalPropertyCell> TypeFeedbackOracle::GetInfoCell(
|
||||||
|
TypeFeedbackId ast_id) {
|
||||||
|
int entry = dictionary_->FindEntry(IdToKey(ast_id));
|
||||||
|
if (entry != UnseededNumberDictionary::kNotFound) {
|
||||||
|
JSGlobalPropertyCell* cell = JSGlobalPropertyCell::cast(
|
||||||
|
dictionary_->ValueAt(entry));
|
||||||
|
return Handle<JSGlobalPropertyCell>(cell, isolate_);
|
||||||
|
}
|
||||||
|
return Handle<JSGlobalPropertyCell>::null();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -316,21 +335,12 @@ Handle<JSFunction> TypeFeedbackOracle::GetCallNewTarget(CallNew* expr) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
ElementsKind TypeFeedbackOracle::GetCallNewElementsKind(CallNew* expr) {
|
Handle<JSGlobalPropertyCell> TypeFeedbackOracle::GetCallNewAllocationInfoCell(
|
||||||
Handle<Object> info = GetInfo(expr->CallNewFeedbackId());
|
CallNew* expr) {
|
||||||
if (info->IsSmi()) {
|
return GetInfoCell(expr->CallNewFeedbackId());
|
||||||
return static_cast<ElementsKind>(Smi::cast(*info)->value());
|
|
||||||
} else {
|
|
||||||
// TODO(mvstanton): avoided calling GetInitialFastElementsKind() for perf
|
|
||||||
// reasons. Is there a better fix?
|
|
||||||
if (FLAG_packed_arrays) {
|
|
||||||
return FAST_SMI_ELEMENTS;
|
|
||||||
} else {
|
|
||||||
return FAST_HOLEY_SMI_ELEMENTS;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
Handle<Map> TypeFeedbackOracle::GetObjectLiteralStoreMap(
|
Handle<Map> TypeFeedbackOracle::GetObjectLiteralStoreMap(
|
||||||
ObjectLiteral::Property* prop) {
|
ObjectLiteral::Property* prop) {
|
||||||
ASSERT(ObjectLiteralStoreIsMonomorphic(prop));
|
ASSERT(ObjectLiteralStoreIsMonomorphic(prop));
|
||||||
@ -749,12 +759,13 @@ void TypeFeedbackOracle::ProcessTypeFeedbackCells(Handle<Code> code) {
|
|||||||
TypeFeedbackInfo::cast(raw_info)->type_feedback_cells());
|
TypeFeedbackInfo::cast(raw_info)->type_feedback_cells());
|
||||||
for (int i = 0; i < cache->CellCount(); i++) {
|
for (int i = 0; i < cache->CellCount(); i++) {
|
||||||
TypeFeedbackId ast_id = cache->AstId(i);
|
TypeFeedbackId ast_id = cache->AstId(i);
|
||||||
Object* value = cache->Cell(i)->value();
|
JSGlobalPropertyCell* cell = cache->Cell(i);
|
||||||
|
Object* value = cell->value();
|
||||||
if (value->IsSmi() ||
|
if (value->IsSmi() ||
|
||||||
(value->IsJSFunction() &&
|
(value->IsJSFunction() &&
|
||||||
!CanRetainOtherContext(JSFunction::cast(value),
|
!CanRetainOtherContext(JSFunction::cast(value),
|
||||||
*native_context_))) {
|
*native_context_))) {
|
||||||
SetInfo(ast_id, value);
|
SetInfo(ast_id, cell);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -283,7 +283,7 @@ class TypeFeedbackOracle: public ZoneObject {
|
|||||||
CheckType GetCallCheckType(Call* expr);
|
CheckType GetCallCheckType(Call* expr);
|
||||||
Handle<JSFunction> GetCallTarget(Call* expr);
|
Handle<JSFunction> GetCallTarget(Call* expr);
|
||||||
Handle<JSFunction> GetCallNewTarget(CallNew* expr);
|
Handle<JSFunction> GetCallNewTarget(CallNew* expr);
|
||||||
ElementsKind GetCallNewElementsKind(CallNew* expr);
|
Handle<JSGlobalPropertyCell> GetCallNewAllocationInfoCell(CallNew* expr);
|
||||||
|
|
||||||
Handle<Map> GetObjectLiteralStoreMap(ObjectLiteralProperty* prop);
|
Handle<Map> GetObjectLiteralStoreMap(ObjectLiteralProperty* prop);
|
||||||
|
|
||||||
@ -338,11 +338,11 @@ class TypeFeedbackOracle: public ZoneObject {
|
|||||||
|
|
||||||
// Returns an element from the backing store. Returns undefined if
|
// Returns an element from the backing store. Returns undefined if
|
||||||
// there is no information.
|
// there is no information.
|
||||||
public:
|
|
||||||
// TODO(mvstanton): how to get this information without making the method
|
|
||||||
// public?
|
|
||||||
Handle<Object> GetInfo(TypeFeedbackId ast_id);
|
Handle<Object> GetInfo(TypeFeedbackId ast_id);
|
||||||
|
|
||||||
|
// Return the cell that contains type feedback.
|
||||||
|
Handle<JSGlobalPropertyCell> GetInfoCell(TypeFeedbackId ast_id);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
Handle<Context> native_context_;
|
Handle<Context> native_context_;
|
||||||
Isolate* isolate_;
|
Isolate* isolate_;
|
||||||
|
Loading…
Reference in New Issue
Block a user