summaryrefslogtreecommitdiff
path: root/deps/v8/src/hydrogen.cc
diff options
context:
space:
mode:
Diffstat (limited to 'deps/v8/src/hydrogen.cc')
-rw-r--r--deps/v8/src/hydrogen.cc617
1 files changed, 413 insertions, 204 deletions
diff --git a/deps/v8/src/hydrogen.cc b/deps/v8/src/hydrogen.cc
index 8984a6e9f3..901e10721d 100644
--- a/deps/v8/src/hydrogen.cc
+++ b/deps/v8/src/hydrogen.cc
@@ -6,10 +6,9 @@
#include <sstream>
-#include "src/v8.h"
-
#include "src/allocation-site-scopes.h"
#include "src/ast-numbering.h"
+#include "src/code-factory.h"
#include "src/full-codegen/full-codegen.h"
#include "src/hydrogen-bce.h"
#include "src/hydrogen-bch.h"
@@ -37,6 +36,7 @@
#include "src/ic/ic.h"
// GetRootConstructor
#include "src/ic/ic-inl.h"
+#include "src/isolate-inl.h"
#include "src/lithium-allocator.h"
#include "src/parser.h"
#include "src/runtime/runtime.h"
@@ -1567,7 +1567,6 @@ void HGraphBuilder::BuildKeyedIndexCheck(HValue* key,
internalized.Else();
Add<HPushArguments>(key);
HValue* intern_key = Add<HCallRuntime>(
- isolate()->factory()->empty_string(),
Runtime::FunctionForId(Runtime::kInternalizeString), 1);
Push(intern_key);
@@ -1725,7 +1724,6 @@ HValue* HGraphBuilder::BuildUncheckedDictionaryElementLoad(
// TODO(jkummerow): walk the prototype chain instead.
Add<HPushArguments>(receiver, key);
Push(Add<HCallRuntime>(
- isolate()->factory()->empty_string(),
Runtime::FunctionForId(is_strong(language_mode)
? Runtime::kKeyedGetPropertyStrong
: Runtime::kKeyedGetProperty),
@@ -1788,7 +1786,6 @@ HValue* HGraphBuilder::BuildUncheckedDictionaryElementLoad(
details_compare.Else();
Add<HPushArguments>(receiver, key);
Push(Add<HCallRuntime>(
- isolate()->factory()->empty_string(),
Runtime::FunctionForId(is_strong(language_mode)
? Runtime::kKeyedGetPropertyStrong
: Runtime::kKeyedGetProperty),
@@ -1820,6 +1817,37 @@ HValue* HGraphBuilder::BuildUncheckedDictionaryElementLoad(
}
+HValue* HGraphBuilder::BuildCreateIterResultObject(HValue* value,
+ HValue* done) {
+ NoObservableSideEffectsScope scope(this);
+
+ // Allocate the JSIteratorResult object.
+ HValue* result =
+ Add<HAllocate>(Add<HConstant>(JSIteratorResult::kSize), HType::JSObject(),
+ NOT_TENURED, JS_ITERATOR_RESULT_TYPE);
+
+ // Initialize the JSIteratorResult object.
+ HValue* native_context = BuildGetNativeContext();
+ HValue* map = Add<HLoadNamedField>(
+ native_context, nullptr,
+ HObjectAccess::ForContextSlot(Context::ITERATOR_RESULT_MAP_INDEX));
+ Add<HStoreNamedField>(result, HObjectAccess::ForMap(), map);
+ HValue* empty_fixed_array = Add<HLoadRoot>(Heap::kEmptyFixedArrayRootIndex);
+ Add<HStoreNamedField>(result, HObjectAccess::ForPropertiesPointer(),
+ empty_fixed_array);
+ Add<HStoreNamedField>(result, HObjectAccess::ForElementsPointer(),
+ empty_fixed_array);
+ Add<HStoreNamedField>(result, HObjectAccess::ForObservableJSObjectOffset(
+ JSIteratorResult::kValueOffset),
+ value);
+ Add<HStoreNamedField>(result, HObjectAccess::ForObservableJSObjectOffset(
+ JSIteratorResult::kDoneOffset),
+ done);
+ STATIC_ASSERT(JSIteratorResult::kSize == 5 * kPointerSize);
+ return result;
+}
+
+
HValue* HGraphBuilder::BuildRegExpConstructResult(HValue* length,
HValue* index,
HValue* input) {
@@ -2022,7 +2050,6 @@ HValue* HGraphBuilder::BuildNumberToString(HValue* object, Type* type) {
// Cache miss, fallback to runtime.
Add<HPushArguments>(object);
Push(Add<HCallRuntime>(
- isolate()->factory()->empty_string(),
Runtime::FunctionForId(Runtime::kNumberToStringSkipCache),
1));
}
@@ -2438,8 +2465,7 @@ HValue* HGraphBuilder::BuildUncheckedStringAdd(
{
// Fallback to the runtime to add the two strings.
Add<HPushArguments>(left, right);
- Push(Add<HCallRuntime>(isolate()->factory()->empty_string(),
- Runtime::FunctionForId(Runtime::kStringAdd), 2));
+ Push(Add<HCallRuntime>(Runtime::FunctionForId(Runtime::kStringAdd), 2));
}
if_sameencodingandsequential.End();
}
@@ -3515,16 +3541,15 @@ HAllocate* HGraphBuilder::JSArrayBuilder::AllocateArray(
}
-HValue* HGraphBuilder::AddLoadJSBuiltin(Builtins::JavaScript builtin) {
+HValue* HGraphBuilder::AddLoadJSBuiltin(int context_index) {
HValue* global_object = Add<HLoadNamedField>(
context(), nullptr,
HObjectAccess::ForContextSlot(Context::GLOBAL_OBJECT_INDEX));
HObjectAccess access = HObjectAccess::ForObservableJSObjectOffset(
- GlobalObject::kBuiltinsOffset);
- HValue* builtins = Add<HLoadNamedField>(global_object, nullptr, access);
- HObjectAccess function_access = HObjectAccess::ForObservableJSObjectOffset(
- JSBuiltinsObject::OffsetOfFunctionWithId(builtin));
- return Add<HLoadNamedField>(builtins, nullptr, function_access);
+ GlobalObject::kNativeContextOffset);
+ HValue* native_context = Add<HLoadNamedField>(global_object, nullptr, access);
+ HObjectAccess function_access = HObjectAccess::ForContextSlot(context_index);
+ return Add<HLoadNamedField>(native_context, nullptr, function_access);
}
@@ -3654,7 +3679,7 @@ HGraph::HGraph(CompilationInfo* info)
start_environment_ =
new(zone_) HEnvironment(NULL, info->scope(), info->closure(), zone_);
}
- start_environment_->set_ast_id(BailoutId::FunctionEntry());
+ start_environment_->set_ast_id(BailoutId::Prologue());
entry_block_ = CreateBasicBlock();
entry_block_->SetInitialEnvironment(start_environment_);
}
@@ -4416,12 +4441,6 @@ bool HOptimizedGraphBuilder::BuildGraph() {
return false;
}
- int slots = current_info()->num_heap_slots() - Context::MIN_CONTEXT_SLOTS;
- if (current_info()->scope()->is_script_scope() && slots > 0) {
- Bailout(kScriptContext);
- return false;
- }
-
Scope* scope = current_info()->scope();
SetUpScope(scope);
@@ -4625,48 +4644,61 @@ HInstruction* HOptimizedGraphBuilder::PreProcessCall(Instruction* call) {
void HOptimizedGraphBuilder::SetUpScope(Scope* scope) {
+ HEnvironment* prolog_env = environment();
+ int parameter_count = environment()->parameter_count();
+ ZoneList<HValue*> parameters(parameter_count, zone());
+ for (int i = 0; i < parameter_count; ++i) {
+ HInstruction* parameter = Add<HParameter>(static_cast<unsigned>(i));
+ parameters.Add(parameter, zone());
+ environment()->Bind(i, parameter);
+ }
+
+ HConstant* undefined_constant = graph()->GetConstantUndefined();
+ // Initialize specials and locals to undefined.
+ for (int i = parameter_count + 1; i < environment()->length(); ++i) {
+ environment()->Bind(i, undefined_constant);
+ }
+ Add<HPrologue>();
+
+ HEnvironment* initial_env = environment()->CopyWithoutHistory();
+ HBasicBlock* body_entry = CreateBasicBlock(initial_env);
+ GotoNoSimulate(body_entry);
+ set_current_block(body_entry);
+
+ // Initialize context of prolog environment to undefined.
+ prolog_env->BindContext(undefined_constant);
+
// First special is HContext.
HInstruction* context = Add<HContext>();
environment()->BindContext(context);
// Create an arguments object containing the initial parameters. Set the
// initial values of parameters including "this" having parameter index 0.
- DCHECK_EQ(scope->num_parameters() + 1, environment()->parameter_count());
- HArgumentsObject* arguments_object =
- New<HArgumentsObject>(environment()->parameter_count());
- for (int i = 0; i < environment()->parameter_count(); ++i) {
- HInstruction* parameter = Add<HParameter>(i);
+ DCHECK_EQ(scope->num_parameters() + 1, parameter_count);
+ HArgumentsObject* arguments_object = New<HArgumentsObject>(parameter_count);
+ for (int i = 0; i < parameter_count; ++i) {
+ HValue* parameter = parameters.at(i);
arguments_object->AddArgument(parameter, zone());
- environment()->Bind(i, parameter);
}
+
AddInstruction(arguments_object);
graph()->SetArgumentsObject(arguments_object);
- HConstant* undefined_constant = graph()->GetConstantUndefined();
- // Initialize specials and locals to undefined.
- for (int i = environment()->parameter_count() + 1;
- i < environment()->length();
- ++i) {
- environment()->Bind(i, undefined_constant);
- }
-
// Handle the arguments and arguments shadow variables specially (they do
// not have declarations).
if (scope->arguments() != NULL) {
- environment()->Bind(scope->arguments(),
- graph()->GetArgumentsObject());
- }
-
- int rest_index;
- Variable* rest = scope->rest_parameter(&rest_index);
- if (rest) {
- return Bailout(kRestParameter);
+ environment()->Bind(scope->arguments(), graph()->GetArgumentsObject());
}
if (scope->this_function_var() != nullptr ||
scope->new_target_var() != nullptr) {
return Bailout(kSuperReference);
}
+
+ // Trace the call.
+ if (FLAG_trace && top_info()->IsOptimizing()) {
+ Add<HCallRuntime>(Runtime::FunctionForId(Runtime::kTraceEnter), 0);
+ }
}
@@ -4690,7 +4722,7 @@ void HOptimizedGraphBuilder::VisitBlock(Block* stmt) {
{ BreakAndContinueScope push(&break_info, this);
if (scope != NULL) {
- if (scope->ContextLocalCount() > 0) {
+ if (scope->NeedsContext()) {
// Load the function object.
Scope* declaration_scope = scope->DeclarationScope();
HInstruction* function;
@@ -4758,6 +4790,12 @@ void HOptimizedGraphBuilder::VisitEmptyStatement(EmptyStatement* stmt) {
}
+void HOptimizedGraphBuilder::VisitSloppyBlockFunctionStatement(
+ SloppyBlockFunctionStatement* stmt) {
+ Visit(stmt->statement());
+}
+
+
void HOptimizedGraphBuilder::VisitIfStatement(IfStatement* stmt) {
DCHECK(!HasStackOverflow());
DCHECK(current_block() != NULL);
@@ -5301,8 +5339,7 @@ void HOptimizedGraphBuilder::BuildForInBody(ForInStatement* stmt,
map = graph()->GetConstant1();
Runtime::FunctionId function_id = Runtime::kGetPropertyNamesFast;
Add<HPushArguments>(enumerable);
- array = Add<HCallRuntime>(isolate()->factory()->empty_string(),
- Runtime::FunctionForId(function_id), 1);
+ array = Add<HCallRuntime>(Runtime::FunctionForId(function_id), 1);
Push(array);
Add<HSimulate>(stmt->EnumId());
Drop(1);
@@ -5357,8 +5394,7 @@ void HOptimizedGraphBuilder::BuildForInBody(ForInStatement* stmt,
} else {
Add<HPushArguments>(enumerable, key);
Runtime::FunctionId function_id = Runtime::kForInFilter;
- key = Add<HCallRuntime>(isolate()->factory()->empty_string(),
- Runtime::FunctionForId(function_id), 2);
+ key = Add<HCallRuntime>(Runtime::FunctionForId(function_id), 2);
Push(key);
Add<HSimulate>(stmt->FilterId());
key = Pop();
@@ -5444,8 +5480,25 @@ void HOptimizedGraphBuilder::VisitFunctionLiteral(FunctionLiteral* expr) {
expr, current_info()->script(), top_info());
// We also have a stack overflow if the recursive compilation did.
if (HasStackOverflow()) return;
- HFunctionLiteral* instr =
- New<HFunctionLiteral>(shared_info, expr->pretenure());
+ // Use the fast case closure allocation code that allocates in new
+ // space for nested functions that don't need literals cloning.
+ HConstant* shared_info_value = Add<HConstant>(shared_info);
+ HInstruction* instr;
+ if (!expr->pretenure() && shared_info->num_literals() == 0) {
+ FastNewClosureStub stub(isolate(), shared_info->language_mode(),
+ shared_info->kind());
+ FastNewClosureDescriptor descriptor(isolate());
+ HValue* values[] = {context(), shared_info_value};
+ HConstant* stub_value = Add<HConstant>(stub.GetCode());
+ instr = New<HCallWithDescriptor>(stub_value, 0, descriptor,
+ Vector<HValue*>(values, arraysize(values)),
+ NORMAL_CALL);
+ } else {
+ Add<HPushArguments>(shared_info_value);
+ Runtime::FunctionId function_id =
+ expr->pretenure() ? Runtime::kNewClosure_Tenured : Runtime::kNewClosure;
+ instr = New<HCallRuntime>(Runtime::FunctionForId(function_id), 1);
+ }
return ast_context()->ReturnInstruction(instr, expr->id());
}
@@ -5716,7 +5769,7 @@ void HOptimizedGraphBuilder::VisitRegExpLiteral(RegExpLiteral* expr) {
DCHECK(current_block() != NULL);
DCHECK(current_block()->HasPredecessor());
Handle<JSFunction> closure = function_state()->compilation_info()->closure();
- Handle<FixedArray> literals(closure->literals());
+ Handle<LiteralsArray> literals(closure->literals());
HRegExpLiteral* instr = New<HRegExpLiteral>(literals,
expr->pattern(),
expr->flags(),
@@ -5812,8 +5865,8 @@ void HOptimizedGraphBuilder::VisitObjectLiteral(ObjectLiteral* expr) {
// Check whether to use fast or slow deep-copying for boilerplate.
int max_properties = kMaxFastLiteralProperties;
- Handle<Object> literals_cell(closure->literals()->get(expr->literal_index()),
- isolate());
+ Handle<Object> literals_cell(
+ closure->literals()->literal(expr->literal_index()), isolate());
Handle<AllocationSite> site;
Handle<JSObject> boilerplate;
if (!literals_cell->IsUndefined()) {
@@ -5831,7 +5884,7 @@ void HOptimizedGraphBuilder::VisitObjectLiteral(ObjectLiteral* expr) {
site_context.ExitScope(site, boilerplate);
} else {
NoObservableSideEffectsScope no_effects(this);
- Handle<FixedArray> closure_literals(closure->literals(), isolate());
+ Handle<LiteralsArray> closure_literals(closure->literals(), isolate());
Handle<FixedArray> constant_properties = expr->constant_properties();
int literal_index = expr->literal_index();
int flags = expr->ComputeFlags(true);
@@ -5842,15 +5895,12 @@ void HOptimizedGraphBuilder::VisitObjectLiteral(ObjectLiteral* expr) {
Add<HConstant>(flags));
Runtime::FunctionId function_id = Runtime::kCreateObjectLiteral;
- literal = Add<HCallRuntime>(isolate()->factory()->empty_string(),
- Runtime::FunctionForId(function_id),
- 4);
+ literal = Add<HCallRuntime>(Runtime::FunctionForId(function_id), 4);
}
// The object is expected in the bailout environment during computation
// of the property values and is the value of the entire expression.
Push(literal);
- int store_slot_index = 0;
for (int i = 0; i < expr->properties()->length(); i++) {
ObjectLiteral::Property* property = expr->properties()->at(i);
if (property->is_computed_name()) return Bailout(kComputedPropertyName);
@@ -5874,7 +5924,7 @@ void HOptimizedGraphBuilder::VisitObjectLiteral(ObjectLiteral* expr) {
Handle<Map> map = property->GetReceiverType();
Handle<String> name = key->AsPropertyName();
HValue* store;
- FeedbackVectorICSlot slot = expr->GetNthSlot(store_slot_index++);
+ FeedbackVectorICSlot slot = property->GetSlot();
if (map.is_null()) {
// If we don't know the monomorphic type, do a generic store.
CHECK_ALIVE(store = BuildNamedGeneric(STORE, NULL, slot, literal,
@@ -5902,8 +5952,7 @@ void HOptimizedGraphBuilder::VisitObjectLiteral(ObjectLiteral* expr) {
if (FunctionLiteral::NeedsHomeObject(property->value())) {
Handle<Symbol> sym = isolate()->factory()->home_object_symbol();
HInstruction* store_home = BuildNamedGeneric(
- STORE, NULL, expr->GetNthSlot(store_slot_index++), value, sym,
- literal);
+ STORE, NULL, property->GetSlot(1), value, sym, literal);
AddInstruction(store_home);
DCHECK(store_home->HasObservableSideEffects());
Add<HSimulate>(property->value()->id(), REMOVABLE_SIMULATE);
@@ -5922,9 +5971,6 @@ void HOptimizedGraphBuilder::VisitObjectLiteral(ObjectLiteral* expr) {
}
}
- // Crankshaft may not consume all the slots because it doesn't emit accessors.
- DCHECK(!FLAG_vector_stores || store_slot_index <= expr->slot_count());
-
if (expr->has_function()) {
// Return the result of the transformation to fast properties
// instead of the original since this operation changes the map
@@ -5949,9 +5995,10 @@ void HOptimizedGraphBuilder::VisitArrayLiteral(ArrayLiteral* expr) {
HInstruction* literal;
Handle<AllocationSite> site;
- Handle<FixedArray> literals(environment()->closure()->literals(), isolate());
+ Handle<LiteralsArray> literals(environment()->closure()->literals(),
+ isolate());
bool uninitialized = false;
- Handle<Object> literals_cell(literals->get(expr->literal_index()),
+ Handle<Object> literals_cell(literals->literal(expr->literal_index()),
isolate());
Handle<JSObject> boilerplate_object;
if (literals_cell->IsUndefined()) {
@@ -5971,7 +6018,7 @@ void HOptimizedGraphBuilder::VisitArrayLiteral(ArrayLiteral* expr) {
return Bailout(kArrayBoilerplateCreationFailed);
}
creation_context.ExitScope(site, boilerplate_object);
- literals->set(expr->literal_index(), *site);
+ literals->set_literal(expr->literal_index(), *site);
if (boilerplate_object->elements()->map() ==
isolate()->heap()->fixed_cow_array_map()) {
@@ -6013,9 +6060,7 @@ void HOptimizedGraphBuilder::VisitArrayLiteral(ArrayLiteral* expr) {
Add<HConstant>(flags));
Runtime::FunctionId function_id = Runtime::kCreateArrayLiteral;
- literal = Add<HCallRuntime>(isolate()->factory()->empty_string(),
- Runtime::FunctionForId(function_id),
- 4);
+ literal = Add<HCallRuntime>(Runtime::FunctionForId(function_id), 4);
// Register to deopt if the boilerplate ElementsKind changes.
top_info()->dependencies()->AssumeTransitionStable(site);
@@ -6366,8 +6411,8 @@ bool HOptimizedGraphBuilder::PropertyAccessInfo::LookupInPrototypes() {
bool HOptimizedGraphBuilder::PropertyAccessInfo::IsIntegerIndexedExotic() {
InstanceType instance_type = map_->instance_type();
- return instance_type == JS_TYPED_ARRAY_TYPE &&
- IsSpecialIndex(isolate()->unicode_cache(), *name_);
+ return instance_type == JS_TYPED_ARRAY_TYPE && name_->IsString() &&
+ IsSpecialIndex(isolate()->unicode_cache(), String::cast(*name_));
}
@@ -6375,7 +6420,8 @@ bool HOptimizedGraphBuilder::PropertyAccessInfo::CanAccessMonomorphic() {
if (!CanInlinePropertyAccess(map_)) return false;
if (IsJSObjectFieldAccessor()) return IsLoad();
if (IsJSArrayBufferViewFieldAccessor()) return IsLoad();
- if (map_->function_with_prototype() && !map_->has_non_instance_prototype() &&
+ if (map_->IsJSFunctionMap() && map_->is_constructor() &&
+ !map_->has_non_instance_prototype() &&
name_.is_identical_to(isolate()->factory()->prototype_string())) {
return IsLoad();
}
@@ -6489,7 +6535,7 @@ HValue* HOptimizedGraphBuilder::BuildMonomorphicAccess(
}
if (info->name().is_identical_to(isolate()->factory()->prototype_string()) &&
- info->map()->function_with_prototype()) {
+ info->map()->IsJSFunctionMap() && info->map()->is_constructor()) {
DCHECK(!info->map()->has_non_instance_prototype());
return New<HLoadFunctionPrototype>(checked_object);
}
@@ -6504,7 +6550,6 @@ HValue* HOptimizedGraphBuilder::BuildMonomorphicAccess(
DCHECK(info->IsLoad());
if (is_strong(function_language_mode())) {
return New<HCallRuntime>(
- isolate()->factory()->empty_string(),
Runtime::FunctionForId(Runtime::kThrowStrongModeImplicitConversion),
0);
} else {
@@ -7160,8 +7205,7 @@ void HOptimizedGraphBuilder::VisitThrow(Throw* expr) {
HValue* value = environment()->Pop();
if (!top_info()->is_tracking_positions()) SetSourcePosition(expr->position());
Add<HPushArguments>(value);
- Add<HCallRuntime>(isolate()->factory()->empty_string(),
- Runtime::FunctionForId(Runtime::kThrow), 1);
+ Add<HCallRuntime>(Runtime::FunctionForId(Runtime::kThrow), 1);
Add<HSimulate>(expr->id());
// If the throw definitely exits the function, we can finish with a dummy
@@ -7233,7 +7277,8 @@ HInstruction* HOptimizedGraphBuilder::BuildNamedGeneric(
return result;
} else {
if (FLAG_vector_stores &&
- current_feedback_vector()->GetKind(slot) == Code::KEYED_STORE_IC) {
+ current_feedback_vector()->GetKind(slot) ==
+ FeedbackVectorSlotKind::KEYED_STORE_IC) {
// It's possible that a keyed store of a constant string was converted
// to a named store. Here, at the last minute, we need to make sure to
// use a generic Keyed Store if we are using the type vector, because
@@ -7328,7 +7373,7 @@ HInstruction* HOptimizedGraphBuilder::BuildMonomorphicElementAccess(
PrototypeIterator iter(map);
JSObject* holder = NULL;
while (!iter.IsAtEnd()) {
- holder = JSObject::cast(*PrototypeIterator::GetCurrent(iter));
+ holder = *PrototypeIterator::GetCurrent<JSObject>(iter);
iter.Advance();
}
DCHECK(holder && holder->IsJSObject());
@@ -7410,11 +7455,45 @@ HInstruction* HOptimizedGraphBuilder::TryBuildConsolidatedElementLoad(
ElementsKind consolidated_elements_kind = has_seen_holey_elements
? GetHoleyElementsKind(most_general_consolidated_map->elements_kind())
: most_general_consolidated_map->elements_kind();
+ LoadKeyedHoleMode load_mode = NEVER_RETURN_HOLE;
+ if (has_seen_holey_elements) {
+ // Make sure that all of the maps we are handling have the initial array
+ // prototype.
+ bool saw_non_array_prototype = false;
+ for (int i = 0; i < maps->length(); ++i) {
+ Handle<Map> map = maps->at(i);
+ if (map->prototype() != *isolate()->initial_array_prototype()) {
+ // We can't guarantee that loading the hole is safe. The prototype may
+ // have an element at this position.
+ saw_non_array_prototype = true;
+ break;
+ }
+ }
+
+ if (!saw_non_array_prototype) {
+ Handle<Map> holey_map = handle(
+ isolate()->get_initial_js_array_map(consolidated_elements_kind));
+ load_mode = BuildKeyedHoleMode(holey_map);
+ if (load_mode != NEVER_RETURN_HOLE) {
+ for (int i = 0; i < maps->length(); ++i) {
+ Handle<Map> map = maps->at(i);
+ // The prototype check was already done for the holey map in
+ // BuildKeyedHoleMode.
+ if (!map.is_identical_to(holey_map)) {
+ Handle<JSObject> prototype(JSObject::cast(map->prototype()),
+ isolate());
+ Handle<JSObject> object_prototype =
+ isolate()->initial_object_prototype();
+ BuildCheckPrototypeMaps(prototype, object_prototype);
+ }
+ }
+ }
+ }
+ }
HInstruction* instr = BuildUncheckedMonomorphicElementAccess(
checked_object, key, val,
most_general_consolidated_map->instance_type() == JS_ARRAY_TYPE,
- consolidated_elements_kind,
- LOAD, NEVER_RETURN_HOLE, STANDARD_STORE);
+ consolidated_elements_kind, LOAD, load_mode, STANDARD_STORE);
return instr;
}
@@ -7857,15 +7936,13 @@ HInstruction* HGraphBuilder::BuildCheckPrototypeMaps(Handle<JSObject> prototype,
PrototypeIterator::START_AT_RECEIVER);
while (holder.is_null() ||
!PrototypeIterator::GetCurrent(iter).is_identical_to(holder)) {
- BuildConstantMapCheck(
- Handle<JSObject>::cast(PrototypeIterator::GetCurrent(iter)));
+ BuildConstantMapCheck(PrototypeIterator::GetCurrent<JSObject>(iter));
iter.Advance();
if (iter.IsAtEnd()) {
return NULL;
}
}
- return BuildConstantMapCheck(
- Handle<JSObject>::cast(PrototypeIterator::GetCurrent(iter)));
+ return BuildConstantMapCheck(PrototypeIterator::GetCurrent<JSObject>(iter));
}
@@ -7878,9 +7955,9 @@ void HOptimizedGraphBuilder::AddCheckPrototypeMaps(Handle<JSObject> holder,
}
-HInstruction* HOptimizedGraphBuilder::NewPlainFunctionCall(
- HValue* fun, int argument_count, bool pass_argument_count) {
- return New<HCallJSFunction>(fun, argument_count, pass_argument_count);
+HInstruction* HOptimizedGraphBuilder::NewPlainFunctionCall(HValue* fun,
+ int argument_count) {
+ return New<HCallJSFunction>(fun, argument_count);
}
@@ -7918,7 +7995,7 @@ HInstruction* HOptimizedGraphBuilder::BuildCallConstantFunction(
if (jsfun.is_identical_to(current_info()->closure())) {
graph()->MarkRecursive();
}
- return NewPlainFunctionCall(target, argument_count, dont_adapt_arguments);
+ return NewPlainFunctionCall(target, argument_count);
} else {
HValue* param_count_value = Add<HConstant>(formal_parameter_count);
HValue* context = Add<HLoadNamedField>(
@@ -8337,7 +8414,9 @@ bool HOptimizedGraphBuilder::TryInline(Handle<JSFunction> target,
// Type-check the inlined function.
DCHECK(target_shared->has_deoptimization_support());
- AstTyper::Run(&target_info);
+ AstTyper(target_info.isolate(), target_info.zone(), target_info.closure(),
+ target_info.scope(), target_info.osr_ast_id(), target_info.literal())
+ .Run();
int inlining_id = 0;
if (top_info()->is_tracking_positions()) {
@@ -8603,9 +8682,10 @@ bool HOptimizedGraphBuilder::CanInlineArrayResizeOperation(
return !receiver_map.is_null() &&
receiver_map->instance_type() == JS_ARRAY_TYPE &&
IsFastElementsKind(receiver_map->elements_kind()) &&
- !receiver_map->is_dictionary_map() &&
- !IsReadOnlyLengthDescriptor(receiver_map) &&
- !receiver_map->is_observed() && receiver_map->is_extensible();
+ !receiver_map->is_dictionary_map() && !receiver_map->is_observed() &&
+ receiver_map->is_extensible() &&
+ (!receiver_map->is_prototype_map() || receiver_map->is_stable()) &&
+ !IsReadOnlyLengthDescriptor(receiver_map);
}
@@ -8936,7 +9016,7 @@ bool HOptimizedGraphBuilder::TryInlineBuiltinMethodCall(
if_inline.Else();
{
Add<HPushArguments>(receiver);
- result = Add<HCallJSFunction>(function, 1, true);
+ result = Add<HCallJSFunction>(function, 1);
if (!ast_context()->IsEffect()) Push(result);
}
if_inline.End();
@@ -9838,16 +9918,6 @@ void HOptimizedGraphBuilder::VisitCallNew(CallNew* expr) {
// Allocate an instance of the implicit receiver object.
HValue* size_in_bytes = Add<HConstant>(instance_size);
HAllocationMode allocation_mode;
- if (FLAG_pretenuring_call_new) {
- if (FLAG_allocation_site_pretenuring) {
- // Try to use pretenuring feedback.
- Handle<AllocationSite> allocation_site = expr->allocation_site();
- allocation_mode = HAllocationMode(allocation_site);
- // Take a dependency on allocation site.
- top_info()->dependencies()->AssumeTenuringDecision(allocation_site);
- }
- }
-
HAllocate* receiver = BuildAllocate(
size_in_bytes, HType::JSObject(), JS_OBJECT_TYPE, allocation_mode);
receiver->set_known_initial_map(initial_map);
@@ -10286,7 +10356,7 @@ void HOptimizedGraphBuilder::GenerateTypedArrayInitialize(
Push(byte_length);
CHECK_ALIVE(VisitForValue(arguments->at(kInitializeArg)));
PushArgumentsFromEnvironment(kArgsLength);
- Add<HCallRuntime>(expr->name(), expr->function(), kArgsLength);
+ Add<HCallRuntime>(expr->function(), kArgsLength);
}
}
byte_offset_smi.End();
@@ -10377,11 +10447,10 @@ void HOptimizedGraphBuilder::VisitCallRuntime(CallRuntime* expr) {
FOR_EACH_HYDROGEN_INTRINSIC(CALL_INTRINSIC_GENERATOR)
#undef CALL_INTRINSIC_GENERATOR
default: {
- Handle<String> name = expr->name();
int argument_count = expr->arguments()->length();
CHECK_ALIVE(VisitExpressions(expr->arguments()));
PushArgumentsFromEnvironment(argument_count);
- HCallRuntime* call = New<HCallRuntime>(name, function, argument_count);
+ HCallRuntime* call = New<HCallRuntime>(function, argument_count);
return ast_context()->ReturnInstruction(call, expr->id());
}
}
@@ -10412,7 +10481,6 @@ void HOptimizedGraphBuilder::VisitDelete(UnaryOperation* expr) {
HValue* obj = Pop();
Add<HPushArguments>(obj, key);
HInstruction* instr = New<HCallRuntime>(
- isolate()->factory()->empty_string(),
Runtime::FunctionForId(is_strict(function_language_mode())
? Runtime::kDeleteProperty_Strict
: Runtime::kDeleteProperty_Sloppy),
@@ -10927,9 +10995,9 @@ HValue* HGraphBuilder::BuildBinaryOperation(
left = BuildNumberToString(left, left_type);
} else if (!left_type->Is(Type::String())) {
DCHECK(right_type->Is(Type::String()));
- HValue* function = AddLoadJSBuiltin(Builtins::STRING_ADD_RIGHT);
- Add<HPushArguments>(left, right);
- return AddUncasted<HInvokeFunction>(function, 2);
+ return AddUncasted<HStringAdd>(
+ left, right, allocation_mode.GetPretenureMode(),
+ STRING_ADD_CONVERT_LEFT, allocation_mode.feedback_site());
}
// Convert right argument as necessary.
@@ -10938,9 +11006,9 @@ HValue* HGraphBuilder::BuildBinaryOperation(
right = BuildNumberToString(right, right_type);
} else if (!right_type->Is(Type::String())) {
DCHECK(left_type->Is(Type::String()));
- HValue* function = AddLoadJSBuiltin(Builtins::STRING_ADD_LEFT);
- Add<HPushArguments>(left, right);
- return AddUncasted<HInvokeFunction>(function, 2);
+ return AddUncasted<HStringAdd>(
+ left, right, allocation_mode.GetPretenureMode(),
+ STRING_ADD_CONVERT_RIGHT, allocation_mode.feedback_site());
}
}
@@ -10957,7 +11025,7 @@ HValue* HGraphBuilder::BuildBinaryOperation(
if (!right_string.is_null() && right_string->length() == 0) return left;
if (!left_string.is_null() && !right_string.is_null()) {
return AddUncasted<HStringAdd>(
- left, right, strength, allocation_mode.GetPretenureMode(),
+ left, right, allocation_mode.GetPretenureMode(),
STRING_ADD_CHECK_NONE, allocation_mode.feedback_site());
}
@@ -10986,8 +11054,8 @@ HValue* HGraphBuilder::BuildBinaryOperation(
// Fallback to using the string add stub.
return AddUncasted<HStringAdd>(
- left, right, strength, allocation_mode.GetPretenureMode(),
- STRING_ADD_CHECK_NONE, allocation_mode.feedback_site());
+ left, right, allocation_mode.GetPretenureMode(), STRING_ADD_CHECK_NONE,
+ allocation_mode.feedback_site());
}
if (graph()->info()->IsStub()) {
@@ -11005,10 +11073,57 @@ HValue* HGraphBuilder::BuildBinaryOperation(
// inline several instructions (including the two pushes) for every tagged
// operation in optimized code, which is more expensive, than a stub call.
if (graph()->info()->IsStub() && is_non_primitive) {
- HValue* function =
- AddLoadJSBuiltin(BinaryOpIC::TokenToJSBuiltin(op, strength));
+ Runtime::FunctionId function_id;
+ switch (op) {
+ default:
+ UNREACHABLE();
+ case Token::ADD:
+ function_id =
+ is_strong(strength) ? Runtime::kAdd_Strong : Runtime::kAdd;
+ break;
+ case Token::SUB:
+ function_id = is_strong(strength) ? Runtime::kSubtract_Strong
+ : Runtime::kSubtract;
+ break;
+ case Token::MUL:
+ function_id = is_strong(strength) ? Runtime::kMultiply_Strong
+ : Runtime::kMultiply;
+ break;
+ case Token::DIV:
+ function_id =
+ is_strong(strength) ? Runtime::kDivide_Strong : Runtime::kDivide;
+ break;
+ case Token::MOD:
+ function_id =
+ is_strong(strength) ? Runtime::kModulus_Strong : Runtime::kModulus;
+ break;
+ case Token::BIT_OR:
+ function_id = is_strong(strength) ? Runtime::kBitwiseOr_Strong
+ : Runtime::kBitwiseOr;
+ break;
+ case Token::BIT_AND:
+ function_id = is_strong(strength) ? Runtime::kBitwiseAnd_Strong
+ : Runtime::kBitwiseAnd;
+ break;
+ case Token::BIT_XOR:
+ function_id = is_strong(strength) ? Runtime::kBitwiseXor_Strong
+ : Runtime::kBitwiseXor;
+ break;
+ case Token::SAR:
+ function_id = is_strong(strength) ? Runtime::kShiftRight_Strong
+ : Runtime::kShiftRight;
+ break;
+ case Token::SHR:
+ function_id = is_strong(strength) ? Runtime::kShiftRightLogical_Strong
+ : Runtime::kShiftRightLogical;
+ break;
+ case Token::SHL:
+ function_id = is_strong(strength) ? Runtime::kShiftLeft_Strong
+ : Runtime::kShiftLeft;
+ break;
+ }
Add<HPushArguments>(left, right);
- instr = AddUncasted<HInvokeFunction>(function, 2);
+ instr = AddUncasted<HCallRuntime>(Runtime::FunctionForId(function_id), 2);
} else {
if (is_strong(strength) && Token::IsBitOp(op)) {
// TODO(conradw): This is not efficient, but is necessary to prevent
@@ -11019,7 +11134,6 @@ HValue* HGraphBuilder::BuildBinaryOperation(
if_builder.OrIf<HHasInstanceTypeAndBranch>(right, ODDBALL_TYPE);
if_builder.Then();
Add<HCallRuntime>(
- isolate()->factory()->empty_string(),
Runtime::FunctionForId(Runtime::kThrowStrongModeImplicitConversion),
0);
if (!graph()->info()->IsStub()) {
@@ -11059,7 +11173,7 @@ HValue* HGraphBuilder::BuildBinaryOperation(
instr = AddUncasted<HBitwise>(op, left, right, strength);
break;
case Token::BIT_OR: {
- HValue* operand, *shift_amount;
+ HValue *operand, *shift_amount;
if (left_type->Is(Type::Signed32()) &&
right_type->Is(Type::Signed32()) &&
MatchRotateRight(left, right, &operand, &shift_amount)) {
@@ -11117,7 +11231,8 @@ static bool IsClassOfTest(CompareOperation* expr) {
Literal* literal = expr->right()->AsLiteral();
if (literal == NULL) return false;
if (!literal->value()->IsString()) return false;
- if (!call->name()->IsOneByteEqualTo(STATIC_CHAR_VECTOR("_ClassOf"))) {
+ if (!call->is_jsruntime() &&
+ call->function()->function_id != Runtime::kInlineClassOf) {
return false;
}
DCHECK(call->arguments()->length() == 1);
@@ -11349,22 +11464,28 @@ void HOptimizedGraphBuilder::VisitCompareOperation(CompareOperation* expr) {
// Check to see if the rhs of the instanceof is a known function.
if (right->IsConstant() &&
HConstant::cast(right)->handle(isolate())->IsJSFunction()) {
- Handle<Object> function = HConstant::cast(right)->handle(isolate());
- Handle<JSFunction> target = Handle<JSFunction>::cast(function);
- HInstanceOfKnownGlobal* result =
- New<HInstanceOfKnownGlobal>(left, target);
- return ast_context()->ReturnInstruction(result, expr->id());
+ Handle<JSFunction> constructor =
+ Handle<JSFunction>::cast(HConstant::cast(right)->handle(isolate()));
+ if (!constructor->map()->has_non_instance_prototype()) {
+ JSFunction::EnsureHasInitialMap(constructor);
+ DCHECK(constructor->has_initial_map());
+ Handle<Map> initial_map(constructor->initial_map(), isolate());
+ top_info()->dependencies()->AssumeInitialMapCantChange(initial_map);
+ HInstruction* prototype =
+ Add<HConstant>(handle(initial_map->prototype(), isolate()));
+ HHasInPrototypeChainAndBranch* result =
+ New<HHasInPrototypeChainAndBranch>(left, prototype);
+ return ast_context()->ReturnControl(result, expr->id());
+ }
}
HInstanceOf* result = New<HInstanceOf>(left, right);
return ast_context()->ReturnInstruction(result, expr->id());
} else if (op == Token::IN) {
- HValue* function = AddLoadJSBuiltin(Builtins::IN);
Add<HPushArguments>(left, right);
- // TODO(olivf) InvokeFunction produces a check for the parameter count,
- // even though we are certain to pass the correct number of arguments here.
- HInstruction* result = New<HInvokeFunction>(function, 2);
+ HInstruction* result =
+ New<HCallRuntime>(Runtime::FunctionForId(Runtime::kHasProperty), 2);
return ast_context()->ReturnInstruction(result, expr->id());
}
@@ -11434,6 +11555,51 @@ HControlInstruction* HOptimizedGraphBuilder::BuildCompareInstruction(
return result;
}
} else {
+ if (combined_type->IsClass()) {
+ // TODO(bmeurer): This is an optimized version of an x < y, x > y,
+ // x <= y or x >= y, where both x and y are spec objects with the
+ // same map. The CompareIC collects this map for us. So if we know
+ // that there's no @@toPrimitive on the map (including the prototype
+ // chain), and both valueOf and toString are the default initial
+ // implementations (on the %ObjectPrototype%), then we can reduce
+ // the comparison to map checks on x and y, because the comparison
+ // will turn into a comparison of "[object CLASS]" to itself (the
+ // default outcome of toString, since valueOf returns a spec object).
+ // This is pretty much adhoc, so in TurboFan we could do a lot better
+ // and inline the interesting parts of ToPrimitive (actually we could
+ // even do that in Crankshaft but we don't want to waste too much
+ // time on this now).
+ DCHECK(Token::IsOrderedRelationalCompareOp(op));
+ Handle<Map> map = combined_type->AsClass()->Map();
+ PropertyAccessInfo value_of(this, LOAD, map,
+ isolate()->factory()->valueOf_string());
+ PropertyAccessInfo to_primitive(
+ this, LOAD, map, isolate()->factory()->to_primitive_symbol());
+ PropertyAccessInfo to_string(this, LOAD, map,
+ isolate()->factory()->toString_string());
+ PropertyAccessInfo to_string_tag(
+ this, LOAD, map, isolate()->factory()->to_string_tag_symbol());
+ if (to_primitive.CanAccessMonomorphic() && !to_primitive.IsFound() &&
+ to_string_tag.CanAccessMonomorphic() &&
+ (!to_string_tag.IsFound() || to_string_tag.IsData() ||
+ to_string_tag.IsDataConstant()) &&
+ value_of.CanAccessMonomorphic() && value_of.IsDataConstant() &&
+ value_of.constant().is_identical_to(isolate()->object_value_of()) &&
+ to_string.CanAccessMonomorphic() && to_string.IsDataConstant() &&
+ to_string.constant().is_identical_to(
+ isolate()->object_to_string())) {
+ // We depend on the prototype chain to stay the same, because we
+ // also need to deoptimize when someone installs @@toPrimitive
+ // or @@toStringTag somewhere in the prototype chain.
+ BuildCheckPrototypeMaps(handle(JSObject::cast(map->prototype())),
+ Handle<JSObject>::null());
+ AddCheckMap(left, map);
+ AddCheckMap(right, map);
+ // The caller expects a branch instruction, so make it happy.
+ return New<HBranch>(
+ graph()->GetConstantBool(op == Token::LTE || op == Token::GTE));
+ }
+ }
Bailout(kUnsupportedNonPrimitiveCompare);
return NULL;
}
@@ -11465,6 +11631,23 @@ HControlInstruction* HOptimizedGraphBuilder::BuildCompareInstruction(
HStringCompareAndBranch* result =
New<HStringCompareAndBranch>(left, right, op);
return result;
+ } else if (combined_type->Is(Type::Boolean())) {
+ AddCheckMap(left, isolate()->factory()->boolean_map());
+ AddCheckMap(right, isolate()->factory()->boolean_map());
+ if (Token::IsEqualityOp(op)) {
+ HCompareObjectEqAndBranch* result =
+ New<HCompareObjectEqAndBranch>(left, right);
+ return result;
+ }
+ left = Add<HLoadNamedField>(
+ left, nullptr,
+ HObjectAccess::ForOddballToNumber(Representation::Smi()));
+ right = Add<HLoadNamedField>(
+ right, nullptr,
+ HObjectAccess::ForOddballToNumber(Representation::Smi()));
+ HCompareNumericAndBranch* result =
+ New<HCompareNumericAndBranch>(left, right, op);
+ return result;
} else {
if (combined_rep.IsTagged() || combined_rep.IsNone()) {
HCompareGeneric* result = Add<HCompareGeneric>(
@@ -11527,6 +11710,11 @@ void HOptimizedGraphBuilder::HandleLiteralCompareNil(CompareOperation* expr,
void HOptimizedGraphBuilder::VisitSpread(Spread* expr) { UNREACHABLE(); }
+void HOptimizedGraphBuilder::VisitEmptyParentheses(EmptyParentheses* expr) {
+ UNREACHABLE();
+}
+
+
HInstruction* HOptimizedGraphBuilder::BuildThisFunction() {
// If we share optimized code between different closures, the
// this-function is not a constant, except inside an inlined body.
@@ -12030,12 +12218,30 @@ void HOptimizedGraphBuilder::GenerateIsRegExp(CallRuntime* call) {
}
-void HOptimizedGraphBuilder::GenerateIsObject(CallRuntime* call) {
- DCHECK(call->arguments()->length() == 1);
+void HOptimizedGraphBuilder::GenerateToInteger(CallRuntime* call) {
+ DCHECK_EQ(1, call->arguments()->length());
CHECK_ALIVE(VisitForValue(call->arguments()->at(0)));
- HValue* value = Pop();
- HIsObjectAndBranch* result = New<HIsObjectAndBranch>(value);
- return ast_context()->ReturnControl(result, call->id());
+ HValue* input = Pop();
+ if (input->type().IsSmi()) {
+ return ast_context()->ReturnValue(input);
+ } else {
+ IfBuilder if_inputissmi(this);
+ if_inputissmi.If<HIsSmiAndBranch>(input);
+ if_inputissmi.Then();
+ {
+ // Return the input value.
+ Push(input);
+ Add<HSimulate>(call->id(), FIXED_SIMULATE);
+ }
+ if_inputissmi.Else();
+ {
+ Add<HPushArguments>(input);
+ Push(Add<HCallRuntime>(Runtime::FunctionForId(Runtime::kToInteger), 1));
+ Add<HSimulate>(call->id(), FIXED_SIMULATE);
+ }
+ if_inputissmi.End();
+ return ast_context()->ReturnValue(Pop());
+ }
}
@@ -12048,6 +12254,24 @@ void HOptimizedGraphBuilder::GenerateToObject(CallRuntime* call) {
}
+void HOptimizedGraphBuilder::GenerateToString(CallRuntime* call) {
+ DCHECK_EQ(1, call->arguments()->length());
+ CHECK_ALIVE(VisitForValue(call->arguments()->at(0)));
+ Callable callable = CodeFactory::ToString(isolate());
+ HValue* input = Pop();
+ if (input->type().IsString()) {
+ return ast_context()->ReturnValue(input);
+ } else {
+ HValue* stub = Add<HConstant>(callable.code());
+ HValue* values[] = {context(), input};
+ HInstruction* result =
+ New<HCallWithDescriptor>(stub, 0, callable.descriptor(),
+ Vector<HValue*>(values, arraysize(values)));
+ return ast_context()->ReturnInstruction(result, call->id());
+ }
+}
+
+
void HOptimizedGraphBuilder::GenerateIsJSProxy(CallRuntime* call) {
DCHECK(call->arguments()->length() == 1);
CHECK_ALIVE(VisitForValue(call->arguments()->at(0)));
@@ -12351,8 +12575,7 @@ void HOptimizedGraphBuilder::GenerateStringAdd(CallRuntime* call) {
CHECK_ALIVE(VisitForValue(call->arguments()->at(1)));
HValue* right = Pop();
HValue* left = Pop();
- HInstruction* result =
- NewUncasted<HStringAdd>(left, right, strength(function_language_mode()));
+ HInstruction* result = NewUncasted<HStringAdd>(left, right);
return ast_context()->ReturnInstruction(result, call->id());
}
@@ -12367,16 +12590,6 @@ void HOptimizedGraphBuilder::GenerateSubString(CallRuntime* call) {
}
-// Fast support for StringCompare.
-void HOptimizedGraphBuilder::GenerateStringCompare(CallRuntime* call) {
- DCHECK_EQ(2, call->arguments()->length());
- CHECK_ALIVE(VisitExpressions(call->arguments()));
- PushArgumentsFromEnvironment(call->arguments()->length());
- HCallStub* result = New<HCallStub>(CodeStub::StringCompare, 2);
- return ast_context()->ReturnInstruction(result, call->id());
-}
-
-
void HOptimizedGraphBuilder::GenerateStringGetLength(CallRuntime* call) {
DCHECK(call->arguments()->length() == 1);
CHECK_ALIVE(VisitForValue(call->arguments()->at(0)));
@@ -12449,6 +12662,23 @@ void HOptimizedGraphBuilder::GenerateNumberToString(CallRuntime* call) {
}
+// Fast support for calls.
+void HOptimizedGraphBuilder::GenerateCall(CallRuntime* call) {
+ DCHECK_LE(2, call->arguments()->length());
+ CHECK_ALIVE(VisitExpressions(call->arguments()));
+ CallTrampolineDescriptor descriptor(isolate());
+ PushArgumentsFromEnvironment(call->arguments()->length() - 1);
+ HValue* trampoline = Add<HConstant>(isolate()->builtins()->Call());
+ HValue* target = Pop();
+ HValue* values[] = {context(), target,
+ Add<HConstant>(call->arguments()->length() - 2)};
+ HInstruction* result = New<HCallWithDescriptor>(
+ trampoline, call->arguments()->length() - 1, descriptor,
+ Vector<HValue*>(values, arraysize(values)));
+ return ast_context()->ReturnInstruction(result, call->id());
+}
+
+
// Fast call for custom callbacks.
void HOptimizedGraphBuilder::GenerateCallFunction(CallRuntime* call) {
// 1 ~ The function to call is not itself an argument to the call.
@@ -12554,6 +12784,18 @@ void HOptimizedGraphBuilder::GenerateUnlikely(CallRuntime* call) {
}
+void HOptimizedGraphBuilder::GenerateHasInPrototypeChain(CallRuntime* call) {
+ DCHECK_EQ(2, call->arguments()->length());
+ CHECK_ALIVE(VisitForValue(call->arguments()->at(0)));
+ CHECK_ALIVE(VisitForValue(call->arguments()->at(1)));
+ HValue* prototype = Pop();
+ HValue* object = Pop();
+ HHasInPrototypeChainAndBranch* result =
+ New<HHasInPrototypeChainAndBranch>(object, prototype);
+ return ast_context()->ReturnControl(result, call->id());
+}
+
+
void HOptimizedGraphBuilder::GenerateFixedArrayGet(CallRuntime* call) {
DCHECK(call->arguments()->length() == 2);
CHECK_ALIVE(VisitForValue(call->arguments()->at(0)));
@@ -12586,6 +12828,17 @@ void HOptimizedGraphBuilder::GenerateTheHole(CallRuntime* call) {
}
+void HOptimizedGraphBuilder::GenerateCreateIterResultObject(CallRuntime* call) {
+ DCHECK_EQ(2, call->arguments()->length());
+ CHECK_ALIVE(VisitForValue(call->arguments()->at(0)));
+ CHECK_ALIVE(VisitForValue(call->arguments()->at(1)));
+ HValue* done = Pop();
+ HValue* value = Pop();
+ HValue* result = BuildCreateIterResultObject(value, done);
+ return ast_context()->ReturnValue(result);
+}
+
+
void HOptimizedGraphBuilder::GenerateJSCollectionGetTable(CallRuntime* call) {
DCHECK(call->arguments()->length() == 1);
CHECK_ALIVE(VisitForValue(call->arguments()->at(0)));
@@ -12760,53 +13013,6 @@ void HOptimizedGraphBuilder::GenerateDebugIsActive(CallRuntime* call) {
}
-void HOptimizedGraphBuilder::GenerateGetPrototype(CallRuntime* call) {
- DCHECK(call->arguments()->length() == 1);
- CHECK_ALIVE(VisitForValue(call->arguments()->at(0)));
- HValue* object = Pop();
-
- NoObservableSideEffectsScope no_effects(this);
-
- HValue* map = Add<HLoadNamedField>(object, nullptr, HObjectAccess::ForMap());
- HValue* bit_field =
- Add<HLoadNamedField>(map, nullptr, HObjectAccess::ForMapBitField());
- HValue* is_access_check_needed_mask =
- Add<HConstant>(1 << Map::kIsAccessCheckNeeded);
- HValue* is_access_check_needed_test = AddUncasted<HBitwise>(
- Token::BIT_AND, bit_field, is_access_check_needed_mask);
-
- HValue* proto =
- Add<HLoadNamedField>(map, nullptr, HObjectAccess::ForPrototype());
- HValue* proto_map =
- Add<HLoadNamedField>(proto, nullptr, HObjectAccess::ForMap());
- HValue* proto_bit_field =
- Add<HLoadNamedField>(proto_map, nullptr, HObjectAccess::ForMapBitField());
- HValue* is_hidden_prototype_mask =
- Add<HConstant>(1 << Map::kIsHiddenPrototype);
- HValue* is_hidden_prototype_test = AddUncasted<HBitwise>(
- Token::BIT_AND, proto_bit_field, is_hidden_prototype_mask);
-
- {
- IfBuilder needs_runtime(this);
- needs_runtime.If<HCompareNumericAndBranch>(
- is_access_check_needed_test, graph()->GetConstant0(), Token::NE);
- needs_runtime.OrIf<HCompareNumericAndBranch>(
- is_hidden_prototype_test, graph()->GetConstant0(), Token::NE);
-
- needs_runtime.Then();
- {
- Add<HPushArguments>(object);
- Push(Add<HCallRuntime>(
- call->name(), Runtime::FunctionForId(Runtime::kGetPrototype), 1));
- }
-
- needs_runtime.Else();
- Push(proto);
- }
- return ast_context()->ReturnValue(Pop());
-}
-
-
#undef CHECK_BAILOUT
#undef CHECK_ALIVE
@@ -12995,6 +13201,12 @@ void HEnvironment::Drop(int count) {
}
+void HEnvironment::Print() const {
+ OFStream os(stdout);
+ os << *this << "\n";
+}
+
+
HEnvironment* HEnvironment::Copy() const {
return new(zone()) HEnvironment(this, zone());
}
@@ -13110,16 +13322,13 @@ std::ostream& operator<<(std::ostream& os, const HEnvironment& env) {
void HTracer::TraceCompilation(CompilationInfo* info) {
Tag tag(this, "compilation");
+ base::SmartArrayPointer<char> name = info->GetDebugName();
if (info->IsOptimizing()) {
- Handle<String> name = info->literal()->debug_name();
- PrintStringProperty("name", name->ToCString().get());
+ PrintStringProperty("name", name.get());
PrintIndent();
- trace_.Add("method \"%s:%d\"\n",
- name->ToCString().get(),
- info->optimization_id());
+ trace_.Add("method \"%s:%d\"\n", name.get(), info->optimization_id());
} else {
- CodeStub::Major major_key = info->code_stub()->MajorKey();
- PrintStringProperty("name", CodeStub::MajorName(major_key, false));
+ PrintStringProperty("name", name.get());
PrintStringProperty("method", "stub");
}
PrintLongProperty("date",
@@ -13356,7 +13565,7 @@ void HTracer::FlushToFile() {
void HStatistics::Initialize(CompilationInfo* info) {
- if (info->shared_info().is_null()) return;
+ if (!info->has_shared_info()) return;
source_size_ += info->shared_info()->SourceSize();
}