summaryrefslogtreecommitdiffstats
path: root/chromium/v8/src/typing.cc
diff options
context:
space:
mode:
Diffstat (limited to 'chromium/v8/src/typing.cc')
-rw-r--r--chromium/v8/src/typing.cc249
1 files changed, 145 insertions, 104 deletions
diff --git a/chromium/v8/src/typing.cc b/chromium/v8/src/typing.cc
index 9458d6dc2fe..7762624b073 100644
--- a/chromium/v8/src/typing.cc
+++ b/chromium/v8/src/typing.cc
@@ -1,34 +1,13 @@
// Copyright 2013 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:
-//
-// * Redistributions of source code must retain the above copyright
-// notice, this list of conditions and the following disclaimer.
-// * Redistributions in binary form must reproduce the above
-// copyright notice, this list of conditions and the following
-// disclaimer in the documentation and/or other materials provided
-// with the distribution.
-// * Neither the name of Google Inc. nor the names of its
-// contributors may be used to endorse or promote products derived
-// from this software without specific prior written permission.
-//
-// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
-// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
-// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
-// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
-// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
-// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
-// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
-// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
-// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
-// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-
-#include "typing.h"
-
-#include "parser.h" // for CompileTimeValue; TODO(rossberg): should move
-#include "scopes.h"
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "src/typing.h"
+
+#include "src/frames.h"
+#include "src/frames-inl.h"
+#include "src/parser.h" // for CompileTimeValue; TODO(rossberg): should move
+#include "src/scopes.h"
namespace v8 {
namespace internal {
@@ -37,12 +16,12 @@ namespace internal {
AstTyper::AstTyper(CompilationInfo* info)
: info_(info),
oracle_(
- Handle<Code>(info->closure()->shared()->code()),
- Handle<Context>(info->closure()->context()->native_context()),
- info->isolate(),
+ handle(info->closure()->shared()->code()),
+ handle(info->closure()->shared()->feedback_vector()),
+ handle(info->closure()->context()->native_context()),
info->zone()),
store_(info->zone()) {
- InitializeAstVisitor(info->isolate());
+ InitializeAstVisitor(info->zone());
}
@@ -68,6 +47,75 @@ void AstTyper::Run(CompilationInfo* info) {
#undef RECURSE
+
+#ifdef OBJECT_PRINT
+ static void PrintObserved(Variable* var, Object* value, Type* type) {
+ PrintF(" observed %s ", var->IsParameter() ? "param" : "local");
+ var->name()->Print();
+ PrintF(" : ");
+ value->ShortPrint();
+ PrintF(" -> ");
+ type->TypePrint();
+ }
+#endif // OBJECT_PRINT
+
+
+Effect AstTyper::ObservedOnStack(Object* value) {
+ Type* lower = Type::NowOf(value, zone());
+ return Effect(Bounds(lower, Type::Any(zone())));
+}
+
+
+void AstTyper::ObserveTypesAtOsrEntry(IterationStatement* stmt) {
+ if (stmt->OsrEntryId() != info_->osr_ast_id()) return;
+
+ DisallowHeapAllocation no_gc;
+ JavaScriptFrameIterator it(isolate());
+ JavaScriptFrame* frame = it.frame();
+ Scope* scope = info_->scope();
+
+ // Assert that the frame on the stack belongs to the function we want to OSR.
+ ASSERT_EQ(*info_->closure(), frame->function());
+
+ int params = scope->num_parameters();
+ int locals = scope->StackLocalCount();
+
+ // Use sequential composition to achieve desired narrowing.
+ // The receiver is a parameter with index -1.
+ store_.Seq(parameter_index(-1), ObservedOnStack(frame->receiver()));
+ for (int i = 0; i < params; i++) {
+ store_.Seq(parameter_index(i), ObservedOnStack(frame->GetParameter(i)));
+ }
+
+ for (int i = 0; i < locals; i++) {
+ store_.Seq(stack_local_index(i), ObservedOnStack(frame->GetExpression(i)));
+ }
+
+#ifdef OBJECT_PRINT
+ if (FLAG_trace_osr && FLAG_print_scopes) {
+ PrintObserved(scope->receiver(),
+ frame->receiver(),
+ store_.LookupBounds(parameter_index(-1)).lower);
+
+ for (int i = 0; i < params; i++) {
+ PrintObserved(scope->parameter(i),
+ frame->GetParameter(i),
+ store_.LookupBounds(parameter_index(i)).lower);
+ }
+
+ ZoneList<Variable*> local_vars(locals, zone());
+ ZoneList<Variable*> context_vars(scope->ContextLocalCount(), zone());
+ scope->CollectStackAndContextLocals(&local_vars, &context_vars);
+ for (int i = 0; i < locals; i++) {
+ PrintObserved(local_vars.at(i),
+ frame->GetExpression(i),
+ store_.LookupBounds(stack_local_index(i)).lower);
+ }
+ }
+#endif // OBJECT_PRINT
+}
+
+
#define RECURSE(call) \
do { \
ASSERT(!HasStackOverflow()); \
@@ -151,24 +199,25 @@ void AstTyper::VisitSwitchStatement(SwitchStatement* stmt) {
RECURSE(Visit(stmt->tag()));
ZoneList<CaseClause*>* clauses = stmt->cases();
- SwitchStatement::SwitchType switch_type = stmt->switch_type();
Effects local_effects(zone());
bool complex_effects = false; // True for label effects or fall-through.
for (int i = 0; i < clauses->length(); ++i) {
CaseClause* clause = clauses->at(i);
+
Effects clause_effects = EnterEffects();
if (!clause->is_default()) {
Expression* label = clause->label();
- SwitchStatement::SwitchType label_switch_type =
- label->IsSmiLiteral() ? SwitchStatement::SMI_SWITCH :
- label->IsStringLiteral() ? SwitchStatement::STRING_SWITCH :
- SwitchStatement::GENERIC_SWITCH;
- if (switch_type == SwitchStatement::UNKNOWN_SWITCH)
- switch_type = label_switch_type;
- else if (switch_type != label_switch_type)
- switch_type = SwitchStatement::GENERIC_SWITCH;
+ // Collect type feedback.
+ Type* tag_type;
+ Type* label_type;
+ Type* combined_type;
+ oracle()->CompareType(clause->CompareId(),
+ &tag_type, &label_type, &combined_type);
+ NarrowLowerType(stmt->tag(), tag_type);
+ NarrowLowerType(label, label_type);
+ clause->set_compare_type(combined_type);
RECURSE(Visit(label));
if (!clause_effects.IsEmpty()) complex_effects = true;
@@ -189,20 +238,6 @@ void AstTyper::VisitSwitchStatement(SwitchStatement* stmt) {
} else {
store_.Seq(local_effects);
}
-
- if (switch_type == SwitchStatement::UNKNOWN_SWITCH)
- switch_type = SwitchStatement::GENERIC_SWITCH;
- stmt->set_switch_type(switch_type);
-
- // Collect type feedback.
- // TODO(rossberg): can we eliminate this special case and extra loop?
- if (switch_type == SwitchStatement::SMI_SWITCH) {
- for (int i = 0; i < clauses->length(); ++i) {
- CaseClause* clause = clauses->at(i);
- if (!clause->is_default())
- clause->set_compare_type(oracle()->ClauseType(clause->CompareId()));
- }
- }
}
@@ -221,6 +256,7 @@ void AstTyper::VisitDoWhileStatement(DoWhileStatement* stmt) {
// computing the set of variables assigned in only some of the origins of the
// control transfer (such as the loop body here).
store_.Forget(); // Control may transfer here via looping or 'continue'.
+ ObserveTypesAtOsrEntry(stmt);
RECURSE(Visit(stmt->body()));
RECURSE(Visit(stmt->cond()));
store_.Forget(); // Control may transfer here via 'break'.
@@ -235,6 +271,7 @@ void AstTyper::VisitWhileStatement(WhileStatement* stmt) {
store_.Forget(); // Control may transfer here via looping or 'continue'.
RECURSE(Visit(stmt->cond()));
+ ObserveTypesAtOsrEntry(stmt);
RECURSE(Visit(stmt->body()));
store_.Forget(); // Control may transfer here via termination or 'break'.
}
@@ -251,6 +288,7 @@ void AstTyper::VisitForStatement(ForStatement* stmt) {
RECURSE(Visit(stmt->cond()));
}
+ ObserveTypesAtOsrEntry(stmt);
RECURSE(Visit(stmt->body()));
if (stmt->next() != NULL) {
store_.Forget(); // Control may transfer here via 'continue'.
@@ -263,10 +301,11 @@ void AstTyper::VisitForStatement(ForStatement* stmt) {
void AstTyper::VisitForInStatement(ForInStatement* stmt) {
// Collect type feedback.
stmt->set_for_in_type(static_cast<ForInStatement::ForInType>(
- oracle()->ForInType(stmt->ForInFeedbackId())));
+ oracle()->ForInType(stmt->ForInFeedbackSlot())));
RECURSE(Visit(stmt->enumerable()));
store_.Forget(); // Control may transfer here via looping or 'continue'.
+ ObserveTypesAtOsrEntry(stmt);
RECURSE(Visit(stmt->body()));
store_.Forget(); // Control may transfer here via 'break'.
}
@@ -308,6 +347,7 @@ void AstTyper::VisitDebuggerStatement(DebuggerStatement* stmt) {
void AstTyper::VisitFunctionLiteral(FunctionLiteral* expr) {
+ expr->InitializeSharedInfo(Handle<Code>(info_->closure()->shared()->code()));
}
@@ -331,7 +371,7 @@ void AstTyper::VisitConditional(Conditional* expr) {
NarrowType(expr, Bounds::Either(
expr->then_expression()->bounds(),
- expr->else_expression()->bounds(), isolate_));
+ expr->else_expression()->bounds(), zone()));
}
@@ -344,13 +384,13 @@ void AstTyper::VisitVariableProxy(VariableProxy* expr) {
void AstTyper::VisitLiteral(Literal* expr) {
- Type* type = Type::Constant(expr->value(), isolate_);
- NarrowType(expr, Bounds(type, isolate_));
+ Type* type = Type::Constant(expr->value(), zone());
+ NarrowType(expr, Bounds(type));
}
void AstTyper::VisitRegExpLiteral(RegExpLiteral* expr) {
- NarrowType(expr, Bounds(Type::RegExp(), isolate_));
+ NarrowType(expr, Bounds(Type::RegExp(zone())));
}
@@ -371,7 +411,7 @@ void AstTyper::VisitObjectLiteral(ObjectLiteral* expr) {
RECURSE(Visit(prop->value()));
}
- NarrowType(expr, Bounds(Type::Object(), isolate_));
+ NarrowType(expr, Bounds(Type::Object(zone())));
}
@@ -382,7 +422,7 @@ void AstTyper::VisitArrayLiteral(ArrayLiteral* expr) {
RECURSE(Visit(value));
}
- NarrowType(expr, Bounds(Type::Array(), isolate_));
+ NarrowType(expr, Bounds(Type::Array(zone())));
}
@@ -393,7 +433,6 @@ void AstTyper::VisitAssignment(Assignment* expr) {
TypeFeedbackId id = expr->AssignmentFeedbackId();
expr->set_is_uninitialized(oracle()->StoreIsUninitialized(id));
if (!expr->IsUninitialized()) {
- expr->set_is_pre_monomorphic(oracle()->StoreIsPreMonomorphic(id));
if (prop->key()->IsPropertyName()) {
Literal* lit_key = prop->key()->AsLiteral();
ASSERT(lit_key != NULL && lit_key->value()->IsString());
@@ -405,7 +444,6 @@ void AstTyper::VisitAssignment(Assignment* expr) {
id, expr->GetReceiverTypes(), &store_mode);
expr->set_store_mode(store_mode);
}
- ASSERT(!expr->IsPreMonomorphic() || !expr->IsMonomorphic());
}
}
@@ -434,7 +472,7 @@ void AstTyper::VisitThrow(Throw* expr) {
RECURSE(Visit(expr->exception()));
// TODO(rossberg): is it worth having a non-termination effect?
- NarrowType(expr, Bounds(Type::None(), isolate_));
+ NarrowType(expr, Bounds(Type::None(zone())));
}
@@ -443,7 +481,6 @@ void AstTyper::VisitProperty(Property* expr) {
TypeFeedbackId id = expr->PropertyFeedbackId();
expr->set_is_uninitialized(oracle()->LoadIsUninitialized(id));
if (!expr->IsUninitialized()) {
- expr->set_is_pre_monomorphic(oracle()->LoadIsPreMonomorphic(id));
if (expr->key()->IsPropertyName()) {
Literal* lit_key = expr->key()->AsLiteral();
ASSERT(lit_key != NULL && lit_key->value()->IsString());
@@ -458,7 +495,6 @@ void AstTyper::VisitProperty(Property* expr) {
id, expr->GetReceiverTypes(), &is_string);
expr->set_is_string_access(is_string);
}
- ASSERT(!expr->IsPreMonomorphic() || !expr->IsMonomorphic());
}
RECURSE(Visit(expr->obj()));
@@ -470,15 +506,16 @@ void AstTyper::VisitProperty(Property* expr) {
void AstTyper::VisitCall(Call* expr) {
// Collect type feedback.
- Expression* callee = expr->expression();
- Property* prop = callee->AsProperty();
- if (prop != NULL) {
- expr->RecordTypeFeedback(oracle(), CALL_AS_METHOD);
- } else {
- expr->RecordTypeFeedback(oracle(), CALL_AS_FUNCTION);
+ RECURSE(Visit(expr->expression()));
+ if (!expr->expression()->IsProperty() &&
+ expr->IsUsingCallFeedbackSlot(isolate()) &&
+ oracle()->CallIsMonomorphic(expr->CallFeedbackSlot())) {
+ expr->set_target(oracle()->GetCallTarget(expr->CallFeedbackSlot()));
+ Handle<AllocationSite> site =
+ oracle()->GetCallAllocationSite(expr->CallFeedbackSlot());
+ expr->set_allocation_site(site);
}
- RECURSE(Visit(expr->expression()));
ZoneList<Expression*>* args = expr->arguments();
for (int i = 0; i < args->length(); ++i) {
Expression* arg = args->at(i);
@@ -505,7 +542,7 @@ void AstTyper::VisitCallNew(CallNew* expr) {
RECURSE(Visit(arg));
}
- // We don't know anything about the result type.
+ NarrowType(expr, Bounds(Type::None(zone()), Type::Receiver(zone())));
}
@@ -532,13 +569,13 @@ void AstTyper::VisitUnaryOperation(UnaryOperation* expr) {
switch (expr->op()) {
case Token::NOT:
case Token::DELETE:
- NarrowType(expr, Bounds(Type::Boolean(), isolate_));
+ NarrowType(expr, Bounds(Type::Boolean(zone())));
break;
case Token::VOID:
- NarrowType(expr, Bounds(Type::Undefined(), isolate_));
+ NarrowType(expr, Bounds(Type::Undefined(zone())));
break;
case Token::TYPEOF:
- NarrowType(expr, Bounds(Type::InternalizedString(), isolate_));
+ NarrowType(expr, Bounds(Type::InternalizedString(zone())));
break;
default:
UNREACHABLE();
@@ -556,7 +593,7 @@ void AstTyper::VisitCountOperation(CountOperation* expr) {
RECURSE(Visit(expr->expression()));
- NarrowType(expr, Bounds(Type::Smi(), Type::Number(), isolate_));
+ NarrowType(expr, Bounds(Type::SignedSmall(zone()), Type::Number(zone())));
VariableProxy* proxy = expr->expression()->AsVariableProxy();
if (proxy != NULL && proxy->var()->IsStackAllocated()) {
@@ -567,13 +604,18 @@ void AstTyper::VisitCountOperation(CountOperation* expr) {
void AstTyper::VisitBinaryOperation(BinaryOperation* expr) {
// Collect type feedback.
- Handle<Type> type, left_type, right_type;
+ Type* type;
+ Type* left_type;
+ Type* right_type;
Maybe<int> fixed_right_arg;
+ Handle<AllocationSite> allocation_site;
oracle()->BinaryType(expr->BinaryOperationFeedbackId(),
- &left_type, &right_type, &type, &fixed_right_arg, expr->op());
+ &left_type, &right_type, &type, &fixed_right_arg,
+ &allocation_site, expr->op());
NarrowLowerType(expr, type);
NarrowLowerType(expr->left(), left_type);
NarrowLowerType(expr->right(), right_type);
+ expr->set_allocation_site(allocation_site);
expr->set_fixed_right_arg(fixed_right_arg);
if (expr->op() == Token::OR || expr->op() == Token::AND) {
expr->left()->RecordToBooleanTypeFeedback(oracle());
@@ -597,21 +639,17 @@ void AstTyper::VisitBinaryOperation(BinaryOperation* expr) {
store_.Seq(left_effects);
NarrowType(expr, Bounds::Either(
- expr->left()->bounds(), expr->right()->bounds(), isolate_));
+ expr->left()->bounds(), expr->right()->bounds(), zone()));
break;
}
case Token::BIT_OR:
case Token::BIT_AND: {
RECURSE(Visit(expr->left()));
RECURSE(Visit(expr->right()));
- Handle<Type> upper(
- Type::Union(
- expr->left()->bounds().upper, expr->right()->bounds().upper),
- isolate_);
- if (!upper->Is(Type::Signed32()))
- upper = handle(Type::Signed32(), isolate_);
- Handle<Type> lower(Type::Intersect(
- handle(Type::Smi(), isolate_), upper), isolate_);
+ Type* upper = Type::Union(
+ expr->left()->bounds().upper, expr->right()->bounds().upper, zone());
+ if (!upper->Is(Type::Signed32())) upper = Type::Signed32(zone());
+ Type* lower = Type::Intersect(Type::SignedSmall(zone()), upper, zone());
NarrowType(expr, Bounds(lower, upper));
break;
}
@@ -620,7 +658,8 @@ void AstTyper::VisitBinaryOperation(BinaryOperation* expr) {
case Token::SAR:
RECURSE(Visit(expr->left()));
RECURSE(Visit(expr->right()));
- NarrowType(expr, Bounds(Type::Smi(), Type::Signed32(), isolate_));
+ NarrowType(expr,
+ Bounds(Type::SignedSmall(zone()), Type::Signed32(zone())));
break;
case Token::SHR:
RECURSE(Visit(expr->left()));
@@ -628,7 +667,7 @@ void AstTyper::VisitBinaryOperation(BinaryOperation* expr) {
// TODO(rossberg): The upper bound would be Unsigned32, but since there
// is no 'positive Smi' type for the lower bound, we use the smallest
// union of Smi and Unsigned32 as upper bound instead.
- NarrowType(expr, Bounds(Type::Smi(), Type::Number(), isolate_));
+ NarrowType(expr, Bounds(Type::SignedSmall(zone()), Type::Number(zone())));
break;
case Token::ADD: {
RECURSE(Visit(expr->left()));
@@ -636,18 +675,18 @@ void AstTyper::VisitBinaryOperation(BinaryOperation* expr) {
Bounds l = expr->left()->bounds();
Bounds r = expr->right()->bounds();
Type* lower =
- l.lower->Is(Type::None()) || r.lower->Is(Type::None()) ?
- Type::None() :
+ !l.lower->IsInhabited() || !r.lower->IsInhabited() ?
+ Type::None(zone()) :
l.lower->Is(Type::String()) || r.lower->Is(Type::String()) ?
- Type::String() :
+ Type::String(zone()) :
l.lower->Is(Type::Number()) && r.lower->Is(Type::Number()) ?
- Type::Smi() : Type::None();
+ Type::SignedSmall(zone()) : Type::None(zone());
Type* upper =
l.upper->Is(Type::String()) || r.upper->Is(Type::String()) ?
- Type::String() :
+ Type::String(zone()) :
l.upper->Is(Type::Number()) && r.upper->Is(Type::Number()) ?
- Type::Number() : Type::NumberOrString();
- NarrowType(expr, Bounds(lower, upper, isolate_));
+ Type::Number(zone()) : Type::NumberOrString(zone());
+ NarrowType(expr, Bounds(lower, upper));
break;
}
case Token::SUB:
@@ -656,7 +695,7 @@ void AstTyper::VisitBinaryOperation(BinaryOperation* expr) {
case Token::MOD:
RECURSE(Visit(expr->left()));
RECURSE(Visit(expr->right()));
- NarrowType(expr, Bounds(Type::Smi(), Type::Number(), isolate_));
+ NarrowType(expr, Bounds(Type::SignedSmall(zone()), Type::Number(zone())));
break;
default:
UNREACHABLE();
@@ -666,7 +705,9 @@ void AstTyper::VisitBinaryOperation(BinaryOperation* expr) {
void AstTyper::VisitCompareOperation(CompareOperation* expr) {
// Collect type feedback.
- Handle<Type> left_type, right_type, combined_type;
+ Type* left_type;
+ Type* right_type;
+ Type* combined_type;
oracle()->CompareType(expr->CompareOperationFeedbackId(),
&left_type, &right_type, &combined_type);
NarrowLowerType(expr->left(), left_type);
@@ -676,7 +717,7 @@ void AstTyper::VisitCompareOperation(CompareOperation* expr) {
RECURSE(Visit(expr->left()));
RECURSE(Visit(expr->right()));
- NarrowType(expr, Bounds(Type::Boolean(), isolate_));
+ NarrowType(expr, Bounds(Type::Boolean(zone())));
}