diff options
Diffstat (limited to 'chromium/v8/src/ast.cc')
-rw-r--r-- | chromium/v8/src/ast.cc | 252 |
1 files changed, 197 insertions, 55 deletions
diff --git a/chromium/v8/src/ast.cc b/chromium/v8/src/ast.cc index 5038716003e..e52504a86fb 100644 --- a/chromium/v8/src/ast.cc +++ b/chromium/v8/src/ast.cc @@ -54,7 +54,7 @@ bool Expression::IsUndefinedLiteral(Isolate* isolate) const { Variable* var = var_proxy->var(); // The global identifier "undefined" is immutable. Everything // else could be reassigned. - return var != NULL && var->location() == Variable::UNALLOCATED && + return var != NULL && var->IsUnallocatedOrGlobalSlot() && var_proxy->raw_name()->IsOneByteEqualTo("undefined"); } @@ -95,8 +95,8 @@ void VariableProxy::BindTo(Variable* var) { void VariableProxy::SetFirstFeedbackICSlot(FeedbackVectorICSlot slot, ICSlotCache* cache) { variable_feedback_slot_ = slot; - if (var()->IsUnallocated()) { - cache->Add(VariableICSlotPair(var(), slot)); + if (var()->IsUnallocatedOrGlobalSlot()) { + cache->Put(var(), slot); } } @@ -106,13 +106,12 @@ FeedbackVectorRequirements VariableProxy::ComputeFeedbackRequirements( if (UsesVariableFeedbackSlot()) { // VariableProxies that point to the same Variable within a function can // make their loads from the same IC slot. - if (var()->IsUnallocated()) { - for (int i = 0; i < cache->length(); i++) { - VariableICSlotPair& pair = cache->at(i); - if (pair.variable() == var()) { - variable_feedback_slot_ = pair.slot(); - return FeedbackVectorRequirements(0, 0); - } + if (var()->IsUnallocatedOrGlobalSlot()) { + ZoneHashMap::Entry* entry = cache->Get(var()); + if (entry != NULL) { + variable_feedback_slot_ = FeedbackVectorICSlot( + static_cast<int>(reinterpret_cast<intptr_t>(entry->value))); + return FeedbackVectorRequirements(0, 0); } } return FeedbackVectorRequirements(0, 1); @@ -121,16 +120,73 @@ FeedbackVectorRequirements VariableProxy::ComputeFeedbackRequirements( } +static int GetStoreICSlots(Expression* expr) { + int ic_slots = 0; + if (FLAG_vector_stores) { + Property* property = expr->AsProperty(); + LhsKind assign_type = Property::GetAssignType(property); + if ((assign_type == VARIABLE && + expr->AsVariableProxy()->var()->IsUnallocatedOrGlobalSlot()) || + assign_type == NAMED_PROPERTY || assign_type == KEYED_PROPERTY) { + ic_slots++; + } + } + return ic_slots; +} + + +static Code::Kind GetStoreICKind(Expression* expr) { + LhsKind assign_type = Property::GetAssignType(expr->AsProperty()); + return assign_type == KEYED_PROPERTY ? Code::KEYED_STORE_IC : Code::STORE_IC; +} + + +FeedbackVectorRequirements ForEachStatement::ComputeFeedbackRequirements( + Isolate* isolate, const ICSlotCache* cache) { + int ic_slots = GetStoreICSlots(each()); + return FeedbackVectorRequirements(0, ic_slots); +} + + +Code::Kind ForEachStatement::FeedbackICSlotKind(int index) { + return GetStoreICKind(each()); +} + + Assignment::Assignment(Zone* zone, Token::Value op, Expression* target, Expression* value, int pos) : Expression(zone, pos), - bit_field_(IsUninitializedField::encode(false) | - KeyTypeField::encode(ELEMENT) | - StoreModeField::encode(STANDARD_STORE) | - TokenField::encode(op)), + bit_field_( + IsUninitializedField::encode(false) | KeyTypeField::encode(ELEMENT) | + StoreModeField::encode(STANDARD_STORE) | TokenField::encode(op)), target_(target), value_(value), - binary_operation_(NULL) {} + binary_operation_(NULL), + slot_(FeedbackVectorICSlot::Invalid()) {} + + +FeedbackVectorRequirements Assignment::ComputeFeedbackRequirements( + Isolate* isolate, const ICSlotCache* cache) { + int ic_slots = GetStoreICSlots(target()); + return FeedbackVectorRequirements(0, ic_slots); +} + + +Code::Kind Assignment::FeedbackICSlotKind(int index) { + return GetStoreICKind(target()); +} + + +FeedbackVectorRequirements CountOperation::ComputeFeedbackRequirements( + Isolate* isolate, const ICSlotCache* cache) { + int ic_slots = GetStoreICSlots(expression()); + return FeedbackVectorRequirements(0, ic_slots); +} + + +Code::Kind CountOperation::FeedbackICSlotKind(int index) { + return GetStoreICKind(expression()); +} Token::Value Assignment::binary_op() const { @@ -177,28 +233,10 @@ LanguageMode FunctionLiteral::language_mode() const { } -bool FunctionLiteral::uses_super_property() const { - DCHECK_NOT_NULL(scope()); - return scope()->uses_super_property() || scope()->inner_uses_super_property(); -} - - -// Helper to find an existing shared function info in the baseline code for the -// given function literal. Used to canonicalize SharedFunctionInfo objects. -void FunctionLiteral::InitializeSharedInfo( - Handle<Code> unoptimized_code) { - for (RelocIterator it(*unoptimized_code); !it.done(); it.next()) { - RelocInfo* rinfo = it.rinfo(); - if (rinfo->rmode() != RelocInfo::EMBEDDED_OBJECT) continue; - Object* obj = rinfo->target_object(); - if (obj->IsSharedFunctionInfo()) { - SharedFunctionInfo* shared = SharedFunctionInfo::cast(obj); - if (shared->start_position() == start_position()) { - shared_info_ = Handle<SharedFunctionInfo>(shared); - break; - } - } - } +bool FunctionLiteral::NeedsHomeObject(Expression* expr) { + if (expr == nullptr || !expr->IsFunctionLiteral()) return false; + DCHECK_NOT_NULL(expr->AsFunctionLiteral()->scope()); + return expr->AsFunctionLiteral()->scope()->NeedsHomeObject(); } @@ -236,6 +274,46 @@ ObjectLiteralProperty::ObjectLiteralProperty(AstValueFactory* ast_value_factory, } +FeedbackVectorRequirements ClassLiteral::ComputeFeedbackRequirements( + Isolate* isolate, const ICSlotCache* cache) { + if (!FLAG_vector_stores) return FeedbackVectorRequirements(0, 0); + + // This logic that computes the number of slots needed for vector store + // ICs must mirror FullCodeGenerator::VisitClassLiteral. + int ic_slots = 0; + for (int i = 0; i < properties()->length(); i++) { + ObjectLiteral::Property* property = properties()->at(i); + + Expression* value = property->value(); + if (FunctionLiteral::NeedsHomeObject(value)) ic_slots++; + } + + if (scope() != NULL && + class_variable_proxy()->var()->IsUnallocatedOrGlobalSlot()) { + ic_slots++; + } + +#ifdef DEBUG + // FullCodeGenerator::VisitClassLiteral verifies that it consumes slot_count_ + // slots. + slot_count_ = ic_slots; +#endif + return FeedbackVectorRequirements(0, ic_slots); +} + + +FeedbackVectorICSlot ClassLiteral::SlotForHomeObject(Expression* value, + int* slot_index) const { + if (FLAG_vector_stores && FunctionLiteral::NeedsHomeObject(value)) { + DCHECK(slot_index != NULL && *slot_index >= 0 && *slot_index < slot_count_); + FeedbackVectorICSlot slot = GetNthSlot(*slot_index); + *slot_index += 1; + return slot; + } + return FeedbackVectorICSlot::Invalid(); +} + + bool ObjectLiteral::Property::IsCompileTimeValue() { return kind_ == CONSTANT || (kind_ == MATERIALIZED_LITERAL && @@ -253,6 +331,56 @@ bool ObjectLiteral::Property::emit_store() { } +FeedbackVectorRequirements ObjectLiteral::ComputeFeedbackRequirements( + Isolate* isolate, const ICSlotCache* cache) { + if (!FLAG_vector_stores) return FeedbackVectorRequirements(0, 0); + + // This logic that computes the number of slots needed for vector store + // ics must mirror FullCodeGenerator::VisitObjectLiteral. + int ic_slots = 0; + for (int i = 0; i < properties()->length(); i++) { + ObjectLiteral::Property* property = properties()->at(i); + if (property->IsCompileTimeValue()) continue; + + Expression* value = property->value(); + if (property->is_computed_name() && + property->kind() != ObjectLiteral::Property::PROTOTYPE) { + if (FunctionLiteral::NeedsHomeObject(value)) ic_slots++; + } else if (property->emit_store()) { + if (property->kind() == ObjectLiteral::Property::MATERIALIZED_LITERAL || + property->kind() == ObjectLiteral::Property::COMPUTED) { + Literal* key = property->key()->AsLiteral(); + if (key->value()->IsInternalizedString()) ic_slots++; + if (FunctionLiteral::NeedsHomeObject(value)) ic_slots++; + } else if (property->kind() == ObjectLiteral::Property::GETTER || + property->kind() == ObjectLiteral::Property::SETTER) { + // We might need a slot for the home object. + if (FunctionLiteral::NeedsHomeObject(value)) ic_slots++; + } + } + } + +#ifdef DEBUG + // FullCodeGenerator::VisitObjectLiteral verifies that it consumes slot_count_ + // slots. + slot_count_ = ic_slots; +#endif + return FeedbackVectorRequirements(0, ic_slots); +} + + +FeedbackVectorICSlot ObjectLiteral::SlotForHomeObject(Expression* value, + int* slot_index) const { + if (FLAG_vector_stores && FunctionLiteral::NeedsHomeObject(value)) { + DCHECK(slot_index != NULL && *slot_index >= 0 && *slot_index < slot_count_); + FeedbackVectorICSlot slot = GetNthSlot(*slot_index); + *slot_index += 1; + return slot; + } + return FeedbackVectorICSlot::Invalid(); +} + + void ObjectLiteral::CalculateEmitStore(Zone* zone) { const auto GETTER = ObjectLiteral::Property::GETTER; const auto SETTER = ObjectLiteral::Property::SETTER; @@ -378,16 +506,18 @@ void ArrayLiteral::BuildConstantElements(Isolate* isolate) { if (!constant_elements_.is_null()) return; // Allocate a fixed array to hold all the object literals. - Handle<JSArray> array = - isolate->factory()->NewJSArray(0, FAST_HOLEY_SMI_ELEMENTS); - JSArray::Expand(array, values()->length()); + Handle<JSArray> array = isolate->factory()->NewJSArray( + FAST_HOLEY_SMI_ELEMENTS, values()->length(), values()->length(), + Strength::WEAK, INITIALIZE_ARRAY_ELEMENTS_WITH_HOLE); // Fill in the literals. bool is_simple = true; int depth_acc = 1; bool is_holey = false; - for (int i = 0, n = values()->length(); i < n; i++) { - Expression* element = values()->at(i); + int array_index = 0; + for (int n = values()->length(); array_index < n; array_index++) { + Expression* element = values()->at(array_index); + if (element->IsSpread()) break; MaterializedLiteral* m_literal = element->AsMaterializedLiteral(); if (m_literal != NULL) { m_literal->BuildConstants(isolate); @@ -395,23 +525,33 @@ void ArrayLiteral::BuildConstantElements(Isolate* isolate) { depth_acc = m_literal->depth() + 1; } } + + // New handle scope here, needs to be after BuildContants(). + HandleScope scope(isolate); Handle<Object> boilerplate_value = GetBoilerplateValue(element, isolate); if (boilerplate_value->IsTheHole()) { is_holey = true; - } else if (boilerplate_value->IsUninitialized()) { + continue; + } + + if (boilerplate_value->IsUninitialized()) { + boilerplate_value = handle(Smi::FromInt(0), isolate); is_simple = false; - JSObject::SetOwnElement( - array, i, handle(Smi::FromInt(0), isolate), SLOPPY).Assert(); - } else { - JSObject::SetOwnElement(array, i, boilerplate_value, SLOPPY).Assert(); } + + JSObject::AddDataElement(array, array_index, boilerplate_value, NONE) + .Assert(); } + if (array_index != values()->length()) { + JSArray::SetLength(array, array_index); + } + JSObject::ValidateElements(array); Handle<FixedArrayBase> element_values(array->elements()); // Simple and shallow arrays can be lazily copied, we transform the // elements array to a copy-on-write array. - if (is_simple && depth_acc == 1 && values()->length() > 0 && + if (is_simple && depth_acc == 1 && array_index > 0 && array->HasFastSmiOrObjectElements()) { element_values->set_map(isolate->heap()->fixed_cow_array_map()); } @@ -582,7 +722,10 @@ void Expression::RecordToBooleanTypeFeedback(TypeFeedbackOracle* oracle) { bool Call::IsUsingCallFeedbackICSlot(Isolate* isolate) const { CallType call_type = GetCallType(isolate); - if (IsUsingCallFeedbackSlot(isolate) || call_type == POSSIBLY_EVAL_CALL) { + if (call_type == POSSIBLY_EVAL_CALL) { + return false; + } + if (call_type == SUPER_CALL && !FLAG_vector_stores) { return false; } return true; @@ -591,7 +734,7 @@ bool Call::IsUsingCallFeedbackICSlot(Isolate* isolate) const { bool Call::IsUsingCallFeedbackSlot(Isolate* isolate) const { // SuperConstructorCall uses a CallConstructStub, which wants - // a Slot, not an IC slot. + // a Slot, in addition to any IC slots requested elsewhere. return GetCallType(isolate) == SUPER_CALL; } @@ -600,8 +743,6 @@ FeedbackVectorRequirements Call::ComputeFeedbackRequirements( Isolate* isolate, const ICSlotCache* cache) { int ic_slots = IsUsingCallFeedbackICSlot(isolate) ? 1 : 0; int slots = IsUsingCallFeedbackSlot(isolate) ? 1 : 0; - // A Call uses either a slot or an IC slot. - DCHECK((ic_slots & slots) == 0); return FeedbackVectorRequirements(slots, ic_slots); } @@ -611,14 +752,14 @@ Call::CallType Call::GetCallType(Isolate* isolate) const { if (proxy != NULL) { if (proxy->var()->is_possibly_eval(isolate)) { return POSSIBLY_EVAL_CALL; - } else if (proxy->var()->IsUnallocated()) { + } else if (proxy->var()->IsUnallocatedOrGlobalSlot()) { return GLOBAL_CALL; } else if (proxy->var()->IsLookupSlot()) { return LOOKUP_SLOT_CALL; } } - if (expression()->AsSuperReference() != NULL) return SUPER_CALL; + if (expression()->IsSuperCallReference()) return SUPER_CALL; Property* property = expression()->AsProperty(); return property != NULL ? PROPERTY_CALL : OTHER_CALL; @@ -1009,4 +1150,5 @@ bool Literal::Match(void* literal1, void* literal2) { } -} } // namespace v8::internal +} // namespace internal +} // namespace v8 |