Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(150)

Side by Side Diff: src/hydrogen.cc

Issue 155723005: A64: Synchronize with r19001. (Closed) Base URL: https://v8.googlecode.com/svn/branches/experimental/a64
Patch Set: Created 6 years, 10 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
« no previous file with comments | « src/hydrogen.h ('k') | src/hydrogen-instructions.h » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 // Copyright 2013 the V8 project authors. All rights reserved. 1 // Copyright 2013 the V8 project authors. All rights reserved.
2 // Redistribution and use in source and binary forms, with or without 2 // Redistribution and use in source and binary forms, with or without
3 // modification, are permitted provided that the following conditions are 3 // modification, are permitted provided that the following conditions are
4 // met: 4 // met:
5 // 5 //
6 // * Redistributions of source code must retain the above copyright 6 // * Redistributions of source code must retain the above copyright
7 // notice, this list of conditions and the following disclaimer. 7 // notice, this list of conditions and the following disclaimer.
8 // * Redistributions in binary form must reproduce the above 8 // * Redistributions in binary form must reproduce the above
9 // copyright notice, this list of conditions and the following 9 // copyright notice, this list of conditions and the following
10 // disclaimer in the documentation and/or other materials provided 10 // disclaimer in the documentation and/or other materials provided
(...skipping 209 matching lines...) Expand 10 before | Expand all | Expand 10 after
220 it.Current()->RegisterPredecessor(this); 220 it.Current()->RegisterPredecessor(this);
221 } 221 }
222 } 222 }
223 223
224 224
225 void HBasicBlock::Goto(HBasicBlock* block, 225 void HBasicBlock::Goto(HBasicBlock* block,
226 int position, 226 int position,
227 FunctionState* state, 227 FunctionState* state,
228 bool add_simulate) { 228 bool add_simulate) {
229 bool drop_extra = state != NULL && 229 bool drop_extra = state != NULL &&
230 state->inlining_kind() == DROP_EXTRA_ON_RETURN; 230 state->inlining_kind() == NORMAL_RETURN;
231 231
232 if (block->IsInlineReturnTarget()) { 232 if (block->IsInlineReturnTarget()) {
233 HEnvironment* env = last_environment(); 233 HEnvironment* env = last_environment();
234 int argument_count = env->arguments_environment()->parameter_count(); 234 int argument_count = env->arguments_environment()->parameter_count();
235 AddInstruction(new(zone()) 235 AddInstruction(new(zone())
236 HLeaveInlined(state->entry(), argument_count), 236 HLeaveInlined(state->entry(), argument_count),
237 position); 237 position);
238 UpdateEnvironment(last_environment()->DiscardInlined(drop_extra)); 238 UpdateEnvironment(last_environment()->DiscardInlined(drop_extra));
239 } 239 }
240 240
241 if (add_simulate) AddNewSimulate(BailoutId::None(), position); 241 if (add_simulate) AddNewSimulate(BailoutId::None(), position);
242 HGoto* instr = new(zone()) HGoto(block); 242 HGoto* instr = new(zone()) HGoto(block);
243 Finish(instr, position); 243 Finish(instr, position);
244 } 244 }
245 245
246 246
247 void HBasicBlock::AddLeaveInlined(HValue* return_value, 247 void HBasicBlock::AddLeaveInlined(HValue* return_value,
248 FunctionState* state, 248 FunctionState* state,
249 int position) { 249 int position) {
250 HBasicBlock* target = state->function_return(); 250 HBasicBlock* target = state->function_return();
251 bool drop_extra = state->inlining_kind() == DROP_EXTRA_ON_RETURN; 251 bool drop_extra = state->inlining_kind() == NORMAL_RETURN;
252 252
253 ASSERT(target->IsInlineReturnTarget()); 253 ASSERT(target->IsInlineReturnTarget());
254 ASSERT(return_value != NULL); 254 ASSERT(return_value != NULL);
255 HEnvironment* env = last_environment(); 255 HEnvironment* env = last_environment();
256 int argument_count = env->arguments_environment()->parameter_count(); 256 int argument_count = env->arguments_environment()->parameter_count();
257 AddInstruction(new(zone()) HLeaveInlined(state->entry(), argument_count), 257 AddInstruction(new(zone()) HLeaveInlined(state->entry(), argument_count),
258 position); 258 position);
259 UpdateEnvironment(last_environment()->DiscardInlined(drop_extra)); 259 UpdateEnvironment(last_environment()->DiscardInlined(drop_extra));
260 last_environment()->Push(return_value); 260 last_environment()->Push(return_value);
261 AddNewSimulate(BailoutId::None(), position); 261 AddNewSimulate(BailoutId::None(), position);
(...skipping 35 matching lines...) Expand 10 before | Expand all | Expand 10 after
297 bool HBasicBlock::Dominates(HBasicBlock* other) const { 297 bool HBasicBlock::Dominates(HBasicBlock* other) const {
298 HBasicBlock* current = other->dominator(); 298 HBasicBlock* current = other->dominator();
299 while (current != NULL) { 299 while (current != NULL) {
300 if (current == this) return true; 300 if (current == this) return true;
301 current = current->dominator(); 301 current = current->dominator();
302 } 302 }
303 return false; 303 return false;
304 } 304 }
305 305
306 306
307 bool HBasicBlock::EqualToOrDominates(HBasicBlock* other) const {
308 if (this == other) return true;
309 return Dominates(other);
310 }
311
312
307 int HBasicBlock::LoopNestingDepth() const { 313 int HBasicBlock::LoopNestingDepth() const {
308 const HBasicBlock* current = this; 314 const HBasicBlock* current = this;
309 int result = (current->IsLoopHeader()) ? 1 : 0; 315 int result = (current->IsLoopHeader()) ? 1 : 0;
310 while (current->parent_loop_header() != NULL) { 316 while (current->parent_loop_header() != NULL) {
311 current = current->parent_loop_header(); 317 current = current->parent_loop_header();
312 result++; 318 result++;
313 } 319 }
314 return result; 320 return result;
315 } 321 }
316 322
(...skipping 965 matching lines...) Expand 10 before | Expand all | Expand 10 after
1282 !HConstant::cast(string)->HasStringValue()); 1288 !HConstant::cast(string)->HasStringValue());
1283 BuildCheckHeapObject(string); 1289 BuildCheckHeapObject(string);
1284 return Add<HCheckInstanceType>(string, HCheckInstanceType::IS_STRING); 1290 return Add<HCheckInstanceType>(string, HCheckInstanceType::IS_STRING);
1285 } 1291 }
1286 return string; 1292 return string;
1287 } 1293 }
1288 1294
1289 1295
1290 HValue* HGraphBuilder::BuildWrapReceiver(HValue* object, HValue* function) { 1296 HValue* HGraphBuilder::BuildWrapReceiver(HValue* object, HValue* function) {
1291 if (object->type().IsJSObject()) return object; 1297 if (object->type().IsJSObject()) return object;
1298 if (function->IsConstant() &&
1299 HConstant::cast(function)->handle(isolate())->IsJSFunction()) {
1300 Handle<JSFunction> f = Handle<JSFunction>::cast(
1301 HConstant::cast(function)->handle(isolate()));
1302 SharedFunctionInfo* shared = f->shared();
1303 if (!shared->is_classic_mode() || shared->native()) return object;
1304 }
1292 return Add<HWrapReceiver>(object, function); 1305 return Add<HWrapReceiver>(object, function);
1293 } 1306 }
1294 1307
1295 1308
1296 HValue* HGraphBuilder::BuildCheckForCapacityGrow(HValue* object, 1309 HValue* HGraphBuilder::BuildCheckForCapacityGrow(HValue* object,
1297 HValue* elements, 1310 HValue* elements,
1298 ElementsKind kind, 1311 ElementsKind kind,
1299 HValue* length, 1312 HValue* length,
1300 HValue* key, 1313 HValue* key,
1301 bool is_js_array, 1314 bool is_js_array,
(...skipping 3617 matching lines...) Expand 10 before | Expand all | Expand 10 after
4919 Handle<JSFunction> closure = function_state()->compilation_info()->closure(); 4932 Handle<JSFunction> closure = function_state()->compilation_info()->closure();
4920 Handle<FixedArray> literals(closure->literals()); 4933 Handle<FixedArray> literals(closure->literals());
4921 HRegExpLiteral* instr = New<HRegExpLiteral>(literals, 4934 HRegExpLiteral* instr = New<HRegExpLiteral>(literals,
4922 expr->pattern(), 4935 expr->pattern(),
4923 expr->flags(), 4936 expr->flags(),
4924 expr->literal_index()); 4937 expr->literal_index());
4925 return ast_context()->ReturnInstruction(instr, expr->id()); 4938 return ast_context()->ReturnInstruction(instr, expr->id());
4926 } 4939 }
4927 4940
4928 4941
4929 static bool CanInlinePropertyAccess(Map* type) { 4942 static bool CanInlinePropertyAccess(Handle<HeapType> type) {
4930 return type->IsJSObjectMap() && 4943 if (type->Is(HeapType::NumberOrString())) return true;
4931 !type->is_dictionary_map() && 4944 if (!type->IsClass()) return false;
4932 !type->has_named_interceptor(); 4945 Handle<Map> map = type->AsClass();
4946 return map->IsJSObjectMap() &&
4947 !map->is_dictionary_map() &&
4948 !map->has_named_interceptor();
4933 } 4949 }
4934 4950
4935 4951
4936 static void LookupInPrototypes(Handle<Map> map, 4952 static void LookupInPrototypes(Handle<Map> map,
4937 Handle<String> name, 4953 Handle<String> name,
4938 LookupResult* lookup) { 4954 LookupResult* lookup) {
4939 while (map->prototype()->IsJSObject()) { 4955 while (map->prototype()->IsJSObject()) {
4940 Handle<JSObject> holder(JSObject::cast(map->prototype())); 4956 Handle<JSObject> holder(JSObject::cast(map->prototype()));
4941 map = Handle<Map>(holder->map()); 4957 map = handle(holder->map());
4942 if (!CanInlinePropertyAccess(*map)) break; 4958 if (!CanInlinePropertyAccess(IC::MapToType(map))) break;
4943 map->LookupDescriptor(*holder, *name, lookup); 4959 map->LookupDescriptor(*holder, *name, lookup);
4944 if (lookup->IsFound()) return; 4960 if (lookup->IsFound()) return;
4945 } 4961 }
4946 lookup->NotFound(); 4962 lookup->NotFound();
4947 } 4963 }
4948 4964
4949 4965
4950 // Tries to find a JavaScript accessor of the given name in the prototype chain 4966 // Tries to find a JavaScript accessor of the given name in the prototype chain
4951 // starting at the given map. Return true iff there is one, including the 4967 // starting at the given map. Return true iff there is one, including the
4952 // corresponding AccessorPair plus its holder (which could be null when the 4968 // corresponding AccessorPair plus its holder (which could be null when the
(...skipping 480 matching lines...) Expand 10 before | Expand all | Expand 10 after
5433 function_strict_mode_flag()); 5449 function_strict_mode_flag());
5434 } 5450 }
5435 5451
5436 5452
5437 // Sets the lookup result and returns true if the load/store can be inlined. 5453 // Sets the lookup result and returns true if the load/store can be inlined.
5438 static bool ComputeStoreField(Handle<Map> type, 5454 static bool ComputeStoreField(Handle<Map> type,
5439 Handle<String> name, 5455 Handle<String> name,
5440 LookupResult* lookup, 5456 LookupResult* lookup,
5441 bool lookup_transition = true) { 5457 bool lookup_transition = true) {
5442 ASSERT(!type->is_observed()); 5458 ASSERT(!type->is_observed());
5443 if (!CanInlinePropertyAccess(*type)) { 5459 if (!CanInlinePropertyAccess(IC::MapToType(type))) {
5444 lookup->NotFound(); 5460 lookup->NotFound();
5445 return false; 5461 return false;
5446 } 5462 }
5447 // If we directly find a field, the access can be inlined. 5463 // If we directly find a field, the access can be inlined.
5448 type->LookupDescriptor(NULL, *name, lookup); 5464 type->LookupDescriptor(NULL, *name, lookup);
5449 if (lookup->IsField()) return true; 5465 if (lookup->IsField()) return true;
5450 5466
5451 if (!lookup_transition) return false; 5467 if (!lookup_transition) return false;
5452 5468
5453 type->LookupTransition(NULL, *name, lookup); 5469 type->LookupTransition(NULL, *name, lookup);
(...skipping 14 matching lines...) Expand all
5468 return BuildStoreNamedField(checked_object, name, value, map, &lookup); 5484 return BuildStoreNamedField(checked_object, name, value, map, &lookup);
5469 } 5485 }
5470 5486
5471 // No luck, do a generic store. 5487 // No luck, do a generic store.
5472 return BuildStoreNamedGeneric(object, name, value); 5488 return BuildStoreNamedGeneric(object, name, value);
5473 } 5489 }
5474 5490
5475 5491
5476 bool HOptimizedGraphBuilder::PropertyAccessInfo::IsCompatibleForLoad( 5492 bool HOptimizedGraphBuilder::PropertyAccessInfo::IsCompatibleForLoad(
5477 PropertyAccessInfo* info) { 5493 PropertyAccessInfo* info) {
5478 if (!CanInlinePropertyAccess(*map_)) return false; 5494 if (!CanInlinePropertyAccess(type_)) return false;
5495
5496 // Currently only handle HeapType::Number as a polymorphic case.
5497 // TODO(verwaest): Support monomorphic handling of numbers with a HCheckNumber
5498 // instruction.
5499 if (type_->Is(HeapType::Number())) return false;
5500
5501 // Values are only compatible for monomorphic load if they all behave the same
5502 // regarding value wrappers.
5503 if (type_->Is(HeapType::NumberOrString())) {
5504 if (!info->type_->Is(HeapType::NumberOrString())) return false;
5505 } else {
5506 if (info->type_->Is(HeapType::NumberOrString())) return false;
5507 }
5479 5508
5480 if (!LookupDescriptor()) return false; 5509 if (!LookupDescriptor()) return false;
5481 5510
5482 if (!lookup_.IsFound()) { 5511 if (!lookup_.IsFound()) {
5483 return (!info->lookup_.IsFound() || info->has_holder()) && 5512 return (!info->lookup_.IsFound() || info->has_holder()) &&
5484 map_->prototype() == info->map_->prototype(); 5513 map()->prototype() == info->map()->prototype();
5485 } 5514 }
5486 5515
5487 // Mismatch if the other access info found the property in the prototype 5516 // Mismatch if the other access info found the property in the prototype
5488 // chain. 5517 // chain.
5489 if (info->has_holder()) return false; 5518 if (info->has_holder()) return false;
5490 5519
5491 if (lookup_.IsPropertyCallbacks()) { 5520 if (lookup_.IsPropertyCallbacks()) {
5492 return accessor_.is_identical_to(info->accessor_); 5521 return accessor_.is_identical_to(info->accessor_);
5493 } 5522 }
5494 5523
5495 if (lookup_.IsConstant()) { 5524 if (lookup_.IsConstant()) {
5496 return constant_.is_identical_to(info->constant_); 5525 return constant_.is_identical_to(info->constant_);
5497 } 5526 }
5498 5527
5499 ASSERT(lookup_.IsField()); 5528 ASSERT(lookup_.IsField());
5500 if (!info->lookup_.IsField()) return false; 5529 if (!info->lookup_.IsField()) return false;
5501 5530
5502 Representation r = access_.representation(); 5531 Representation r = access_.representation();
5503 if (!info->access_.representation().IsCompatibleForLoad(r)) return false; 5532 if (!info->access_.representation().IsCompatibleForLoad(r)) return false;
5504 if (info->access_.offset() != access_.offset()) return false; 5533 if (info->access_.offset() != access_.offset()) return false;
5505 if (info->access_.IsInobject() != access_.IsInobject()) return false; 5534 if (info->access_.IsInobject() != access_.IsInobject()) return false;
5506 info->GeneralizeRepresentation(r); 5535 info->GeneralizeRepresentation(r);
5507 return true; 5536 return true;
5508 } 5537 }
5509 5538
5510 5539
5511 bool HOptimizedGraphBuilder::PropertyAccessInfo::LookupDescriptor() { 5540 bool HOptimizedGraphBuilder::PropertyAccessInfo::LookupDescriptor() {
5512 map_->LookupDescriptor(NULL, *name_, &lookup_); 5541 if (!type_->IsClass()) return true;
5513 return LoadResult(map_); 5542 map()->LookupDescriptor(NULL, *name_, &lookup_);
5543 return LoadResult(map());
5514 } 5544 }
5515 5545
5516 5546
5517 bool HOptimizedGraphBuilder::PropertyAccessInfo::LoadResult(Handle<Map> map) { 5547 bool HOptimizedGraphBuilder::PropertyAccessInfo::LoadResult(Handle<Map> map) {
5518 if (lookup_.IsField()) { 5548 if (lookup_.IsField()) {
5519 access_ = HObjectAccess::ForField(map, &lookup_, name_); 5549 access_ = HObjectAccess::ForField(map, &lookup_, name_);
5520 } else if (lookup_.IsPropertyCallbacks()) { 5550 } else if (lookup_.IsPropertyCallbacks()) {
5521 Handle<Object> callback(lookup_.GetValueFromMap(*map), isolate()); 5551 Handle<Object> callback(lookup_.GetValueFromMap(*map), isolate());
5522 if (!callback->IsAccessorPair()) return false; 5552 if (!callback->IsAccessorPair()) return false;
5523 Object* getter = Handle<AccessorPair>::cast(callback)->getter(); 5553 Object* getter = Handle<AccessorPair>::cast(callback)->getter();
5524 if (!getter->IsJSFunction()) return false; 5554 if (!getter->IsJSFunction()) return false;
5525 Handle<JSFunction> accessor = handle(JSFunction::cast(getter)); 5555 Handle<JSFunction> accessor = handle(JSFunction::cast(getter));
5526 CallOptimization call_optimization(accessor); 5556 CallOptimization call_optimization(accessor);
5527 // TODO(dcarney): temporary hack unless crankshaft can handle api calls. 5557 // TODO(dcarney): temporary hack unless crankshaft can handle api calls.
5528 if (call_optimization.is_simple_api_call()) return false; 5558 if (call_optimization.is_simple_api_call()) return false;
5529 accessor_ = accessor; 5559 accessor_ = accessor;
5530 } else if (lookup_.IsConstant()) { 5560 } else if (lookup_.IsConstant()) {
5531 constant_ = handle(lookup_.GetConstantFromMap(*map), isolate()); 5561 constant_ = handle(lookup_.GetConstantFromMap(*map), isolate());
5532 } 5562 }
5533 5563
5534 return true; 5564 return true;
5535 } 5565 }
5536 5566
5537 5567
5538 bool HOptimizedGraphBuilder::PropertyAccessInfo::LookupInPrototypes() { 5568 bool HOptimizedGraphBuilder::PropertyAccessInfo::LookupInPrototypes() {
5539 Handle<Map> map = map_; 5569 Handle<Map> map = this->map();
5570
5540 while (map->prototype()->IsJSObject()) { 5571 while (map->prototype()->IsJSObject()) {
5541 holder_ = handle(JSObject::cast(map->prototype())); 5572 holder_ = handle(JSObject::cast(map->prototype()));
5542 if (holder_->map()->is_deprecated()) { 5573 if (holder_->map()->is_deprecated()) {
5543 JSObject::TryMigrateInstance(holder_); 5574 JSObject::TryMigrateInstance(holder_);
5544 } 5575 }
5545 map = Handle<Map>(holder_->map()); 5576 map = Handle<Map>(holder_->map());
5546 if (!CanInlinePropertyAccess(*map)) { 5577 if (!CanInlinePropertyAccess(IC::MapToType(map))) {
5547 lookup_.NotFound(); 5578 lookup_.NotFound();
5548 return false; 5579 return false;
5549 } 5580 }
5550 map->LookupDescriptor(*holder_, *name_, &lookup_); 5581 map->LookupDescriptor(*holder_, *name_, &lookup_);
5551 if (lookup_.IsFound()) return LoadResult(map); 5582 if (lookup_.IsFound()) return LoadResult(map);
5552 } 5583 }
5553 lookup_.NotFound(); 5584 lookup_.NotFound();
5554 return true; 5585 return true;
5555 } 5586 }
5556 5587
5557 5588
5558 bool HOptimizedGraphBuilder::PropertyAccessInfo::CanLoadMonomorphic() { 5589 bool HOptimizedGraphBuilder::PropertyAccessInfo::CanLoadMonomorphic() {
5559 if (!CanInlinePropertyAccess(*map_)) return IsStringLength(); 5590 if (!CanInlinePropertyAccess(type_)) return false;
5560 if (IsJSObjectFieldAccessor()) return true; 5591 if (IsJSObjectFieldAccessor()) return true;
5561 if (!LookupDescriptor()) return false; 5592 if (!LookupDescriptor()) return false;
5562 if (lookup_.IsFound()) return true; 5593 if (lookup_.IsFound()) return true;
5563 return LookupInPrototypes(); 5594 return LookupInPrototypes();
5564 } 5595 }
5565 5596
5566 5597
5567 bool HOptimizedGraphBuilder::PropertyAccessInfo::CanLoadAsMonomorphic( 5598 bool HOptimizedGraphBuilder::PropertyAccessInfo::CanLoadAsMonomorphic(
5568 SmallMapList* types) { 5599 SmallMapList* types) {
5569 ASSERT(map_.is_identical_to(types->first())); 5600 ASSERT(type_->Is(IC::MapToType(types->first())));
5570 if (!CanLoadMonomorphic()) return false; 5601 if (!CanLoadMonomorphic()) return false;
5571 if (types->length() > kMaxLoadPolymorphism) return false; 5602 if (types->length() > kMaxLoadPolymorphism) return false;
5572 5603
5573 if (IsStringLength()) {
5574 for (int i = 1; i < types->length(); ++i) {
5575 if (types->at(i)->instance_type() >= FIRST_NONSTRING_TYPE) return false;
5576 }
5577 return true;
5578 }
5579
5580 if (IsArrayLength()) { 5604 if (IsArrayLength()) {
5581 bool is_fast = IsFastElementsKind(map_->elements_kind()); 5605 bool is_fast = IsFastElementsKind(map()->elements_kind());
5582 for (int i = 1; i < types->length(); ++i) { 5606 for (int i = 1; i < types->length(); ++i) {
5583 Handle<Map> test_map = types->at(i); 5607 Handle<Map> test_map = types->at(i);
5584 if (test_map->instance_type() != JS_ARRAY_TYPE) return false; 5608 if (test_map->instance_type() != JS_ARRAY_TYPE) return false;
5585 if (IsFastElementsKind(test_map->elements_kind()) != is_fast) { 5609 if (IsFastElementsKind(test_map->elements_kind()) != is_fast) {
5586 return false; 5610 return false;
5587 } 5611 }
5588 } 5612 }
5589 return true; 5613 return true;
5590 } 5614 }
5591 5615
5592 if (IsJSObjectFieldAccessor()) { 5616 HObjectAccess access = HObjectAccess::ForMap(); // bogus default
5593 InstanceType instance_type = map_->instance_type(); 5617 if (GetJSObjectFieldAccess(&access)) {
5594 for (int i = 1; i < types->length(); ++i) { 5618 for (int i = 1; i < types->length(); ++i) {
5595 if (types->at(i)->instance_type() != instance_type) return false; 5619 PropertyAccessInfo test_info(
5620 builder_, IC::MapToType(types->at(i)), name_);
5621 HObjectAccess test_access = HObjectAccess::ForMap(); // bogus default
5622 if (!test_info.GetJSObjectFieldAccess(&test_access)) return false;
5623 if (!access.Equals(test_access)) return false;
5596 } 5624 }
5597 return true; 5625 return true;
5598 } 5626 }
5599 5627
5628 // Currently only handle HeapType::Number as a polymorphic case.
5629 // TODO(verwaest): Support monomorphic handling of numbers with a HCheckNumber
5630 // instruction.
5631 if (type_->Is(HeapType::Number())) return false;
5632
5600 for (int i = 1; i < types->length(); ++i) { 5633 for (int i = 1; i < types->length(); ++i) {
5601 PropertyAccessInfo test_info(isolate(), types->at(i), name_); 5634 PropertyAccessInfo test_info(builder_, IC::MapToType(types->at(i)), name_);
5602 if (!test_info.IsCompatibleForLoad(this)) return false; 5635 if (!test_info.IsCompatibleForLoad(this)) return false;
5603 } 5636 }
5604 5637
5605 return true; 5638 return true;
5606 } 5639 }
5607 5640
5608 5641
5642 static bool NeedsWrappingFor(Handle<HeapType> type, Handle<JSFunction> target) {
5643 return type->Is(HeapType::NumberOrString()) &&
5644 target->shared()->is_classic_mode() &&
5645 !target->shared()->native();
5646 }
5647
5648
5609 HInstruction* HOptimizedGraphBuilder::BuildLoadMonomorphic( 5649 HInstruction* HOptimizedGraphBuilder::BuildLoadMonomorphic(
5610 PropertyAccessInfo* info, 5650 PropertyAccessInfo* info,
5611 HValue* object, 5651 HValue* object,
5612 HInstruction* checked_object, 5652 HValue* checked_object,
5613 BailoutId ast_id, 5653 BailoutId ast_id,
5614 BailoutId return_id, 5654 BailoutId return_id,
5615 bool can_inline_accessor) { 5655 bool can_inline_accessor) {
5616 5656
5617 HObjectAccess access = HObjectAccess::ForMap(); // bogus default 5657 HObjectAccess access = HObjectAccess::ForMap(); // bogus default
5618 if (info->GetJSObjectFieldAccess(&access)) { 5658 if (info->GetJSObjectFieldAccess(&access)) {
5619 return New<HLoadNamedField>( 5659 return New<HLoadNamedField>(
5620 checked_object, static_cast<HValue*>(NULL), access); 5660 checked_object, static_cast<HValue*>(NULL), access);
5621 } 5661 }
5622 5662
5623 HValue* checked_holder = checked_object; 5663 HValue* checked_holder = checked_object;
5624 if (info->has_holder()) { 5664 if (info->has_holder()) {
5625 Handle<JSObject> prototype(JSObject::cast(info->map()->prototype())); 5665 Handle<JSObject> prototype(JSObject::cast(info->map()->prototype()));
5626 checked_holder = BuildCheckPrototypeMaps(prototype, info->holder()); 5666 checked_holder = BuildCheckPrototypeMaps(prototype, info->holder());
5627 } 5667 }
5628 5668
5629 if (!info->lookup()->IsFound()) return graph()->GetConstantUndefined(); 5669 if (!info->lookup()->IsFound()) return graph()->GetConstantUndefined();
5630 5670
5631 if (info->lookup()->IsField()) { 5671 if (info->lookup()->IsField()) {
5632 return BuildLoadNamedField(checked_holder, info->access()); 5672 return BuildLoadNamedField(checked_holder, info->access());
5633 } 5673 }
5634 5674
5635 if (info->lookup()->IsPropertyCallbacks()) { 5675 if (info->lookup()->IsPropertyCallbacks()) {
5636 Push(checked_object); 5676 if (NeedsWrappingFor(info->type(), info->accessor())) {
5637 if (FLAG_inline_accessors && 5677 HValue* function = Add<HConstant>(info->accessor());
5638 can_inline_accessor && 5678 Add<HPushArgument>(checked_object);
5639 TryInlineGetter(info->accessor(), ast_id, return_id)) { 5679 return New<HCallFunction>(function, 1, WRAP_AND_CALL);
5640 return NULL; 5680 } else {
5681 Push(checked_object);
5682 if (FLAG_inline_accessors &&
5683 can_inline_accessor &&
5684 TryInlineGetter(info->accessor(), ast_id, return_id)) {
5685 return NULL;
5686 }
5687 Add<HPushArgument>(Pop());
5688 return BuildCallConstantFunction(info->accessor(), 1);
5641 } 5689 }
5642 Add<HPushArgument>(Pop());
5643 return BuildCallConstantFunction(info->accessor(), 1);
5644 } 5690 }
5645 5691
5646 ASSERT(info->lookup()->IsConstant()); 5692 ASSERT(info->lookup()->IsConstant());
5647 return New<HConstant>(info->constant()); 5693 return New<HConstant>(info->constant());
5648 } 5694 }
5649 5695
5650 5696
5651 void HOptimizedGraphBuilder::HandlePolymorphicLoadNamedField( 5697 void HOptimizedGraphBuilder::HandlePolymorphicLoadNamedField(
5652 BailoutId ast_id, 5698 BailoutId ast_id,
5653 BailoutId return_id, 5699 BailoutId return_id,
5654 HValue* object, 5700 HValue* object,
5655 SmallMapList* types, 5701 SmallMapList* types,
5656 Handle<String> name) { 5702 Handle<String> name) {
5657 // Something did not match; must use a polymorphic load. 5703 // Something did not match; must use a polymorphic load.
5658 int count = 0; 5704 int count = 0;
5659 HBasicBlock* join = NULL; 5705 HBasicBlock* join = NULL;
5706 HBasicBlock* number_block = NULL;
5707 bool handled_string = false;
5708
5709 bool handle_smi = false;
5660 for (int i = 0; i < types->length() && count < kMaxLoadPolymorphism; ++i) { 5710 for (int i = 0; i < types->length() && count < kMaxLoadPolymorphism; ++i) {
5661 PropertyAccessInfo info(isolate(), types->at(i), name); 5711 PropertyAccessInfo info(this, IC::MapToType(types->at(i)), name);
5712 if (info.type()->Is(HeapType::String())) {
5713 if (handled_string) continue;
5714 handled_string = true;
5715 }
5662 if (info.CanLoadMonomorphic()) { 5716 if (info.CanLoadMonomorphic()) {
5663 if (count == 0) { 5717 count++;
5664 BuildCheckHeapObject(object); 5718 if (info.type()->Is(HeapType::Number())) {
5665 join = graph()->CreateBasicBlock(); 5719 handle_smi = true;
5720 break;
5666 } 5721 }
5667 ++count;
5668 HBasicBlock* if_true = graph()->CreateBasicBlock();
5669 HBasicBlock* if_false = graph()->CreateBasicBlock();
5670 HCompareMap* compare = New<HCompareMap>(
5671 object, info.map(), if_true, if_false);
5672 FinishCurrentBlock(compare);
5673
5674 set_current_block(if_true);
5675
5676 HInstruction* load = BuildLoadMonomorphic(
5677 &info, object, compare, ast_id, return_id, FLAG_polymorphic_inlining);
5678 if (load == NULL) {
5679 if (HasStackOverflow()) return;
5680 } else {
5681 if (!load->IsLinked()) {
5682 AddInstruction(load);
5683 }
5684 if (!ast_context()->IsEffect()) Push(load);
5685 }
5686
5687 if (current_block() != NULL) Goto(join);
5688 set_current_block(if_false);
5689 } 5722 }
5690 } 5723 }
5691 5724
5725 count = 0;
5726 HControlInstruction* smi_check = NULL;
5727 handled_string = false;
5728
5729 for (int i = 0; i < types->length() && count < kMaxLoadPolymorphism; ++i) {
5730 PropertyAccessInfo info(this, IC::MapToType(types->at(i)), name);
5731 if (info.type()->Is(HeapType::String())) {
5732 if (handled_string) continue;
5733 handled_string = true;
5734 }
5735 if (!info.CanLoadMonomorphic()) continue;
5736
5737 if (count == 0) {
5738 join = graph()->CreateBasicBlock();
5739 if (handle_smi) {
5740 HBasicBlock* empty_smi_block = graph()->CreateBasicBlock();
5741 HBasicBlock* not_smi_block = graph()->CreateBasicBlock();
5742 number_block = graph()->CreateBasicBlock();
5743 smi_check = New<HIsSmiAndBranch>(
5744 object, empty_smi_block, not_smi_block);
5745 FinishCurrentBlock(smi_check);
5746 Goto(empty_smi_block, number_block);
5747 set_current_block(not_smi_block);
5748 } else {
5749 BuildCheckHeapObject(object);
5750 }
5751 }
5752 ++count;
5753 HBasicBlock* if_true = graph()->CreateBasicBlock();
5754 HBasicBlock* if_false = graph()->CreateBasicBlock();
5755 HUnaryControlInstruction* compare;
5756
5757 HValue* dependency;
5758 if (info.type()->Is(HeapType::Number())) {
5759 Handle<Map> heap_number_map = isolate()->factory()->heap_number_map();
5760 compare = New<HCompareMap>(object, heap_number_map, if_true, if_false);
5761 dependency = smi_check;
5762 } else if (info.type()->Is(HeapType::String())) {
5763 compare = New<HIsStringAndBranch>(object, if_true, if_false);
5764 dependency = compare;
5765 } else {
5766 compare = New<HCompareMap>(object, info.map(), if_true, if_false);
5767 dependency = compare;
5768 }
5769 FinishCurrentBlock(compare);
5770
5771 if (info.type()->Is(HeapType::Number())) {
5772 Goto(if_true, number_block);
5773 if_true = number_block;
5774 number_block->SetJoinId(ast_id);
5775 }
5776
5777 set_current_block(if_true);
5778
5779 HInstruction* load = BuildLoadMonomorphic(
5780 &info, object, dependency, ast_id,
5781 return_id, FLAG_polymorphic_inlining);
5782 if (load == NULL) {
5783 if (HasStackOverflow()) return;
5784 } else {
5785 if (!load->IsLinked()) {
5786 AddInstruction(load);
5787 }
5788 if (!ast_context()->IsEffect()) Push(load);
5789 }
5790
5791 if (current_block() != NULL) Goto(join);
5792 set_current_block(if_false);
5793 }
5794
5692 // Finish up. Unconditionally deoptimize if we've handled all the maps we 5795 // Finish up. Unconditionally deoptimize if we've handled all the maps we
5693 // know about and do not want to handle ones we've never seen. Otherwise 5796 // know about and do not want to handle ones we've never seen. Otherwise
5694 // use a generic IC. 5797 // use a generic IC.
5695 if (count == types->length() && FLAG_deoptimize_uncommon_cases) { 5798 if (count == types->length() && FLAG_deoptimize_uncommon_cases) {
5696 // Because the deopt may be the only path in the polymorphic load, make sure 5799 // Because the deopt may be the only path in the polymorphic load, make sure
5697 // that the environment stack matches the depth on deopt that it otherwise 5800 // that the environment stack matches the depth on deopt that it otherwise
5698 // would have had after a successful load. 5801 // would have had after a successful load.
5699 if (!ast_context()->IsEffect()) Push(graph()->GetConstant0()); 5802 if (!ast_context()->IsEffect()) Push(graph()->GetConstant0());
5700 FinishExitWithHardDeoptimization("Unknown map in polymorphic load", join); 5803 FinishExitWithHardDeoptimization("Unknown map in polymorphic load", join);
5701 } else { 5804 } else {
(...skipping 161 matching lines...) Expand 10 before | Expand all | Expand 10 after
5863 HValue* receiver, 5966 HValue* receiver,
5864 SmallMapList** t) { 5967 SmallMapList** t) {
5865 SmallMapList* types = expr->GetReceiverTypes(); 5968 SmallMapList* types = expr->GetReceiverTypes();
5866 *t = types; 5969 *t = types;
5867 bool monomorphic = expr->IsMonomorphic(); 5970 bool monomorphic = expr->IsMonomorphic();
5868 if (types != NULL && receiver->HasMonomorphicJSObjectType()) { 5971 if (types != NULL && receiver->HasMonomorphicJSObjectType()) {
5869 Map* root_map = receiver->GetMonomorphicJSObjectMap()->FindRootMap(); 5972 Map* root_map = receiver->GetMonomorphicJSObjectMap()->FindRootMap();
5870 types->FilterForPossibleTransitions(root_map); 5973 types->FilterForPossibleTransitions(root_map);
5871 monomorphic = types->length() == 1; 5974 monomorphic = types->length() == 1;
5872 } 5975 }
5873 return monomorphic && CanInlinePropertyAccess(*types->first()); 5976 return monomorphic && CanInlinePropertyAccess(IC::MapToType(types->first()));
5874 } 5977 }
5875 5978
5876 5979
5877 void HOptimizedGraphBuilder::BuildStore(Expression* expr, 5980 void HOptimizedGraphBuilder::BuildStore(Expression* expr,
5878 Property* prop, 5981 Property* prop,
5879 BailoutId ast_id, 5982 BailoutId ast_id,
5880 BailoutId return_id, 5983 BailoutId return_id,
5881 bool is_uninitialized) { 5984 bool is_uninitialized) {
5882 HValue* value = environment()->ExpressionStackAt(0); 5985 HValue* value = environment()->ExpressionStackAt(0);
5883 5986
(...skipping 26 matching lines...) Expand all
5910 HInstruction* instr = NULL; 6013 HInstruction* instr = NULL;
5911 6014
5912 SmallMapList* types; 6015 SmallMapList* types;
5913 bool monomorphic = ComputeReceiverTypes(expr, object, &types); 6016 bool monomorphic = ComputeReceiverTypes(expr, object, &types);
5914 6017
5915 if (monomorphic) { 6018 if (monomorphic) {
5916 Handle<Map> map = types->first(); 6019 Handle<Map> map = types->first();
5917 Handle<JSFunction> setter; 6020 Handle<JSFunction> setter;
5918 Handle<JSObject> holder; 6021 Handle<JSObject> holder;
5919 if (LookupSetter(map, name, &setter, &holder)) { 6022 if (LookupSetter(map, name, &setter, &holder)) {
5920 AddCheckConstantFunction(holder, object, map); 6023 AddCheckMap(object, map);
5921 if (FLAG_inline_accessors && 6024 AddCheckPrototypeMaps(holder, map);
5922 TryInlineSetter(setter, ast_id, return_id, value)) { 6025 bool needs_wrapping = NeedsWrappingFor(IC::MapToType(map), setter);
6026 bool try_inline = FLAG_inline_accessors && !needs_wrapping;
6027 if (try_inline && TryInlineSetter(setter, ast_id, return_id, value)) {
5923 return; 6028 return;
5924 } 6029 }
5925 Drop(2); 6030 Drop(2);
5926 Add<HPushArgument>(object); 6031 Add<HPushArgument>(object);
5927 Add<HPushArgument>(value); 6032 Add<HPushArgument>(value);
5928 instr = BuildCallConstantFunction(setter, 2); 6033 if (needs_wrapping) {
6034 HValue* function = Add<HConstant>(setter);
6035 instr = New<HCallFunction>(function, 2, WRAP_AND_CALL);
6036 } else {
6037 instr = BuildCallConstantFunction(setter, 2);
6038 }
5929 } else { 6039 } else {
5930 Drop(2); 6040 Drop(2);
5931 CHECK_ALIVE(instr = BuildStoreNamedMonomorphic(object, 6041 CHECK_ALIVE(instr = BuildStoreNamedMonomorphic(object,
5932 name, 6042 name,
5933 value, 6043 value,
5934 map)); 6044 map));
5935 } 6045 }
5936 } else if (types != NULL && types->length() > 1) { 6046 } else if (types != NULL && types->length() > 1) {
5937 Drop(2); 6047 Drop(2);
5938 return HandlePolymorphicStoreNamedField(ast_id, object, value, types, name); 6048 return HandlePolymorphicStoreNamedField(ast_id, object, value, types, name);
(...skipping 310 matching lines...) Expand 10 before | Expand all | Expand 10 after
6249 ASSERT(current_block() != NULL); 6359 ASSERT(current_block() != NULL);
6250 ASSERT(current_block()->HasPredecessor()); 6360 ASSERT(current_block()->HasPredecessor());
6251 // We don't optimize functions with invalid left-hand sides in 6361 // We don't optimize functions with invalid left-hand sides in
6252 // assignments, count operations, or for-in. Consequently throw can 6362 // assignments, count operations, or for-in. Consequently throw can
6253 // currently only occur in an effect context. 6363 // currently only occur in an effect context.
6254 ASSERT(ast_context()->IsEffect()); 6364 ASSERT(ast_context()->IsEffect());
6255 CHECK_ALIVE(VisitForValue(expr->exception())); 6365 CHECK_ALIVE(VisitForValue(expr->exception()));
6256 6366
6257 HValue* value = environment()->Pop(); 6367 HValue* value = environment()->Pop();
6258 if (!FLAG_emit_opt_code_positions) SetSourcePosition(expr->position()); 6368 if (!FLAG_emit_opt_code_positions) SetSourcePosition(expr->position());
6259 Add<HThrow>(value); 6369 Add<HPushArgument>(value);
6370 Add<HCallRuntime>(isolate()->factory()->empty_string(),
6371 Runtime::FunctionForId(Runtime::kThrow), 1);
6260 Add<HSimulate>(expr->id()); 6372 Add<HSimulate>(expr->id());
6261 6373
6262 // If the throw definitely exits the function, we can finish with a dummy 6374 // If the throw definitely exits the function, we can finish with a dummy
6263 // control flow at this point. This is not the case if the throw is inside 6375 // control flow at this point. This is not the case if the throw is inside
6264 // an inlined function which may be replaced. 6376 // an inlined function which may be replaced.
6265 if (call_context() == NULL) { 6377 if (call_context() == NULL) {
6266 FinishExitCurrentBlock(New<HAbnormalExit>()); 6378 FinishExitCurrentBlock(New<HAbnormalExit>());
6267 } 6379 }
6268 } 6380 }
6269 6381
(...skipping 42 matching lines...) Expand 10 before | Expand all | Expand 10 after
6312 } 6424 }
6313 } 6425 }
6314 return AddLoadNamedField(string, HObjectAccess::ForStringLength()); 6426 return AddLoadNamedField(string, HObjectAccess::ForStringLength());
6315 } 6427 }
6316 6428
6317 6429
6318 HInstruction* HOptimizedGraphBuilder::BuildLoadNamedGeneric( 6430 HInstruction* HOptimizedGraphBuilder::BuildLoadNamedGeneric(
6319 HValue* object, 6431 HValue* object,
6320 Handle<String> name, 6432 Handle<String> name,
6321 Property* expr) { 6433 Property* expr) {
6322 if (expr->IsUninitialized()) { 6434 if (!expr->IsForCall() && expr->IsUninitialized()) {
6323 Add<HDeoptimize>("Insufficient type feedback for generic named load", 6435 Add<HDeoptimize>("Insufficient type feedback for generic named load",
6324 Deoptimizer::SOFT); 6436 Deoptimizer::SOFT);
6325 } 6437 }
6326 return New<HLoadNamedGeneric>(object, name); 6438 return New<HLoadNamedGeneric>(object, name);
6327 } 6439 }
6328 6440
6329 6441
6330 6442
6331 HInstruction* HOptimizedGraphBuilder::BuildLoadKeyedGeneric(HValue* object, 6443 HInstruction* HOptimizedGraphBuilder::BuildLoadKeyedGeneric(HValue* object,
6332 HValue* key) { 6444 HValue* key) {
(...skipping 270 matching lines...) Expand 10 before | Expand all | Expand 10 after
6603 if (current_map->DictionaryElementsInPrototypeChainOnly()) { 6715 if (current_map->DictionaryElementsInPrototypeChainOnly()) {
6604 force_generic = true; 6716 force_generic = true;
6605 monomorphic = false; 6717 monomorphic = false;
6606 break; 6718 break;
6607 } 6719 }
6608 } 6720 }
6609 } 6721 }
6610 6722
6611 if (monomorphic) { 6723 if (monomorphic) {
6612 Handle<Map> map = types->first(); 6724 Handle<Map> map = types->first();
6613 if (map->has_slow_elements_kind()) { 6725 if (map->has_slow_elements_kind() || !map->IsJSObjectMap()) {
6614 instr = is_store ? BuildStoreKeyedGeneric(obj, key, val) 6726 instr = is_store ? BuildStoreKeyedGeneric(obj, key, val)
6615 : BuildLoadKeyedGeneric(obj, key); 6727 : BuildLoadKeyedGeneric(obj, key);
6616 AddInstruction(instr); 6728 AddInstruction(instr);
6617 } else { 6729 } else {
6618 BuildCheckHeapObject(obj); 6730 BuildCheckHeapObject(obj);
6619 instr = BuildMonomorphicElementAccess( 6731 instr = BuildMonomorphicElementAccess(
6620 obj, key, val, NULL, map, is_store, expr->GetStoreMode()); 6732 obj, key, val, NULL, map, is_store, expr->GetStoreMode());
6621 } 6733 }
6622 } else if (!force_generic && (types != NULL && !types->is_empty())) { 6734 } else if (!force_generic && (types != NULL && !types->is_empty())) {
6623 return HandlePolymorphicElementAccess( 6735 return HandlePolymorphicElementAccess(
(...skipping 145 matching lines...) Expand 10 before | Expand all | Expand 10 after
6769 6881
6770 } else if (expr->key()->IsPropertyName()) { 6882 } else if (expr->key()->IsPropertyName()) {
6771 Handle<String> name = expr->key()->AsLiteral()->AsPropertyName(); 6883 Handle<String> name = expr->key()->AsLiteral()->AsPropertyName();
6772 HValue* object = Pop(); 6884 HValue* object = Pop();
6773 6885
6774 SmallMapList* types; 6886 SmallMapList* types;
6775 ComputeReceiverTypes(expr, object, &types); 6887 ComputeReceiverTypes(expr, object, &types);
6776 ASSERT(types != NULL); 6888 ASSERT(types != NULL);
6777 6889
6778 if (types->length() > 0) { 6890 if (types->length() > 0) {
6779 PropertyAccessInfo info(isolate(), types->first(), name); 6891 PropertyAccessInfo info(this, IC::MapToType(types->first()), name);
6780 if (!info.CanLoadAsMonomorphic(types)) { 6892 if (!info.CanLoadAsMonomorphic(types)) {
6781 return HandlePolymorphicLoadNamedField( 6893 return HandlePolymorphicLoadNamedField(
6782 ast_id, expr->LoadId(), object, types, name); 6894 ast_id, expr->LoadId(), object, types, name);
6783 } 6895 }
6784 6896
6897 HValue* checked_object;
6898 // HeapType::Number() is only supported by polymorphic load/call handling.
6899 ASSERT(!info.type()->Is(HeapType::Number()));
6785 BuildCheckHeapObject(object); 6900 BuildCheckHeapObject(object);
6786 HInstruction* checked_object;
6787 if (AreStringTypes(types)) { 6901 if (AreStringTypes(types)) {
6788 checked_object = 6902 checked_object =
6789 Add<HCheckInstanceType>(object, HCheckInstanceType::IS_STRING); 6903 Add<HCheckInstanceType>(object, HCheckInstanceType::IS_STRING);
6790 } else { 6904 } else {
6791 checked_object = Add<HCheckMaps>(object, types); 6905 checked_object = Add<HCheckMaps>(object, types);
6792 } 6906 }
6793 instr = BuildLoadMonomorphic( 6907 instr = BuildLoadMonomorphic(
6794 &info, object, checked_object, ast_id, expr->LoadId()); 6908 &info, object, checked_object, ast_id, expr->LoadId());
6795 if (instr == NULL) return; 6909 if (instr == NULL) return;
6796 if (instr->IsLinked()) return ast_context()->ReturnValue(instr); 6910 if (instr->IsLinked()) return ast_context()->ReturnValue(instr);
(...skipping 75 matching lines...) Expand 10 before | Expand all | Expand 10 after
6872 6986
6873 void HOptimizedGraphBuilder::AddCheckPrototypeMaps(Handle<JSObject> holder, 6987 void HOptimizedGraphBuilder::AddCheckPrototypeMaps(Handle<JSObject> holder,
6874 Handle<Map> receiver_map) { 6988 Handle<Map> receiver_map) {
6875 if (!holder.is_null()) { 6989 if (!holder.is_null()) {
6876 Handle<JSObject> prototype(JSObject::cast(receiver_map->prototype())); 6990 Handle<JSObject> prototype(JSObject::cast(receiver_map->prototype()));
6877 BuildCheckPrototypeMaps(prototype, holder); 6991 BuildCheckPrototypeMaps(prototype, holder);
6878 } 6992 }
6879 } 6993 }
6880 6994
6881 6995
6882 void HOptimizedGraphBuilder::AddCheckConstantFunction(
6883 Handle<JSObject> holder,
6884 HValue* receiver,
6885 Handle<Map> receiver_map) {
6886 // Constant functions have the nice property that the map will change if they
6887 // are overwritten. Therefore it is enough to check the map of the holder and
6888 // its prototypes.
6889 AddCheckMap(receiver, receiver_map);
6890 AddCheckPrototypeMaps(holder, receiver_map);
6891 }
6892
6893
6894 HInstruction* HOptimizedGraphBuilder::NewPlainFunctionCall( 6996 HInstruction* HOptimizedGraphBuilder::NewPlainFunctionCall(
6895 HValue* fun, int argument_count, bool pass_argument_count) { 6997 HValue* fun, int argument_count, bool pass_argument_count) {
6896 return New<HCallJSFunction>( 6998 return New<HCallJSFunction>(
6897 fun, argument_count, pass_argument_count); 6999 fun, argument_count, pass_argument_count);
6898 } 7000 }
6899 7001
6900 7002
6901 HInstruction* HOptimizedGraphBuilder::NewArgumentAdaptorCall( 7003 HInstruction* HOptimizedGraphBuilder::NewArgumentAdaptorCall(
6902 HValue* fun, HValue* context, 7004 HValue* fun, HValue* context,
6903 int argument_count, HValue* expected_param_count) { 7005 int argument_count, HValue* expected_param_count) {
(...skipping 20 matching lines...) Expand all
6924 // For constant functions, we try to avoid calling the 7026 // For constant functions, we try to avoid calling the
6925 // argument adaptor and instead call the function directly 7027 // argument adaptor and instead call the function directly
6926 int formal_parameter_count = jsfun->shared()->formal_parameter_count(); 7028 int formal_parameter_count = jsfun->shared()->formal_parameter_count();
6927 bool dont_adapt_arguments = 7029 bool dont_adapt_arguments =
6928 (formal_parameter_count == 7030 (formal_parameter_count ==
6929 SharedFunctionInfo::kDontAdaptArgumentsSentinel); 7031 SharedFunctionInfo::kDontAdaptArgumentsSentinel);
6930 int arity = argument_count - 1; 7032 int arity = argument_count - 1;
6931 bool can_invoke_directly = 7033 bool can_invoke_directly =
6932 dont_adapt_arguments || formal_parameter_count == arity; 7034 dont_adapt_arguments || formal_parameter_count == arity;
6933 if (can_invoke_directly) { 7035 if (can_invoke_directly) {
7036 if (jsfun.is_identical_to(current_info()->closure())) {
7037 graph()->MarkRecursive();
7038 }
6934 return NewPlainFunctionCall(target, argument_count, dont_adapt_arguments); 7039 return NewPlainFunctionCall(target, argument_count, dont_adapt_arguments);
6935 } else { 7040 } else {
6936 HValue* param_count_value = Add<HConstant>(formal_parameter_count); 7041 HValue* param_count_value = Add<HConstant>(formal_parameter_count);
6937 HValue* context = Add<HLoadNamedField>( 7042 HValue* context = Add<HLoadNamedField>(
6938 target, static_cast<HValue*>(NULL), 7043 target, static_cast<HValue*>(NULL),
6939 HObjectAccess::ForFunctionContextPointer()); 7044 HObjectAccess::ForFunctionContextPointer());
6940 return NewArgumentAdaptorCall(target, context, 7045 return NewArgumentAdaptorCall(target, context,
6941 argument_count, param_count_value); 7046 argument_count, param_count_value);
6942 } 7047 }
6943 UNREACHABLE(); 7048 UNREACHABLE();
6944 return NULL; 7049 return NULL;
6945 } 7050 }
6946 7051
6947 7052
6948 HInstruction* HOptimizedGraphBuilder::NewCallNamed(
6949 Handle<String> name, int argument_count) {
6950 CallInterfaceDescriptor* descriptor =
6951 isolate()->call_descriptor(Isolate::NamedCall);
6952 HValue* op_vals[] = { context(), Add<HConstant>(name) };
6953 int arity = argument_count - 1;
6954 Handle<Code> ic = isolate()->stub_cache()->ComputeCallInitialize(arity);
6955
6956 return New<HCallWithDescriptor>(
6957 Add<HConstant>(ic), argument_count, descriptor,
6958 Vector<HValue*>(op_vals, descriptor->environment_length()));
6959 }
6960
6961
6962 HInstruction* HOptimizedGraphBuilder::NewCallKeyed(
6963 HValue* key, int argument_count) {
6964 CallInterfaceDescriptor* descriptor =
6965 isolate()->call_descriptor(Isolate::KeyedCall);
6966 HValue* op_vals[] = { context(), key };
6967 int arity = argument_count - 1;
6968 Handle<Code> ic = isolate()->stub_cache()->ComputeKeyedCallInitialize(arity);
6969
6970 return New<HCallWithDescriptor>(
6971 Add<HConstant>(ic), argument_count, descriptor,
6972 Vector<HValue*>(op_vals, descriptor->environment_length()));
6973 }
6974
6975 class FunctionSorter { 7053 class FunctionSorter {
6976 public: 7054 public:
6977 FunctionSorter() : index_(0), ticks_(0), ast_length_(0), src_length_(0) { } 7055 FunctionSorter() : index_(0), ticks_(0), ast_length_(0), src_length_(0) { }
6978 FunctionSorter(int index, int ticks, int ast_length, int src_length) 7056 FunctionSorter(int index, int ticks, int ast_length, int src_length)
6979 : index_(index), 7057 : index_(index),
6980 ticks_(ticks), 7058 ticks_(ticks),
6981 ast_length_(ast_length), 7059 ast_length_(ast_length),
6982 src_length_(src_length) { } 7060 src_length_(src_length) { }
6983 7061
6984 int index() const { return index_; } 7062 int index() const { return index_; }
(...skipping 11 matching lines...) Expand all
6996 7074
6997 inline bool operator<(const FunctionSorter& lhs, const FunctionSorter& rhs) { 7075 inline bool operator<(const FunctionSorter& lhs, const FunctionSorter& rhs) {
6998 int diff = lhs.ticks() - rhs.ticks(); 7076 int diff = lhs.ticks() - rhs.ticks();
6999 if (diff != 0) return diff > 0; 7077 if (diff != 0) return diff > 0;
7000 diff = lhs.ast_length() - rhs.ast_length(); 7078 diff = lhs.ast_length() - rhs.ast_length();
7001 if (diff != 0) return diff < 0; 7079 if (diff != 0) return diff < 0;
7002 return lhs.src_length() < rhs.src_length(); 7080 return lhs.src_length() < rhs.src_length();
7003 } 7081 }
7004 7082
7005 7083
7006 bool HOptimizedGraphBuilder::TryCallPolymorphicAsMonomorphic(
7007 Call* expr,
7008 HValue* receiver,
7009 SmallMapList* types,
7010 Handle<String> name) {
7011 if (types->length() > kMaxCallPolymorphism) return false;
7012
7013 PropertyAccessInfo info(isolate(), types->at(0), name);
7014 if (!info.CanLoadAsMonomorphic(types)) return false;
7015 if (!expr->ComputeTarget(info.map(), name)) return false;
7016
7017 BuildCheckHeapObject(receiver);
7018 Add<HCheckMaps>(receiver, types);
7019 AddCheckPrototypeMaps(expr->holder(), info.map());
7020 if (FLAG_trace_inlining) {
7021 Handle<JSFunction> caller = current_info()->closure();
7022 SmartArrayPointer<char> caller_name =
7023 caller->shared()->DebugName()->ToCString();
7024 PrintF("Trying to inline the polymorphic call to %s from %s\n",
7025 name->ToCString().get(), caller_name.get());
7026 }
7027
7028 if (!TryInlineCall(expr)) {
7029 int argument_count = expr->arguments()->length() + 1; // Includes receiver.
7030 HInstruction* call = BuildCallConstantFunction(
7031 expr->target(), argument_count);
7032 PushArgumentsFromEnvironment(argument_count);
7033 AddInstruction(call);
7034 if (!ast_context()->IsEffect()) Push(call);
7035 Add<HSimulate>(expr->id(), REMOVABLE_SIMULATE);
7036 if (!ast_context()->IsEffect()) ast_context()->ReturnValue(Pop());
7037 }
7038
7039 return true;
7040 }
7041
7042
7043 void HOptimizedGraphBuilder::HandlePolymorphicCallNamed( 7084 void HOptimizedGraphBuilder::HandlePolymorphicCallNamed(
7044 Call* expr, 7085 Call* expr,
7045 HValue* receiver, 7086 HValue* receiver,
7046 SmallMapList* types, 7087 SmallMapList* types,
7047 Handle<String> name) { 7088 Handle<String> name) {
7048 if (TryCallPolymorphicAsMonomorphic(expr, receiver, types, name)) return;
7049
7050 int argument_count = expr->arguments()->length() + 1; // Includes receiver. 7089 int argument_count = expr->arguments()->length() + 1; // Includes receiver.
7051 HBasicBlock* join = NULL;
7052 FunctionSorter order[kMaxCallPolymorphism]; 7090 FunctionSorter order[kMaxCallPolymorphism];
7053 int ordered_functions = 0;
7054
7055 Handle<Map> initial_string_map(
7056 isolate()->native_context()->string_function()->initial_map());
7057 Handle<Map> string_marker_map(
7058 JSObject::cast(initial_string_map->prototype())->map());
7059 Handle<Map> initial_number_map(
7060 isolate()->native_context()->number_function()->initial_map());
7061 Handle<Map> number_marker_map(
7062 JSObject::cast(initial_number_map->prototype())->map());
7063 Handle<Map> heap_number_map = isolate()->factory()->heap_number_map();
7064 7091
7065 bool handle_smi = false; 7092 bool handle_smi = false;
7093 bool handled_string = false;
7094 int ordered_functions = 0;
7066 7095
7067 for (int i = 0; 7096 for (int i = 0;
7068 i < types->length() && ordered_functions < kMaxCallPolymorphism; 7097 i < types->length() && ordered_functions < kMaxCallPolymorphism;
7069 ++i) { 7098 ++i) {
7070 Handle<Map> map = types->at(i); 7099 PropertyAccessInfo info(this, IC::MapToType(types->at(i)), name);
7071 if (expr->ComputeTarget(map, name)) { 7100 if (info.CanLoadMonomorphic() &&
7072 if (map.is_identical_to(number_marker_map)) handle_smi = true; 7101 info.lookup()->IsConstant() &&
7102 info.constant()->IsJSFunction()) {
7103 if (info.type()->Is(HeapType::String())) {
7104 if (handled_string) continue;
7105 handled_string = true;
7106 }
7107 Handle<JSFunction> target = Handle<JSFunction>::cast(info.constant());
7108 if (info.type()->Is(HeapType::Number())) {
7109 handle_smi = true;
7110 }
7111 expr->set_target(target);
7073 order[ordered_functions++] = 7112 order[ordered_functions++] =
7074 FunctionSorter(i, 7113 FunctionSorter(i,
7075 expr->target()->shared()->profiler_ticks(), 7114 expr->target()->shared()->profiler_ticks(),
7076 InliningAstSize(expr->target()), 7115 InliningAstSize(expr->target()),
7077 expr->target()->shared()->SourceSize()); 7116 expr->target()->shared()->SourceSize());
7078 } 7117 }
7079 } 7118 }
7080 7119
7081 std::sort(order, order + ordered_functions); 7120 std::sort(order, order + ordered_functions);
7082 7121
7083 HBasicBlock* number_block = NULL; 7122 HBasicBlock* number_block = NULL;
7123 HBasicBlock* join = NULL;
7124 handled_string = false;
7125 int count = 0;
7084 7126
7085 for (int fn = 0; fn < ordered_functions; ++fn) { 7127 for (int fn = 0; fn < ordered_functions; ++fn) {
7086 int i = order[fn].index(); 7128 int i = order[fn].index();
7087 Handle<Map> map = types->at(i); 7129 PropertyAccessInfo info(this, IC::MapToType(types->at(i)), name);
7088 if (fn == 0) { 7130 if (info.type()->Is(HeapType::String())) {
7131 if (handled_string) continue;
7132 handled_string = true;
7133 }
7134 // Reloads the target.
7135 info.CanLoadMonomorphic();
7136 Handle<JSFunction> target = Handle<JSFunction>::cast(info.constant());
7137
7138 expr->set_target(target);
7139 if (count == 0) {
7089 // Only needed once. 7140 // Only needed once.
7090 join = graph()->CreateBasicBlock(); 7141 join = graph()->CreateBasicBlock();
7091 if (handle_smi) { 7142 if (handle_smi) {
7092 HBasicBlock* empty_smi_block = graph()->CreateBasicBlock(); 7143 HBasicBlock* empty_smi_block = graph()->CreateBasicBlock();
7093 HBasicBlock* not_smi_block = graph()->CreateBasicBlock(); 7144 HBasicBlock* not_smi_block = graph()->CreateBasicBlock();
7094 number_block = graph()->CreateBasicBlock(); 7145 number_block = graph()->CreateBasicBlock();
7095 FinishCurrentBlock(New<HIsSmiAndBranch>( 7146 FinishCurrentBlock(New<HIsSmiAndBranch>(
7096 receiver, empty_smi_block, not_smi_block)); 7147 receiver, empty_smi_block, not_smi_block));
7097 Goto(empty_smi_block, number_block); 7148 Goto(empty_smi_block, number_block);
7098 set_current_block(not_smi_block); 7149 set_current_block(not_smi_block);
7099 } else { 7150 } else {
7100 BuildCheckHeapObject(receiver); 7151 BuildCheckHeapObject(receiver);
7101 } 7152 }
7102 } 7153 }
7154 ++count;
7103 HBasicBlock* if_true = graph()->CreateBasicBlock(); 7155 HBasicBlock* if_true = graph()->CreateBasicBlock();
7104 HBasicBlock* if_false = graph()->CreateBasicBlock(); 7156 HBasicBlock* if_false = graph()->CreateBasicBlock();
7105 HUnaryControlInstruction* compare; 7157 HUnaryControlInstruction* compare;
7106 7158
7107 if (handle_smi && map.is_identical_to(number_marker_map)) { 7159 Handle<Map> map = info.map();
7160 if (info.type()->Is(HeapType::Number())) {
7161 Handle<Map> heap_number_map = isolate()->factory()->heap_number_map();
7108 compare = New<HCompareMap>(receiver, heap_number_map, if_true, if_false); 7162 compare = New<HCompareMap>(receiver, heap_number_map, if_true, if_false);
7109 map = initial_number_map; 7163 } else if (info.type()->Is(HeapType::String())) {
7110 expr->set_number_check(
7111 Handle<JSObject>(JSObject::cast(map->prototype())));
7112 } else if (map.is_identical_to(string_marker_map)) {
7113 compare = New<HIsStringAndBranch>(receiver, if_true, if_false); 7164 compare = New<HIsStringAndBranch>(receiver, if_true, if_false);
7114 map = initial_string_map;
7115 expr->set_string_check(
7116 Handle<JSObject>(JSObject::cast(map->prototype())));
7117 } else { 7165 } else {
7118 compare = New<HCompareMap>(receiver, map, if_true, if_false); 7166 compare = New<HCompareMap>(receiver, map, if_true, if_false);
7119 expr->set_map_check();
7120 } 7167 }
7121
7122 FinishCurrentBlock(compare); 7168 FinishCurrentBlock(compare);
7123 7169
7124 if (expr->check_type() == NUMBER_CHECK) { 7170 if (info.type()->Is(HeapType::Number())) {
7125 Goto(if_true, number_block); 7171 Goto(if_true, number_block);
7126 if_true = number_block; 7172 if_true = number_block;
7127 number_block->SetJoinId(expr->id()); 7173 number_block->SetJoinId(expr->id());
7128 } 7174 }
7175
7129 set_current_block(if_true); 7176 set_current_block(if_true);
7130 7177
7131 expr->ComputeTarget(map, name); 7178 AddCheckPrototypeMaps(info.holder(), map);
7132 AddCheckPrototypeMaps(expr->holder(), map); 7179
7133 if (FLAG_trace_inlining && FLAG_polymorphic_inlining) { 7180 HValue* function = Add<HConstant>(expr->target());
7181 environment()->SetExpressionStackAt(0, function);
7182 Push(receiver);
7183 CHECK_ALIVE(VisitExpressions(expr->arguments()));
7184 bool needs_wrapping = NeedsWrappingFor(info.type(), target);
7185 bool try_inline = FLAG_polymorphic_inlining && !needs_wrapping;
7186 if (FLAG_trace_inlining && try_inline) {
7134 Handle<JSFunction> caller = current_info()->closure(); 7187 Handle<JSFunction> caller = current_info()->closure();
7135 SmartArrayPointer<char> caller_name = 7188 SmartArrayPointer<char> caller_name =
7136 caller->shared()->DebugName()->ToCString(); 7189 caller->shared()->DebugName()->ToCString();
7137 PrintF("Trying to inline the polymorphic call to %s from %s\n", 7190 PrintF("Trying to inline the polymorphic call to %s from %s\n",
7138 name->ToCString().get(), 7191 name->ToCString().get(),
7139 caller_name.get()); 7192 caller_name.get());
7140 } 7193 }
7141 if (FLAG_polymorphic_inlining && TryInlineCall(expr)) { 7194 if (try_inline && TryInlineCall(expr)) {
7142 // Trying to inline will signal that we should bailout from the 7195 // Trying to inline will signal that we should bailout from the
7143 // entire compilation by setting stack overflow on the visitor. 7196 // entire compilation by setting stack overflow on the visitor.
7144 if (HasStackOverflow()) return; 7197 if (HasStackOverflow()) return;
7145 } else { 7198 } else {
7146 HInstruction* call = BuildCallConstantFunction( 7199 // Since HWrapReceiver currently cannot actually wrap numbers and strings,
7147 expr->target(), argument_count); 7200 // use the regular CallFunctionStub for method calls to wrap the receiver.
7201 // TODO(verwaest): Support creation of value wrappers directly in
7202 // HWrapReceiver.
7203 HInstruction* call = needs_wrapping
7204 ? NewUncasted<HCallFunction>(
7205 function, argument_count, WRAP_AND_CALL)
7206 : BuildCallConstantFunction(target, argument_count);
7148 PushArgumentsFromEnvironment(argument_count); 7207 PushArgumentsFromEnvironment(argument_count);
7149 AddInstruction(call); 7208 AddInstruction(call);
7209 Drop(1); // Drop the function.
7150 if (!ast_context()->IsEffect()) Push(call); 7210 if (!ast_context()->IsEffect()) Push(call);
7151 } 7211 }
7152 7212
7153 if (current_block() != NULL) Goto(join); 7213 if (current_block() != NULL) Goto(join);
7154 set_current_block(if_false); 7214 set_current_block(if_false);
7155 } 7215 }
7156 7216
7157 // Finish up. Unconditionally deoptimize if we've handled all the maps we 7217 // Finish up. Unconditionally deoptimize if we've handled all the maps we
7158 // know about and do not want to handle ones we've never seen. Otherwise 7218 // know about and do not want to handle ones we've never seen. Otherwise
7159 // use a generic IC. 7219 // use a generic IC.
7160 if (ordered_functions == types->length() && FLAG_deoptimize_uncommon_cases) { 7220 if (ordered_functions == types->length() && FLAG_deoptimize_uncommon_cases) {
7161 // Because the deopt may be the only path in the polymorphic call, make sure 7221 // Because the deopt may be the only path in the polymorphic call, make sure
7162 // that the environment stack matches the depth on deopt that it otherwise 7222 // that the environment stack matches the depth on deopt that it otherwise
7163 // would have had after a successful call. 7223 // would have had after a successful call.
7164 Drop(argument_count); 7224 Drop(1); // Drop receiver.
7165 if (!ast_context()->IsEffect()) Push(graph()->GetConstant0()); 7225 if (!ast_context()->IsEffect()) Push(graph()->GetConstant0());
7166 FinishExitWithHardDeoptimization("Unknown map in polymorphic call", join); 7226 FinishExitWithHardDeoptimization("Unknown map in polymorphic call", join);
7167 } else { 7227 } else {
7168 HInstruction* call = NewCallNamed(name, argument_count); 7228 Property* prop = expr->expression()->AsProperty();
7229 HInstruction* function = BuildLoadNamedGeneric(receiver, name, prop);
7230 AddInstruction(function);
7231 Push(function);
7232 AddSimulate(prop->LoadId(), REMOVABLE_SIMULATE);
7233
7234 environment()->SetExpressionStackAt(1, function);
7235 environment()->SetExpressionStackAt(0, receiver);
7236 CHECK_ALIVE(VisitExpressions(expr->arguments()));
7237
7238 CallFunctionFlags flags = receiver->type().IsJSObject()
7239 ? NO_CALL_FUNCTION_FLAGS : CALL_AS_METHOD;
7240 HInstruction* call = New<HCallFunction>(
7241 function, argument_count, flags);
7242
7169 PushArgumentsFromEnvironment(argument_count); 7243 PushArgumentsFromEnvironment(argument_count);
7170 7244
7245 Drop(1); // Function.
7246
7171 if (join != NULL) { 7247 if (join != NULL) {
7172 AddInstruction(call); 7248 AddInstruction(call);
7173 if (!ast_context()->IsEffect()) Push(call); 7249 if (!ast_context()->IsEffect()) Push(call);
7174 Goto(join); 7250 Goto(join);
7175 } else { 7251 } else {
7176 return ast_context()->ReturnInstruction(call, expr->id()); 7252 return ast_context()->ReturnInstruction(call, expr->id());
7177 } 7253 }
7178 } 7254 }
7179 7255
7180 // We assume that control flow is always live after an expression. So 7256 // We assume that control flow is always live after an expression. So
(...skipping 360 matching lines...) Expand 10 before | Expand all | Expand 10 after
7541 function_return()->SetJoinId(ast_id); 7617 function_return()->SetJoinId(ast_id);
7542 set_current_block(function_return()); 7618 set_current_block(function_return());
7543 } else { 7619 } else {
7544 set_current_block(NULL); 7620 set_current_block(NULL);
7545 } 7621 }
7546 delete target_state; 7622 delete target_state;
7547 return true; 7623 return true;
7548 } 7624 }
7549 7625
7550 7626
7551 bool HOptimizedGraphBuilder::TryInlineCall(Call* expr, bool drop_extra) { 7627 bool HOptimizedGraphBuilder::TryInlineCall(Call* expr) {
7552 return TryInline(expr->target(), 7628 return TryInline(expr->target(),
7553 expr->arguments()->length(), 7629 expr->arguments()->length(),
7554 NULL, 7630 NULL,
7555 expr->id(), 7631 expr->id(),
7556 expr->ReturnId(), 7632 expr->ReturnId(),
7557 drop_extra ? DROP_EXTRA_ON_RETURN : NORMAL_RETURN); 7633 NORMAL_RETURN);
7558 } 7634 }
7559 7635
7560 7636
7561 bool HOptimizedGraphBuilder::TryInlineConstruct(CallNew* expr, 7637 bool HOptimizedGraphBuilder::TryInlineConstruct(CallNew* expr,
7562 HValue* implicit_return_value) { 7638 HValue* implicit_return_value) {
7563 return TryInline(expr->target(), 7639 return TryInline(expr->target(),
7564 expr->arguments()->length(), 7640 expr->arguments()->length(),
7565 implicit_return_value, 7641 implicit_return_value,
7566 expr->id(), 7642 expr->id(),
7567 expr->ReturnId(), 7643 expr->ReturnId(),
(...skipping 30 matching lines...) Expand all
7598 int arguments_count) { 7674 int arguments_count) {
7599 return TryInline(function, 7675 return TryInline(function,
7600 arguments_count, 7676 arguments_count,
7601 NULL, 7677 NULL,
7602 expr->id(), 7678 expr->id(),
7603 expr->ReturnId(), 7679 expr->ReturnId(),
7604 NORMAL_RETURN); 7680 NORMAL_RETURN);
7605 } 7681 }
7606 7682
7607 7683
7608 bool HOptimizedGraphBuilder::TryInlineBuiltinFunctionCall(Call* expr, 7684 bool HOptimizedGraphBuilder::TryInlineBuiltinFunctionCall(Call* expr) {
7609 bool drop_extra) {
7610 if (!expr->target()->shared()->HasBuiltinFunctionId()) return false; 7685 if (!expr->target()->shared()->HasBuiltinFunctionId()) return false;
7611 BuiltinFunctionId id = expr->target()->shared()->builtin_function_id(); 7686 BuiltinFunctionId id = expr->target()->shared()->builtin_function_id();
7612 switch (id) { 7687 switch (id) {
7613 case kMathExp: 7688 case kMathExp:
7614 if (!FLAG_fast_math) break; 7689 if (!FLAG_fast_math) break;
7615 // Fall through if FLAG_fast_math. 7690 // Fall through if FLAG_fast_math.
7616 case kMathRound: 7691 case kMathRound:
7617 case kMathFloor: 7692 case kMathFloor:
7618 case kMathAbs: 7693 case kMathAbs:
7619 case kMathSqrt: 7694 case kMathSqrt:
7620 case kMathLog: 7695 case kMathLog:
7621 if (expr->arguments()->length() == 1) { 7696 if (expr->arguments()->length() == 1) {
7622 HValue* argument = Pop(); 7697 HValue* argument = Pop();
7623 Drop(1); // Receiver. 7698 Drop(2); // Receiver and function.
7624 HInstruction* op = NewUncasted<HUnaryMathOperation>(argument, id); 7699 HInstruction* op = NewUncasted<HUnaryMathOperation>(argument, id);
7625 if (drop_extra) Drop(1); // Optionally drop the function.
7626 ast_context()->ReturnInstruction(op, expr->id()); 7700 ast_context()->ReturnInstruction(op, expr->id());
7627 return true; 7701 return true;
7628 } 7702 }
7629 break; 7703 break;
7630 case kMathImul: 7704 case kMathImul:
7631 if (expr->arguments()->length() == 2) { 7705 if (expr->arguments()->length() == 2) {
7632 HValue* right = Pop(); 7706 HValue* right = Pop();
7633 HValue* left = Pop(); 7707 HValue* left = Pop();
7634 Drop(1); // Receiver. 7708 Drop(2); // Receiver and function.
7635 HInstruction* op = HMul::NewImul(zone(), context(), left, right); 7709 HInstruction* op = HMul::NewImul(zone(), context(), left, right);
7636 if (drop_extra) Drop(1); // Optionally drop the function.
7637 ast_context()->ReturnInstruction(op, expr->id()); 7710 ast_context()->ReturnInstruction(op, expr->id());
7638 return true; 7711 return true;
7639 } 7712 }
7640 break; 7713 break;
7641 default: 7714 default:
7642 // Not supported for inlining yet. 7715 // Not supported for inlining yet.
7643 break; 7716 break;
7644 } 7717 }
7645 return false; 7718 return false;
7646 } 7719 }
7647 7720
7648 7721
7649 bool HOptimizedGraphBuilder::TryInlineBuiltinMethodCall( 7722 bool HOptimizedGraphBuilder::TryInlineBuiltinMethodCall(
7650 Call* expr, 7723 Call* expr,
7651 HValue* receiver, 7724 HValue* receiver,
7652 Handle<Map> receiver_map, 7725 Handle<Map> receiver_map) {
7653 CheckType check_type) {
7654 ASSERT(check_type != RECEIVER_MAP_CHECK || !receiver_map.is_null());
7655 // Try to inline calls like Math.* as operations in the calling function. 7726 // Try to inline calls like Math.* as operations in the calling function.
7656 if (!expr->target()->shared()->HasBuiltinFunctionId()) return false; 7727 if (!expr->target()->shared()->HasBuiltinFunctionId()) return false;
7657 BuiltinFunctionId id = expr->target()->shared()->builtin_function_id(); 7728 BuiltinFunctionId id = expr->target()->shared()->builtin_function_id();
7658 int argument_count = expr->arguments()->length() + 1; // Plus receiver. 7729 int argument_count = expr->arguments()->length() + 1; // Plus receiver.
7659 switch (id) { 7730 switch (id) {
7660 case kStringCharCodeAt: 7731 case kStringCharCodeAt:
7661 case kStringCharAt: 7732 case kStringCharAt:
7662 if (argument_count == 2 && check_type == STRING_CHECK) { 7733 if (argument_count == 2) {
7663 HValue* index = Pop(); 7734 HValue* index = Pop();
7664 HValue* string = Pop(); 7735 HValue* string = Pop();
7665 ASSERT(!expr->holder().is_null()); 7736 Drop(1); // Function.
7666 BuildCheckPrototypeMaps(Call::GetPrototypeForPrimitiveCheck(
7667 STRING_CHECK, expr->holder()->GetIsolate()),
7668 expr->holder());
7669 HInstruction* char_code = 7737 HInstruction* char_code =
7670 BuildStringCharCodeAt(string, index); 7738 BuildStringCharCodeAt(string, index);
7671 if (id == kStringCharCodeAt) { 7739 if (id == kStringCharCodeAt) {
7672 ast_context()->ReturnInstruction(char_code, expr->id()); 7740 ast_context()->ReturnInstruction(char_code, expr->id());
7673 return true; 7741 return true;
7674 } 7742 }
7675 AddInstruction(char_code); 7743 AddInstruction(char_code);
7676 HInstruction* result = NewUncasted<HStringCharFromCode>(char_code); 7744 HInstruction* result = NewUncasted<HStringCharFromCode>(char_code);
7677 ast_context()->ReturnInstruction(result, expr->id()); 7745 ast_context()->ReturnInstruction(result, expr->id());
7678 return true; 7746 return true;
7679 } 7747 }
7680 break; 7748 break;
7681 case kStringFromCharCode: 7749 case kStringFromCharCode:
7682 if (argument_count == 2 && check_type == RECEIVER_MAP_CHECK) { 7750 if (argument_count == 2) {
7683 AddCheckConstantFunction(expr->holder(), receiver, receiver_map);
7684 HValue* argument = Pop(); 7751 HValue* argument = Pop();
7685 Drop(1); // Receiver. 7752 Drop(2); // Receiver and function.
7686 HInstruction* result = NewUncasted<HStringCharFromCode>(argument); 7753 HInstruction* result = NewUncasted<HStringCharFromCode>(argument);
7687 ast_context()->ReturnInstruction(result, expr->id()); 7754 ast_context()->ReturnInstruction(result, expr->id());
7688 return true; 7755 return true;
7689 } 7756 }
7690 break; 7757 break;
7691 case kMathExp: 7758 case kMathExp:
7692 if (!FLAG_fast_math) break; 7759 if (!FLAG_fast_math) break;
7693 // Fall through if FLAG_fast_math. 7760 // Fall through if FLAG_fast_math.
7694 case kMathRound: 7761 case kMathRound:
7695 case kMathFloor: 7762 case kMathFloor:
7696 case kMathAbs: 7763 case kMathAbs:
7697 case kMathSqrt: 7764 case kMathSqrt:
7698 case kMathLog: 7765 case kMathLog:
7699 if (argument_count == 2 && check_type == RECEIVER_MAP_CHECK) { 7766 if (argument_count == 2) {
7700 AddCheckConstantFunction(expr->holder(), receiver, receiver_map);
7701 HValue* argument = Pop(); 7767 HValue* argument = Pop();
7702 Drop(1); // Receiver. 7768 Drop(2); // Receiver and function.
7703 HInstruction* op = NewUncasted<HUnaryMathOperation>(argument, id); 7769 HInstruction* op = NewUncasted<HUnaryMathOperation>(argument, id);
7704 ast_context()->ReturnInstruction(op, expr->id()); 7770 ast_context()->ReturnInstruction(op, expr->id());
7705 return true; 7771 return true;
7706 } 7772 }
7707 break; 7773 break;
7708 case kMathPow: 7774 case kMathPow:
7709 if (argument_count == 3 && check_type == RECEIVER_MAP_CHECK) { 7775 if (argument_count == 3) {
7710 AddCheckConstantFunction(expr->holder(), receiver, receiver_map);
7711 HValue* right = Pop(); 7776 HValue* right = Pop();
7712 HValue* left = Pop(); 7777 HValue* left = Pop();
7713 Pop(); // Pop receiver. 7778 Drop(2); // Receiver and function.
7714 HInstruction* result = NULL; 7779 HInstruction* result = NULL;
7715 // Use sqrt() if exponent is 0.5 or -0.5. 7780 // Use sqrt() if exponent is 0.5 or -0.5.
7716 if (right->IsConstant() && HConstant::cast(right)->HasDoubleValue()) { 7781 if (right->IsConstant() && HConstant::cast(right)->HasDoubleValue()) {
7717 double exponent = HConstant::cast(right)->DoubleValue(); 7782 double exponent = HConstant::cast(right)->DoubleValue();
7718 if (exponent == 0.5) { 7783 if (exponent == 0.5) {
7719 result = NewUncasted<HUnaryMathOperation>(left, kMathPowHalf); 7784 result = NewUncasted<HUnaryMathOperation>(left, kMathPowHalf);
7720 } else if (exponent == -0.5) { 7785 } else if (exponent == -0.5) {
7721 HValue* one = graph()->GetConstant1(); 7786 HValue* one = graph()->GetConstant1();
7722 HInstruction* sqrt = AddUncasted<HUnaryMathOperation>( 7787 HInstruction* sqrt = AddUncasted<HUnaryMathOperation>(
7723 left, kMathPowHalf); 7788 left, kMathPowHalf);
7724 // MathPowHalf doesn't have side effects so there's no need for 7789 // MathPowHalf doesn't have side effects so there's no need for
7725 // an environment simulation here. 7790 // an environment simulation here.
7726 ASSERT(!sqrt->HasObservableSideEffects()); 7791 ASSERT(!sqrt->HasObservableSideEffects());
7727 result = NewUncasted<HDiv>(one, sqrt); 7792 result = NewUncasted<HDiv>(one, sqrt);
7728 } else if (exponent == 2.0) { 7793 } else if (exponent == 2.0) {
7729 result = NewUncasted<HMul>(left, left); 7794 result = NewUncasted<HMul>(left, left);
7730 } 7795 }
7731 } 7796 }
7732 7797
7733 if (result == NULL) { 7798 if (result == NULL) {
7734 result = NewUncasted<HPower>(left, right); 7799 result = NewUncasted<HPower>(left, right);
7735 } 7800 }
7736 ast_context()->ReturnInstruction(result, expr->id()); 7801 ast_context()->ReturnInstruction(result, expr->id());
7737 return true; 7802 return true;
7738 } 7803 }
7739 break; 7804 break;
7740 case kMathMax: 7805 case kMathMax:
7741 case kMathMin: 7806 case kMathMin:
7742 if (argument_count == 3 && check_type == RECEIVER_MAP_CHECK) { 7807 if (argument_count == 3) {
7743 AddCheckConstantFunction(expr->holder(), receiver, receiver_map);
7744 HValue* right = Pop(); 7808 HValue* right = Pop();
7745 HValue* left = Pop(); 7809 HValue* left = Pop();
7746 Drop(1); // Receiver. 7810 Drop(2); // Receiver and function.
7747 HMathMinMax::Operation op = (id == kMathMin) ? HMathMinMax::kMathMin 7811 HMathMinMax::Operation op = (id == kMathMin) ? HMathMinMax::kMathMin
7748 : HMathMinMax::kMathMax; 7812 : HMathMinMax::kMathMax;
7749 HInstruction* result = NewUncasted<HMathMinMax>(left, right, op); 7813 HInstruction* result = NewUncasted<HMathMinMax>(left, right, op);
7750 ast_context()->ReturnInstruction(result, expr->id()); 7814 ast_context()->ReturnInstruction(result, expr->id());
7751 return true; 7815 return true;
7752 } 7816 }
7753 break; 7817 break;
7754 case kMathImul: 7818 case kMathImul:
7755 if (argument_count == 3 && check_type == RECEIVER_MAP_CHECK) { 7819 if (argument_count == 3) {
7756 AddCheckConstantFunction(expr->holder(), receiver, receiver_map);
7757 HValue* right = Pop(); 7820 HValue* right = Pop();
7758 HValue* left = Pop(); 7821 HValue* left = Pop();
7759 Drop(1); // Receiver. 7822 Drop(2); // Receiver and function.
7760 HInstruction* result = HMul::NewImul(zone(), context(), left, right); 7823 HInstruction* result = HMul::NewImul(zone(), context(), left, right);
7761 ast_context()->ReturnInstruction(result, expr->id()); 7824 ast_context()->ReturnInstruction(result, expr->id());
7762 return true; 7825 return true;
7763 } 7826 }
7764 break; 7827 break;
7765 case kArrayPop: { 7828 case kArrayPop: {
7766 if (!expr->IsMonomorphic() || expr->check_type() != RECEIVER_MAP_CHECK) { 7829 if (receiver_map.is_null()) return false;
7767 return false;
7768 }
7769 if (receiver_map->instance_type() != JS_ARRAY_TYPE) return false; 7830 if (receiver_map->instance_type() != JS_ARRAY_TYPE) return false;
7770 ElementsKind elements_kind = receiver_map->elements_kind(); 7831 ElementsKind elements_kind = receiver_map->elements_kind();
7771 if (!IsFastElementsKind(elements_kind)) return false; 7832 if (!IsFastElementsKind(elements_kind)) return false;
7772 AddCheckConstantFunction(expr->holder(), receiver, receiver_map);
7773 7833
7774 Drop(expr->arguments()->length()); 7834 Drop(expr->arguments()->length());
7775 HValue* result; 7835 HValue* result;
7776 HValue* reduced_length; 7836 HValue* reduced_length;
7777 HValue* receiver = Pop(); 7837 HValue* receiver = Pop();
7778 7838
7779 HValue* checked_object = AddCheckMap(receiver, receiver_map); 7839 HValue* checked_object = AddCheckMap(receiver, receiver_map);
7780 HValue* length = Add<HLoadNamedField>( 7840 HValue* length = Add<HLoadNamedField>(
7781 checked_object, static_cast<HValue*>(NULL), 7841 checked_object, static_cast<HValue*>(NULL),
7782 HObjectAccess::ForArrayLength(elements_kind)); 7842 HObjectAccess::ForArrayLength(elements_kind));
7783 7843
7844 Drop(1); // Function.
7845
7784 { NoObservableSideEffectsScope scope(this); 7846 { NoObservableSideEffectsScope scope(this);
7785 IfBuilder length_checker(this); 7847 IfBuilder length_checker(this);
7786 7848
7787 HValue* bounds_check = length_checker.If<HCompareNumericAndBranch>( 7849 HValue* bounds_check = length_checker.If<HCompareNumericAndBranch>(
7788 length, graph()->GetConstant0(), Token::EQ); 7850 length, graph()->GetConstant0(), Token::EQ);
7789 length_checker.Then(); 7851 length_checker.Then();
7790 7852
7791 if (!ast_context()->IsEffect()) Push(graph()->GetConstantUndefined()); 7853 if (!ast_context()->IsEffect()) Push(graph()->GetConstantUndefined());
7792 7854
7793 length_checker.Else(); 7855 length_checker.Else();
(...skipping 25 matching lines...) Expand all
7819 length_checker.End(); 7881 length_checker.End();
7820 } 7882 }
7821 result = ast_context()->IsEffect() ? graph()->GetConstant0() : Top(); 7883 result = ast_context()->IsEffect() ? graph()->GetConstant0() : Top();
7822 Add<HSimulate>(expr->id(), REMOVABLE_SIMULATE); 7884 Add<HSimulate>(expr->id(), REMOVABLE_SIMULATE);
7823 if (!ast_context()->IsEffect()) Drop(1); 7885 if (!ast_context()->IsEffect()) Drop(1);
7824 7886
7825 ast_context()->ReturnValue(result); 7887 ast_context()->ReturnValue(result);
7826 return true; 7888 return true;
7827 } 7889 }
7828 case kArrayPush: { 7890 case kArrayPush: {
7829 if (!expr->IsMonomorphic() || expr->check_type() != RECEIVER_MAP_CHECK) { 7891 if (receiver_map.is_null()) return false;
7830 return false;
7831 }
7832 if (receiver_map->instance_type() != JS_ARRAY_TYPE) return false; 7892 if (receiver_map->instance_type() != JS_ARRAY_TYPE) return false;
7833 ElementsKind elements_kind = receiver_map->elements_kind(); 7893 ElementsKind elements_kind = receiver_map->elements_kind();
7834 if (!IsFastElementsKind(elements_kind)) return false; 7894 if (!IsFastElementsKind(elements_kind)) return false;
7835 AddCheckConstantFunction(expr->holder(), receiver, receiver_map);
7836 7895
7837 HValue* op_vals[] = { 7896 HValue* op_vals[] = {
7838 context(), 7897 context(),
7839 // Receiver. 7898 // Receiver.
7840 environment()->ExpressionStackAt(expr->arguments()->length()) 7899 environment()->ExpressionStackAt(expr->arguments()->length())
7841 }; 7900 };
7842 7901
7843 const int argc = expr->arguments()->length(); 7902 const int argc = expr->arguments()->length();
7844 // Includes receiver. 7903 // Includes receiver.
7845 PushArgumentsFromEnvironment(argc + 1); 7904 PushArgumentsFromEnvironment(argc + 1);
7846 7905
7847 CallInterfaceDescriptor* descriptor = 7906 CallInterfaceDescriptor* descriptor =
7848 isolate()->call_descriptor(Isolate::CallHandler); 7907 isolate()->call_descriptor(Isolate::CallHandler);
7849 7908
7850 ArrayPushStub stub(receiver_map->elements_kind(), argc); 7909 ArrayPushStub stub(receiver_map->elements_kind(), argc);
7851 Handle<Code> code = stub.GetCode(isolate()); 7910 Handle<Code> code = stub.GetCode(isolate());
7852 HConstant* code_value = Add<HConstant>(code); 7911 HConstant* code_value = Add<HConstant>(code);
7853 7912
7854 ASSERT((sizeof(op_vals) / kPointerSize) == 7913 ASSERT((sizeof(op_vals) / kPointerSize) ==
7855 descriptor->environment_length()); 7914 descriptor->environment_length());
7856 7915
7857 HInstruction* call = New<HCallWithDescriptor>( 7916 HInstruction* call = New<HCallWithDescriptor>(
7858 code_value, argc + 1, descriptor, 7917 code_value, argc + 1, descriptor,
7859 Vector<HValue*>(op_vals, descriptor->environment_length())); 7918 Vector<HValue*>(op_vals, descriptor->environment_length()));
7919 Drop(1); // Drop function.
7860 ast_context()->ReturnInstruction(call, expr->id()); 7920 ast_context()->ReturnInstruction(call, expr->id());
7861 return true; 7921 return true;
7862 } 7922 }
7863 default: 7923 default:
7864 // Not yet supported for inlining. 7924 // Not yet supported for inlining.
7865 break; 7925 break;
7866 } 7926 }
7867 return false; 7927 return false;
7868 } 7928 }
7869 7929
7870 7930
7931 bool HOptimizedGraphBuilder::TryInlineApiFunctionCall(Call* expr,
7932 HValue* receiver) {
7933 return TryInlineApiCall(
7934 expr, receiver, Handle<Map>::null(), true);
7935 }
7936
7937
7938 bool HOptimizedGraphBuilder::TryInlineApiMethodCall(Call* expr,
7939 HValue* receiver,
7940 Handle<Map> receiver_map) {
7941 return TryInlineApiCall(expr, receiver, receiver_map, false);
7942 }
7943
7944 bool HOptimizedGraphBuilder::TryInlineApiCall(Call* expr,
7945 HValue* receiver,
7946 Handle<Map> receiver_map,
7947 bool is_function_call) {
7948 if (!expr->IsMonomorphic()) return false;
7949 CallOptimization optimization(expr->target());
7950 if (!optimization.is_simple_api_call()) return false;
7951 Handle<Map> holder_map;
7952 if (is_function_call) {
7953 // Cannot embed a direct reference to the global proxy map
7954 // as it maybe dropped on deserialization.
7955 CHECK(!Serializer::enabled());
7956 receiver_map = Handle<Map>(
7957 expr->target()->context()->global_object()->global_receiver()->map());
7958 }
7959 CallOptimization::HolderLookup holder_lookup =
7960 CallOptimization::kHolderNotFound;
7961 Handle<JSObject> api_holder = optimization.LookupHolderOfExpectedType(
7962 receiver_map, &holder_lookup);
7963 if (holder_lookup == CallOptimization::kHolderNotFound) return false;
7964
7965 if (FLAG_trace_inlining) {
7966 PrintF("Inlining api function ");
7967 expr->target()->ShortPrint();
7968 PrintF("\n");
7969 }
7970
7971 const int argc = expr->arguments()->length();
7972 // Includes receiver.
7973 PushArgumentsFromEnvironment(argc + 1);
7974
7975 // Need to ensure the chain between receiver and api_holder is intact
7976 AddCheckMap(receiver, receiver_map);
7977 if (holder_lookup == CallOptimization::kHolderFound) {
7978 AddCheckPrototypeMaps(api_holder, receiver_map);
7979 } else {
7980 ASSERT_EQ(holder_lookup, CallOptimization::kHolderIsReceiver);
7981 }
7982
7983 HValue* holder = NULL;
7984 switch (holder_lookup) {
7985 case CallOptimization::kHolderFound:
7986 holder = Add<HConstant>(api_holder);
7987 break;
7988 case CallOptimization::kHolderIsReceiver:
7989 holder = receiver;
7990 break;
7991 case CallOptimization::kHolderNotFound:
7992 UNREACHABLE();
7993 break;
7994 }
7995 Handle<CallHandlerInfo> api_call_info = optimization.api_call_info();
7996 Handle<Object> call_data_obj(api_call_info->data(), isolate());
7997 bool call_data_is_undefined = call_data_obj->IsUndefined();
7998 HValue* call_data = Add<HConstant>(call_data_obj);
7999 ApiFunction fun(v8::ToCData<Address>(api_call_info->callback()));
8000 ExternalReference ref = ExternalReference(&fun,
8001 ExternalReference::DIRECT_API_CALL,
8002 isolate());
8003 HValue* api_function_address = Add<HConstant>(ExternalReference(ref));
8004
8005 HValue* op_vals[] = {
8006 // callee
8007 Add<HConstant>(expr->target()),
8008 call_data,
8009 holder,
8010 api_function_address,
8011 context()
8012 };
8013
8014 CallInterfaceDescriptor* descriptor =
8015 isolate()->call_descriptor(Isolate::ApiFunctionCall);
8016
8017 CallApiFunctionStub stub(true, call_data_is_undefined, argc);
8018 Handle<Code> code = stub.GetCode(isolate());
8019 HConstant* code_value = Add<HConstant>(code);
8020
8021 ASSERT((sizeof(op_vals) / kPointerSize) ==
8022 descriptor->environment_length());
8023
8024 HInstruction* call = New<HCallWithDescriptor>(
8025 code_value, argc + 1, descriptor,
8026 Vector<HValue*>(op_vals, descriptor->environment_length()));
8027
8028 Drop(1); // Drop function.
8029 ast_context()->ReturnInstruction(call, expr->id());
8030 return true;
8031 }
8032
8033
7871 bool HOptimizedGraphBuilder::TryCallApply(Call* expr) { 8034 bool HOptimizedGraphBuilder::TryCallApply(Call* expr) {
7872 Expression* callee = expr->expression(); 8035 ASSERT(expr->expression()->IsProperty());
7873 Property* prop = callee->AsProperty();
7874 ASSERT(prop != NULL);
7875 8036
7876 if (!expr->IsMonomorphic() || expr->check_type() != RECEIVER_MAP_CHECK) { 8037 if (!expr->IsMonomorphic()) {
7877 return false; 8038 return false;
7878 } 8039 }
7879 Handle<Map> function_map = expr->GetReceiverTypes()->first(); 8040 Handle<Map> function_map = expr->GetReceiverTypes()->first();
7880 if (function_map->instance_type() != JS_FUNCTION_TYPE || 8041 if (function_map->instance_type() != JS_FUNCTION_TYPE ||
7881 !expr->target()->shared()->HasBuiltinFunctionId() || 8042 !expr->target()->shared()->HasBuiltinFunctionId() ||
7882 expr->target()->shared()->builtin_function_id() != kFunctionApply) { 8043 expr->target()->shared()->builtin_function_id() != kFunctionApply) {
7883 return false; 8044 return false;
7884 } 8045 }
7885 8046
7886 if (current_info()->scope()->arguments() == NULL) return false; 8047 if (current_info()->scope()->arguments() == NULL) return false;
7887 8048
7888 ZoneList<Expression*>* args = expr->arguments(); 8049 ZoneList<Expression*>* args = expr->arguments();
7889 if (args->length() != 2) return false; 8050 if (args->length() != 2) return false;
7890 8051
7891 VariableProxy* arg_two = args->at(1)->AsVariableProxy(); 8052 VariableProxy* arg_two = args->at(1)->AsVariableProxy();
7892 if (arg_two == NULL || !arg_two->var()->IsStackAllocated()) return false; 8053 if (arg_two == NULL || !arg_two->var()->IsStackAllocated()) return false;
7893 HValue* arg_two_value = LookupAndMakeLive(arg_two->var()); 8054 HValue* arg_two_value = LookupAndMakeLive(arg_two->var());
7894 if (!arg_two_value->CheckFlag(HValue::kIsArguments)) return false; 8055 if (!arg_two_value->CheckFlag(HValue::kIsArguments)) return false;
7895 8056
7896 // Found pattern f.apply(receiver, arguments). 8057 // Found pattern f.apply(receiver, arguments).
7897 CHECK_ALIVE_OR_RETURN(VisitForValue(prop->obj()), true);
7898 HValue* function = Top();
7899
7900 AddCheckConstantFunction(expr->holder(), function, function_map);
7901
7902 CHECK_ALIVE_OR_RETURN(VisitForValue(args->at(0)), true); 8058 CHECK_ALIVE_OR_RETURN(VisitForValue(args->at(0)), true);
7903 HValue* receiver = Pop(); 8059 HValue* receiver = Pop(); // receiver
7904 8060 HValue* function = Pop(); // f
7905 Drop(1); // Pop the function. 8061 Drop(1); // apply
7906 8062
7907 if (function_state()->outer() == NULL) { 8063 if (function_state()->outer() == NULL) {
7908 HInstruction* elements = Add<HArgumentsElements>(false); 8064 HInstruction* elements = Add<HArgumentsElements>(false);
7909 HInstruction* length = Add<HArgumentsLength>(elements); 8065 HInstruction* length = Add<HArgumentsLength>(elements);
7910 HValue* wrapped_receiver = BuildWrapReceiver(receiver, function); 8066 HValue* wrapped_receiver = BuildWrapReceiver(receiver, function);
7911 HInstruction* result = New<HApplyArguments>(function, 8067 HInstruction* result = New<HApplyArguments>(function,
7912 wrapped_receiver, 8068 wrapped_receiver,
7913 length, 8069 length,
7914 elements); 8070 elements);
7915 ast_context()->ReturnInstruction(result, expr->id()); 8071 ast_context()->ReturnInstruction(result, expr->id());
7916 return true; 8072 return true;
7917 } else { 8073 } else {
7918 // We are inside inlined function and we know exactly what is inside 8074 // We are inside inlined function and we know exactly what is inside
7919 // arguments object. But we need to be able to materialize at deopt. 8075 // arguments object. But we need to be able to materialize at deopt.
7920 ASSERT_EQ(environment()->arguments_environment()->parameter_count(), 8076 ASSERT_EQ(environment()->arguments_environment()->parameter_count(),
7921 function_state()->entry()->arguments_object()->arguments_count()); 8077 function_state()->entry()->arguments_object()->arguments_count());
7922 HArgumentsObject* args = function_state()->entry()->arguments_object(); 8078 HArgumentsObject* args = function_state()->entry()->arguments_object();
7923 const ZoneList<HValue*>* arguments_values = args->arguments_values(); 8079 const ZoneList<HValue*>* arguments_values = args->arguments_values();
7924 int arguments_count = arguments_values->length(); 8080 int arguments_count = arguments_values->length();
8081 Push(function);
7925 Push(BuildWrapReceiver(receiver, function)); 8082 Push(BuildWrapReceiver(receiver, function));
7926 for (int i = 1; i < arguments_count; i++) { 8083 for (int i = 1; i < arguments_count; i++) {
7927 Push(arguments_values->at(i)); 8084 Push(arguments_values->at(i));
7928 } 8085 }
7929 8086
7930 Handle<JSFunction> known_function; 8087 Handle<JSFunction> known_function;
7931 if (function->IsConstant() && 8088 if (function->IsConstant() &&
7932 HConstant::cast(function)->handle(isolate())->IsJSFunction()) { 8089 HConstant::cast(function)->handle(isolate())->IsJSFunction()) {
7933 known_function = Handle<JSFunction>::cast( 8090 known_function = Handle<JSFunction>::cast(
7934 HConstant::cast(function)->handle(isolate())); 8091 HConstant::cast(function)->handle(isolate()));
7935 int args_count = arguments_count - 1; // Excluding receiver. 8092 int args_count = arguments_count - 1; // Excluding receiver.
7936 if (TryInlineApply(known_function, expr, args_count)) return true; 8093 if (TryInlineApply(known_function, expr, args_count)) return true;
7937 } 8094 }
7938 8095
7939 Drop(arguments_count - 1); 8096 PushArgumentsFromEnvironment(arguments_count);
7940 Push(Add<HPushArgument>(Pop())); 8097 HInvokeFunction* call = New<HInvokeFunction>(
7941 for (int i = 1; i < arguments_count; i++) { 8098 function, known_function, arguments_count);
7942 Push(Add<HPushArgument>(arguments_values->at(i))); 8099 Drop(1); // Function.
7943 }
7944
7945 HInvokeFunction* call = New<HInvokeFunction>(function,
7946 known_function,
7947 arguments_count);
7948 Drop(arguments_count);
7949 ast_context()->ReturnInstruction(call, expr->id()); 8100 ast_context()->ReturnInstruction(call, expr->id());
7950 return true; 8101 return true;
7951 } 8102 }
7952 } 8103 }
7953 8104
7954 8105
7955 HValue* HOptimizedGraphBuilder::ImplicitReceiverFor(HValue* function, 8106 HValue* HOptimizedGraphBuilder::ImplicitReceiverFor(HValue* function,
7956 Handle<JSFunction> target) { 8107 Handle<JSFunction> target) {
7957 SharedFunctionInfo* shared = target->shared(); 8108 SharedFunctionInfo* shared = target->shared();
7958 if (shared->is_classic_mode() && !shared->native()) { 8109 if (shared->is_classic_mode() && !shared->native()) {
7959 HValue* context = Add<HLoadNamedField>( 8110 // Cannot embed a direct reference to the global proxy
7960 function, static_cast<HValue*>(NULL), 8111 // as is it dropped on deserialization.
7961 HObjectAccess::ForJSObjectOffset(JSFunction::kContextOffset)); 8112 CHECK(!Serializer::enabled());
7962 HValue* global_object = Add<HLoadNamedField>( 8113 Handle<JSObject> global_receiver(
7963 context, static_cast<HValue*>(NULL), 8114 target->context()->global_object()->global_receiver());
7964 HObjectAccess::ForContextSlot(Context::GLOBAL_OBJECT_INDEX)); 8115 return Add<HConstant>(global_receiver);
7965 return Add<HLoadNamedField>(
7966 global_object, static_cast<HValue*>(NULL),
7967 HObjectAccess::ForJSObjectOffset(
7968 GlobalObject::kGlobalReceiverOffset));
7969 } 8116 }
7970 return graph()->GetConstantUndefined(); 8117 return graph()->GetConstantUndefined();
7971 } 8118 }
7972 8119
7973 8120
7974 void HOptimizedGraphBuilder::VisitCall(Call* expr) { 8121 void HOptimizedGraphBuilder::VisitCall(Call* expr) {
7975 ASSERT(!HasStackOverflow()); 8122 ASSERT(!HasStackOverflow());
7976 ASSERT(current_block() != NULL); 8123 ASSERT(current_block() != NULL);
7977 ASSERT(current_block()->HasPredecessor()); 8124 ASSERT(current_block()->HasPredecessor());
7978 Expression* callee = expr->expression(); 8125 Expression* callee = expr->expression();
7979 int argument_count = expr->arguments()->length() + 1; // Plus receiver. 8126 int argument_count = expr->arguments()->length() + 1; // Plus receiver.
7980 HInstruction* call = NULL; 8127 HInstruction* call = NULL;
7981 8128
7982 Property* prop = callee->AsProperty(); 8129 Property* prop = callee->AsProperty();
7983 if (prop != NULL) { 8130 if (prop != NULL) {
7984 if (!prop->key()->IsPropertyName()) { 8131 CHECK_ALIVE(VisitForValue(prop->obj()));
7985 // Keyed function call. 8132 HValue* receiver = Top();
7986 CHECK_ALIVE(VisitForValue(prop->obj()));
7987 CHECK_ALIVE(VisitForValue(prop->key()));
7988 8133
7989 // Push receiver and key like the non-optimized code generator expects it. 8134 SmallMapList* types;
7990 HValue* key = Pop(); 8135 ComputeReceiverTypes(expr, receiver, &types);
7991 HValue* receiver = Pop();
7992 Push(key);
7993 Push(Add<HPushArgument>(receiver));
7994 CHECK_ALIVE(VisitArgumentList(expr->arguments()));
7995 8136
7996 if (expr->IsMonomorphic()) { 8137 if (prop->key()->IsPropertyName() && types->length() > 0) {
7997 BuildCheckHeapObject(receiver); 8138 Handle<String> name = prop->key()->AsLiteral()->AsPropertyName();
7998 ElementsKind kind = expr->KeyedArrayCallIsHoley() 8139 PropertyAccessInfo info(this, IC::MapToType(types->first()), name);
7999 ? FAST_HOLEY_ELEMENTS : FAST_ELEMENTS; 8140 if (!info.CanLoadAsMonomorphic(types)) {
8000 8141 HandlePolymorphicCallNamed(expr, receiver, types, name);
8001 Handle<Map> map(isolate()->get_initial_js_array_map(kind)); 8142 return;
8002
8003 HValue* function = BuildMonomorphicElementAccess(
8004 receiver, key, NULL, NULL, map, false, STANDARD_STORE);
8005
8006 call = New<HCallFunction>(function, argument_count);
8007 } else {
8008 call = NewCallKeyed(key, argument_count);
8009 } 8143 }
8010 Drop(argument_count + 1); // 1 is the key.
8011 return ast_context()->ReturnInstruction(call, expr->id());
8012 } 8144 }
8013 8145
8014 // Named function call. 8146 HValue* key = NULL;
8015 if (TryCallApply(expr)) return; 8147 if (!prop->key()->IsPropertyName()) {
8016 8148 CHECK_ALIVE(VisitForValue(prop->key()));
8017 CHECK_ALIVE(VisitForValue(prop->obj())); 8149 key = Pop();
8018 CHECK_ALIVE(VisitExpressions(expr->arguments()));
8019
8020 Handle<String> name = prop->key()->AsLiteral()->AsPropertyName();
8021 HValue* receiver =
8022 environment()->ExpressionStackAt(expr->arguments()->length());
8023
8024 SmallMapList* types;
8025 bool was_monomorphic = expr->IsMonomorphic();
8026 bool monomorphic = ComputeReceiverTypes(expr, receiver, &types);
8027 if (!was_monomorphic && monomorphic) {
8028 monomorphic = expr->ComputeTarget(types->first(), name);
8029 } 8150 }
8030 8151
8031 if (monomorphic) { 8152 CHECK_ALIVE(PushLoad(prop, receiver, key));
8032 Handle<Map> map = types->first(); 8153 HValue* function = Pop();
8033 if (TryInlineBuiltinMethodCall(expr, receiver, map, expr->check_type())) { 8154
8155 // Push the function under the receiver.
8156 environment()->SetExpressionStackAt(0, function);
8157
8158 Push(receiver);
8159
8160 if (function->IsConstant() &&
8161 HConstant::cast(function)->handle(isolate())->IsJSFunction()) {
8162 Handle<JSFunction> known_function = Handle<JSFunction>::cast(
8163 HConstant::cast(function)->handle(isolate()));
8164 expr->set_target(known_function);
8165
8166 if (TryCallApply(expr)) return;
8167 CHECK_ALIVE(VisitExpressions(expr->arguments()));
8168
8169 Handle<Map> map = types->length() == 1 ? types->first() : Handle<Map>();
8170 if (TryInlineBuiltinMethodCall(expr, receiver, map)) {
8034 if (FLAG_trace_inlining) { 8171 if (FLAG_trace_inlining) {
8035 PrintF("Inlining builtin "); 8172 PrintF("Inlining builtin ");
8036 expr->target()->ShortPrint(); 8173 known_function->ShortPrint();
8037 PrintF("\n"); 8174 PrintF("\n");
8038 } 8175 }
8039 return; 8176 return;
8040 } 8177 }
8178 if (TryInlineApiMethodCall(expr, receiver, map)) return;
8041 8179
8042 if (CallStubCompiler::HasCustomCallGenerator(expr->target()) || 8180 // Wrap the receiver if necessary.
8043 expr->check_type() != RECEIVER_MAP_CHECK) { 8181 if (NeedsWrappingFor(IC::MapToType(types->first()), known_function)) {
8044 // When the target has a custom call IC generator, use the IC, 8182 // Since HWrapReceiver currently cannot actually wrap numbers and
8045 // because it is likely to generate better code. Also use the IC 8183 // strings, use the regular CallFunctionStub for method calls to wrap
8046 // when a primitive receiver check is required. 8184 // the receiver.
8047 call = NewCallNamed(name, argument_count); 8185 // TODO(verwaest): Support creation of value wrappers directly in
8048 PushArgumentsFromEnvironment(argument_count); 8186 // HWrapReceiver.
8187 call = New<HCallFunction>(
8188 function, argument_count, WRAP_AND_CALL);
8189 } else if (TryInlineCall(expr)) {
8190 return;
8049 } else { 8191 } else {
8050 AddCheckConstantFunction(expr->holder(), receiver, map); 8192 call = BuildCallConstantFunction(known_function, argument_count);
8051
8052 if (TryInlineCall(expr)) return;
8053 call = BuildCallConstantFunction(expr->target(), argument_count);
8054 PushArgumentsFromEnvironment(argument_count);
8055 } 8193 }
8056 } else if (types != NULL && types->length() > 1) {
8057 ASSERT(expr->check_type() == RECEIVER_MAP_CHECK);
8058 HandlePolymorphicCallNamed(expr, receiver, types, name);
8059 return;
8060 8194
8061 } else { 8195 } else {
8062 call = NewCallNamed(name, argument_count); 8196 CHECK_ALIVE(VisitExpressions(expr->arguments()));
8063 PushArgumentsFromEnvironment(argument_count); 8197 CallFunctionFlags flags = receiver->type().IsJSObject()
8198 ? NO_CALL_FUNCTION_FLAGS : CALL_AS_METHOD;
8199 call = New<HCallFunction>(function, argument_count, flags);
8064 } 8200 }
8201 PushArgumentsFromEnvironment(argument_count);
8202
8065 } else { 8203 } else {
8066 VariableProxy* proxy = expr->expression()->AsVariableProxy(); 8204 VariableProxy* proxy = expr->expression()->AsVariableProxy();
8067 if (proxy != NULL && proxy->var()->is_possibly_eval(isolate())) { 8205 if (proxy != NULL && proxy->var()->is_possibly_eval(isolate())) {
8068 return Bailout(kPossibleDirectCallToEval); 8206 return Bailout(kPossibleDirectCallToEval);
8069 } 8207 }
8070 8208
8071 bool global_call = proxy != NULL && proxy->var()->IsUnallocated(); 8209 bool global_call = proxy != NULL && proxy->var()->IsUnallocated();
8072 if (global_call) { 8210 if (global_call) {
8073 Variable* var = proxy->var(); 8211 Variable* var = proxy->var();
8074 bool known_global_function = false; 8212 bool known_global_function = false;
8075 // If there is a global property cell for the name at compile time and 8213 // If there is a global property cell for the name at compile time and
8076 // access check is not enabled we assume that the function will not change 8214 // access check is not enabled we assume that the function will not change
8077 // and generate optimized code for calling the function. 8215 // and generate optimized code for calling the function.
8078 LookupResult lookup(isolate()); 8216 LookupResult lookup(isolate());
8079 GlobalPropertyAccess type = LookupGlobalProperty(var, &lookup, false); 8217 GlobalPropertyAccess type = LookupGlobalProperty(var, &lookup, false);
8080 if (type == kUseCell && 8218 if (type == kUseCell &&
8081 !current_info()->global_object()->IsAccessCheckNeeded()) { 8219 !current_info()->global_object()->IsAccessCheckNeeded()) {
8082 Handle<GlobalObject> global(current_info()->global_object()); 8220 Handle<GlobalObject> global(current_info()->global_object());
8083 known_global_function = expr->ComputeGlobalTarget(global, &lookup); 8221 known_global_function = expr->ComputeGlobalTarget(global, &lookup);
8084 } 8222 }
8223 CHECK_ALIVE(VisitForValue(expr->expression()));
8224 HValue* function = Top();
8085 if (known_global_function) { 8225 if (known_global_function) {
8086 // Push the global object instead of the global receiver because 8226 Add<HCheckValue>(function, expr->target());
8087 // code generated by the full code generator expects it.
8088 HValue* global_object = Add<HLoadNamedField>(
8089 context(), static_cast<HValue*>(NULL),
8090 HObjectAccess::ForContextSlot(Context::GLOBAL_OBJECT_INDEX));
8091 Push(global_object);
8092 8227
8228 // Placeholder for the receiver.
8229 Push(graph()->GetConstantUndefined());
8093 CHECK_ALIVE(VisitExpressions(expr->arguments())); 8230 CHECK_ALIVE(VisitExpressions(expr->arguments()));
8094 8231
8095 CHECK_ALIVE(VisitForValue(expr->expression()));
8096 HValue* function = Pop();
8097 Add<HCheckValue>(function, expr->target());
8098
8099 // Patch the global object on the stack by the expected receiver. 8232 // Patch the global object on the stack by the expected receiver.
8100 HValue* receiver = ImplicitReceiverFor(function, expr->target()); 8233 HValue* receiver = ImplicitReceiverFor(function, expr->target());
8101 const int receiver_index = argument_count - 1; 8234 const int receiver_index = argument_count - 1;
8102 environment()->SetExpressionStackAt(receiver_index, receiver); 8235 environment()->SetExpressionStackAt(receiver_index, receiver);
8103 8236
8104 if (TryInlineBuiltinFunctionCall(expr, false)) { // Nothing to drop. 8237 if (TryInlineBuiltinFunctionCall(expr)) {
8105 if (FLAG_trace_inlining) { 8238 if (FLAG_trace_inlining) {
8106 PrintF("Inlining builtin "); 8239 PrintF("Inlining builtin ");
8107 expr->target()->ShortPrint(); 8240 expr->target()->ShortPrint();
8108 PrintF("\n"); 8241 PrintF("\n");
8109 } 8242 }
8110 return; 8243 return;
8111 } 8244 }
8245 if (TryInlineApiFunctionCall(expr, receiver)) return;
8112 if (TryInlineCall(expr)) return; 8246 if (TryInlineCall(expr)) return;
8113 8247
8114 if (expr->target().is_identical_to(current_info()->closure())) { 8248 PushArgumentsFromEnvironment(argument_count);
8115 graph()->MarkRecursive(); 8249 call = BuildCallConstantFunction(expr->target(), argument_count);
8116 }
8117
8118 if (CallStubCompiler::HasCustomCallGenerator(expr->target())) {
8119 // We're about to install a contextual IC, which expects the global
8120 // object as receiver rather than the global proxy.
8121 HValue* global_object = Add<HLoadNamedField>(
8122 context(), static_cast<HValue*>(NULL),
8123 HObjectAccess::ForContextSlot(Context::GLOBAL_OBJECT_INDEX));
8124 const int receiver_index = argument_count - 1;
8125 environment()->SetExpressionStackAt(receiver_index, global_object);
8126 // When the target has a custom call IC generator, use the IC,
8127 // because it is likely to generate better code.
8128 call = NewCallNamed(var->name(), argument_count);
8129 PushArgumentsFromEnvironment(argument_count);
8130 } else {
8131 call = BuildCallConstantFunction(expr->target(), argument_count);
8132 PushArgumentsFromEnvironment(argument_count);
8133 }
8134 } else { 8250 } else {
8135 HValue* receiver = Add<HLoadNamedField>( 8251 Push(Add<HPushArgument>(graph()->GetConstantUndefined()));
8136 context(), static_cast<HValue*>(NULL),
8137 HObjectAccess::ForContextSlot(Context::GLOBAL_OBJECT_INDEX));
8138 Push(Add<HPushArgument>(receiver));
8139 CHECK_ALIVE(VisitArgumentList(expr->arguments())); 8252 CHECK_ALIVE(VisitArgumentList(expr->arguments()));
8140 8253 call = New<HCallFunction>(function, argument_count);
8141 call = NewCallNamed(var->name(), argument_count);
8142 Drop(argument_count); 8254 Drop(argument_count);
8143 } 8255 }
8144 8256
8145 } else if (expr->IsMonomorphic()) { 8257 } else if (expr->IsMonomorphic()) {
8146 // The function is on the stack in the unoptimized code during 8258 // The function is on the stack in the unoptimized code during
8147 // evaluation of the arguments. 8259 // evaluation of the arguments.
8148 CHECK_ALIVE(VisitForValue(expr->expression())); 8260 CHECK_ALIVE(VisitForValue(expr->expression()));
8149 HValue* function = Top(); 8261 HValue* function = Top();
8150 8262
8151 Add<HCheckValue>(function, expr->target()); 8263 Add<HCheckValue>(function, expr->target());
8152 8264
8153 HValue* receiver = ImplicitReceiverFor(function, expr->target()); 8265 Push(graph()->GetConstantUndefined());
8154 Push(receiver);
8155
8156 CHECK_ALIVE(VisitExpressions(expr->arguments())); 8266 CHECK_ALIVE(VisitExpressions(expr->arguments()));
8157 8267
8158 if (TryInlineBuiltinFunctionCall(expr, true)) { // Drop the function. 8268 HValue* receiver = ImplicitReceiverFor(function, expr->target());
8269 const int receiver_index = argument_count - 1;
8270 environment()->SetExpressionStackAt(receiver_index, receiver);
8271
8272 if (TryInlineBuiltinFunctionCall(expr)) {
8159 if (FLAG_trace_inlining) { 8273 if (FLAG_trace_inlining) {
8160 PrintF("Inlining builtin "); 8274 PrintF("Inlining builtin ");
8161 expr->target()->ShortPrint(); 8275 expr->target()->ShortPrint();
8162 PrintF("\n"); 8276 PrintF("\n");
8163 } 8277 }
8164 return; 8278 return;
8165 } 8279 }
8280 if (TryInlineApiFunctionCall(expr, receiver)) return;
8166 8281
8167 if (TryInlineCall(expr, true)) { // Drop function from environment. 8282 if (TryInlineCall(expr)) return;
8168 return; 8283
8169 } else { 8284 call = PreProcessCall(New<HInvokeFunction>(
8170 call = PreProcessCall(New<HInvokeFunction>(function, expr->target(), 8285 function, expr->target(), argument_count));
8171 argument_count));
8172 Drop(1); // The function.
8173 }
8174 8286
8175 } else { 8287 } else {
8176 CHECK_ALIVE(VisitForValue(expr->expression())); 8288 CHECK_ALIVE(VisitForValue(expr->expression()));
8177 HValue* function = Top(); 8289 HValue* function = Top();
8178 HValue* receiver = graph()->GetConstantUndefined(); 8290 HValue* receiver = graph()->GetConstantUndefined();
8179 Push(Add<HPushArgument>(receiver)); 8291 Push(Add<HPushArgument>(receiver));
8180 CHECK_ALIVE(VisitArgumentList(expr->arguments())); 8292 CHECK_ALIVE(VisitArgumentList(expr->arguments()));
8181 call = New<HCallFunction>( 8293 call = New<HCallFunction>(function, argument_count);
8182 function, argument_count, NORMAL_CONTEXTUAL_CALL); 8294 Drop(argument_count);
8183 Drop(argument_count + 1);
8184 } 8295 }
8185 } 8296 }
8186 8297
8298 Drop(1); // Drop the function.
8187 return ast_context()->ReturnInstruction(call, expr->id()); 8299 return ast_context()->ReturnInstruction(call, expr->id());
8188 } 8300 }
8189 8301
8190 8302
8191 void HOptimizedGraphBuilder::BuildInlinedCallNewArray(CallNew* expr) { 8303 void HOptimizedGraphBuilder::BuildInlinedCallNewArray(CallNew* expr) {
8192 NoObservableSideEffectsScope no_effects(this); 8304 NoObservableSideEffectsScope no_effects(this);
8193 8305
8194 int argument_count = expr->arguments()->length(); 8306 int argument_count = expr->arguments()->length();
8195 // We should at least have the constructor on the expression stack. 8307 // We should at least have the constructor on the expression stack.
8196 HValue* constructor = environment()->ExpressionStackAt(argument_count); 8308 HValue* constructor = environment()->ExpressionStackAt(argument_count);
(...skipping 2128 matching lines...) Expand 10 before | Expand all | Expand 10 after
10325 void HOptimizedGraphBuilder::GenerateClassOf(CallRuntime* call) { 10437 void HOptimizedGraphBuilder::GenerateClassOf(CallRuntime* call) {
10326 // The special form detected by IsClassOfTest is detected before we get here 10438 // The special form detected by IsClassOfTest is detected before we get here
10327 // and does not cause a bailout. 10439 // and does not cause a bailout.
10328 return Bailout(kInlinedRuntimeFunctionClassOf); 10440 return Bailout(kInlinedRuntimeFunctionClassOf);
10329 } 10441 }
10330 10442
10331 10443
10332 void HOptimizedGraphBuilder::GenerateValueOf(CallRuntime* call) { 10444 void HOptimizedGraphBuilder::GenerateValueOf(CallRuntime* call) {
10333 ASSERT(call->arguments()->length() == 1); 10445 ASSERT(call->arguments()->length() == 1);
10334 CHECK_ALIVE(VisitForValue(call->arguments()->at(0))); 10446 CHECK_ALIVE(VisitForValue(call->arguments()->at(0)));
10335 HValue* value = Pop(); 10447 HValue* object = Pop();
10336 HValueOf* result = New<HValueOf>(value); 10448
10337 return ast_context()->ReturnInstruction(result, call->id()); 10449 IfBuilder if_objectisvalue(this);
10450 HValue* objectisvalue = if_objectisvalue.If<HHasInstanceTypeAndBranch>(
10451 object, JS_VALUE_TYPE);
10452 if_objectisvalue.Then();
10453 {
10454 // Return the actual value.
10455 Push(Add<HLoadNamedField>(
10456 object, objectisvalue,
10457 HObjectAccess::ForJSObjectOffset(JSValue::kValueOffset)));
10458 Add<HSimulate>(call->id(), FIXED_SIMULATE);
10459 }
10460 if_objectisvalue.Else();
10461 {
10462 // If the object is not a value return the object.
10463 Push(object);
10464 Add<HSimulate>(call->id(), FIXED_SIMULATE);
10465 }
10466 if_objectisvalue.End();
10467 return ast_context()->ReturnValue(Pop());
10338 } 10468 }
10339 10469
10340 10470
10341 void HOptimizedGraphBuilder::GenerateDateField(CallRuntime* call) { 10471 void HOptimizedGraphBuilder::GenerateDateField(CallRuntime* call) {
10342 ASSERT(call->arguments()->length() == 2); 10472 ASSERT(call->arguments()->length() == 2);
10343 ASSERT_NE(NULL, call->arguments()->at(1)->AsLiteral()); 10473 ASSERT_NE(NULL, call->arguments()->at(1)->AsLiteral());
10344 Smi* index = Smi::cast(*(call->arguments()->at(1)->AsLiteral()->value())); 10474 Smi* index = Smi::cast(*(call->arguments()->at(1)->AsLiteral()->value()));
10345 CHECK_ALIVE(VisitForValue(call->arguments()->at(0))); 10475 CHECK_ALIVE(VisitForValue(call->arguments()->at(0)));
10346 HValue* date = Pop(); 10476 HValue* date = Pop();
10347 HDateField* result = New<HDateField>(date, index); 10477 HDateField* result = New<HDateField>(date, index);
(...skipping 252 matching lines...) Expand 10 before | Expand all | Expand 10 after
10600 10730
10601 void HOptimizedGraphBuilder::GenerateMathSqrt(CallRuntime* call) { 10731 void HOptimizedGraphBuilder::GenerateMathSqrt(CallRuntime* call) {
10602 ASSERT(call->arguments()->length() == 1); 10732 ASSERT(call->arguments()->length() == 1);
10603 CHECK_ALIVE(VisitForValue(call->arguments()->at(0))); 10733 CHECK_ALIVE(VisitForValue(call->arguments()->at(0)));
10604 HValue* value = Pop(); 10734 HValue* value = Pop();
10605 HInstruction* result = NewUncasted<HUnaryMathOperation>(value, kMathSqrt); 10735 HInstruction* result = NewUncasted<HUnaryMathOperation>(value, kMathSqrt);
10606 return ast_context()->ReturnInstruction(result, call->id()); 10736 return ast_context()->ReturnInstruction(result, call->id());
10607 } 10737 }
10608 10738
10609 10739
10610 // Check whether two RegExps are equivalent
10611 void HOptimizedGraphBuilder::GenerateIsRegExpEquivalent(CallRuntime* call) {
10612 return Bailout(kInlinedRuntimeFunctionIsRegExpEquivalent);
10613 }
10614
10615
10616 void HOptimizedGraphBuilder::GenerateGetCachedArrayIndex(CallRuntime* call) { 10740 void HOptimizedGraphBuilder::GenerateGetCachedArrayIndex(CallRuntime* call) {
10617 ASSERT(call->arguments()->length() == 1); 10741 ASSERT(call->arguments()->length() == 1);
10618 CHECK_ALIVE(VisitForValue(call->arguments()->at(0))); 10742 CHECK_ALIVE(VisitForValue(call->arguments()->at(0)));
10619 HValue* value = Pop(); 10743 HValue* value = Pop();
10620 HGetCachedArrayIndex* result = New<HGetCachedArrayIndex>(value); 10744 HGetCachedArrayIndex* result = New<HGetCachedArrayIndex>(value);
10621 return ast_context()->ReturnInstruction(result, call->id()); 10745 return ast_context()->ReturnInstruction(result, call->id());
10622 } 10746 }
10623 10747
10624 10748
10625 void HOptimizedGraphBuilder::GenerateFastAsciiArrayJoin(CallRuntime* call) { 10749 void HOptimizedGraphBuilder::GenerateFastAsciiArrayJoin(CallRuntime* call) {
(...skipping 634 matching lines...) Expand 10 before | Expand all | Expand 10 after
11260 if (ShouldProduceTraceOutput()) { 11384 if (ShouldProduceTraceOutput()) {
11261 isolate()->GetHTracer()->TraceHydrogen(name(), graph_); 11385 isolate()->GetHTracer()->TraceHydrogen(name(), graph_);
11262 } 11386 }
11263 11387
11264 #ifdef DEBUG 11388 #ifdef DEBUG
11265 graph_->Verify(false); // No full verify. 11389 graph_->Verify(false); // No full verify.
11266 #endif 11390 #endif
11267 } 11391 }
11268 11392
11269 } } // namespace v8::internal 11393 } } // namespace v8::internal
OLDNEW
« no previous file with comments | « src/hydrogen.h ('k') | src/hydrogen-instructions.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698