From ff6ebf7dffc1706b62cc5ef37c4d7fdbdfdb5bef Mon Sep 17 00:00:00 2001 From: "vegorov@chromium.org" Date: Fri, 2 Mar 2012 11:33:33 +0000 Subject: [PATCH] Introduce basic type feedback for for-in statements to avoid deopts. R=fschneider@chromium.org Review URL: https://chromiumcodereview.appspot.com/9571001 git-svn-id: http://v8.googlecode.com/svn/branches/bleeding_edge@10901 ce2b1a6d-e550-0410-aec6-3dcde31c8c00 --- src/arm/full-codegen-arm.cc | 10 ++++++++++ src/hydrogen.cc | 4 ++++ src/ia32/full-codegen-ia32.cc | 10 ++++++++++ src/objects.h | 3 +++ src/type-info.cc | 14 +++++++++++--- src/type-info.h | 3 +++ src/x64/full-codegen-x64.cc | 10 ++++++++++ 7 files changed, 51 insertions(+), 3 deletions(-) diff --git a/src/arm/full-codegen-arm.cc b/src/arm/full-codegen-arm.cc index 418e0c5f7c..8639698051 100644 --- a/src/arm/full-codegen-arm.cc +++ b/src/arm/full-codegen-arm.cc @@ -1004,6 +1004,16 @@ void FullCodeGenerator::VisitForInStatement(ForInStatement* stmt) { // We got a fixed array in register r0. Iterate through that. Label non_proxy; __ bind(&fixed_array); + + Handle cell = + isolate()->factory()->NewJSGlobalPropertyCell( + Handle( + Smi::FromInt(TypeFeedbackCells::kForInFastCaseMarker))); + RecordTypeFeedbackCell(stmt->PrepareId(), cell); + __ LoadHeapObject(r1, cell); + __ mov(r2, Operand(Smi::FromInt(TypeFeedbackCells::kForInSlowCaseMarker))); + __ str(r2, FieldMemOperand(r1, JSGlobalPropertyCell::kValueOffset)); + __ mov(r1, Operand(Smi::FromInt(1))); // Smi indicates slow check __ ldr(r2, MemOperand(sp, 0 * kPointerSize)); // Get enumerated object STATIC_ASSERT(FIRST_JS_PROXY_TYPE == FIRST_SPEC_OBJECT_TYPE); diff --git a/src/hydrogen.cc b/src/hydrogen.cc index cbcf32f12b..ee02b68ec3 100644 --- a/src/hydrogen.cc +++ b/src/hydrogen.cc @@ -3274,6 +3274,10 @@ void HGraphBuilder::VisitForInStatement(ForInStatement* stmt) { return Bailout("ForInStatement optimization is disabled"); } + if (!oracle()->IsForInFastCase(stmt)) { + return Bailout("ForInStatement is not fast case"); + } + if (!stmt->each()->IsVariableProxy() || !stmt->each()->AsVariableProxy()->var()->IsStackLocal()) { return Bailout("ForInStatement with non-local each variable"); diff --git a/src/ia32/full-codegen-ia32.cc b/src/ia32/full-codegen-ia32.cc index 0b7c7fd451..86ca138ad2 100644 --- a/src/ia32/full-codegen-ia32.cc +++ b/src/ia32/full-codegen-ia32.cc @@ -1033,6 +1033,16 @@ void FullCodeGenerator::VisitForInStatement(ForInStatement* stmt) { // We got a fixed array in register eax. Iterate through that. Label non_proxy; __ bind(&fixed_array); + + Handle cell = + isolate()->factory()->NewJSGlobalPropertyCell( + Handle( + Smi::FromInt(TypeFeedbackCells::kForInFastCaseMarker))); + RecordTypeFeedbackCell(stmt->PrepareId(), cell); + __ LoadHeapObject(ebx, cell); + __ mov(FieldOperand(ebx, JSGlobalPropertyCell::kValueOffset), + Immediate(Smi::FromInt(TypeFeedbackCells::kForInSlowCaseMarker))); + __ mov(ebx, Immediate(Smi::FromInt(1))); // Smi indicates slow check __ mov(ecx, Operand(esp, 0 * kPointerSize)); // Get enumerated object STATIC_ASSERT(FIRST_JS_PROXY_TYPE == FIRST_SPEC_OBJECT_TYPE); diff --git a/src/objects.h b/src/objects.h index be75faba65..7d8a55e7de 100644 --- a/src/objects.h +++ b/src/objects.h @@ -4063,6 +4063,9 @@ class TypeFeedbackCells: public FixedArray { // Casting. static inline TypeFeedbackCells* cast(Object* obj); + + static const int kForInFastCaseMarker = 0; + static const int kForInSlowCaseMarker = 1; }; diff --git a/src/type-info.cc b/src/type-info.cc index 81cbff3b0a..fa479b2e51 100644 --- a/src/type-info.cc +++ b/src/type-info.cc @@ -154,6 +154,13 @@ bool TypeFeedbackOracle::CallNewIsMonomorphic(CallNew* expr) { } +bool TypeFeedbackOracle::IsForInFastCase(ForInStatement* stmt) { + Handle value = GetInfo(stmt->PrepareId()); + return value->IsSmi() && + Smi::cast(*value)->value() == TypeFeedbackCells::kForInFastCaseMarker; +} + + Handle TypeFeedbackOracle::LoadMonomorphicReceiverType(Property* expr) { ASSERT(LoadIsMonomorphicNormal(expr)); Handle map_or_code = GetInfo(expr->id()); @@ -659,9 +666,10 @@ void TypeFeedbackOracle::ProcessTypeFeedbackCells(Handle code) { for (int i = 0; i < cache->CellCount(); i++) { unsigned ast_id = cache->AstId(i)->value(); Object* value = cache->Cell(i)->value(); - if (value->IsJSFunction() && - !CanRetainOtherContext(JSFunction::cast(value), - *global_context_)) { + if (value->IsSmi() || + (value->IsJSFunction() && + !CanRetainOtherContext(JSFunction::cast(value), + *global_context_))) { SetInfo(ast_id, value); } } diff --git a/src/type-info.h b/src/type-info.h index 19a309bc8d..84ec51d975 100644 --- a/src/type-info.h +++ b/src/type-info.h @@ -228,6 +228,7 @@ class Expression; class Property; class SmallMapList; class UnaryOperation; +class ForInStatement; class TypeFeedbackOracle BASE_EMBEDDED { @@ -243,6 +244,8 @@ class TypeFeedbackOracle BASE_EMBEDDED { bool CallIsMonomorphic(Call* expr); bool CallNewIsMonomorphic(CallNew* expr); + bool IsForInFastCase(ForInStatement* expr); + Handle LoadMonomorphicReceiverType(Property* expr); Handle StoreMonomorphicReceiverType(Expression* expr); diff --git a/src/x64/full-codegen-x64.cc b/src/x64/full-codegen-x64.cc index a9bf9a80e7..7a60adc0b3 100644 --- a/src/x64/full-codegen-x64.cc +++ b/src/x64/full-codegen-x64.cc @@ -969,6 +969,16 @@ void FullCodeGenerator::VisitForInStatement(ForInStatement* stmt) { // We got a fixed array in register rax. Iterate through that. Label non_proxy; __ bind(&fixed_array); + + Handle cell = + isolate()->factory()->NewJSGlobalPropertyCell( + Handle( + Smi::FromInt(TypeFeedbackCells::kForInFastCaseMarker))); + RecordTypeFeedbackCell(stmt->PrepareId(), cell); + __ LoadHeapObject(rbx, cell); + __ Move(FieldOperand(rbx, JSGlobalPropertyCell::kValueOffset), + Smi::FromInt(TypeFeedbackCells::kForInSlowCaseMarker)); + __ Move(rbx, Smi::FromInt(1)); // Smi indicates slow check __ movq(rcx, Operand(rsp, 0 * kPointerSize)); // Get enumerated object STATIC_ASSERT(FIRST_JS_PROXY_TYPE == FIRST_SPEC_OBJECT_TYPE);