Index: src/crankshaft/hydrogen.cc |
diff --git a/src/crankshaft/hydrogen.cc b/src/crankshaft/hydrogen.cc |
index 6868f5563ea4bef76fb023a0f193b538e1b124b7..9e934f0a13fcfe11eff106da036461d70efe6175 100644 |
--- a/src/crankshaft/hydrogen.cc |
+++ b/src/crankshaft/hydrogen.cc |
@@ -8820,9 +8820,13 @@ bool HOptimizedGraphBuilder::TryInlineGetter(Handle<Object> getter, |
BailoutId ast_id, |
BailoutId return_id) { |
if (TryInlineApiGetter(getter, receiver_map, ast_id)) return true; |
- return getter->IsJSFunction() && |
- TryInline(Handle<JSFunction>::cast(getter), 0, NULL, ast_id, return_id, |
- GETTER_CALL_RETURN, TailCallMode::kDisallow); |
+ if (getter->IsJSFunction()) { |
+ Handle<JSFunction> getter_function = Handle<JSFunction>::cast(getter); |
+ return TryInlineBuiltinGetterCall(getter_function, receiver_map, ast_id) || |
+ TryInline(getter_function, 0, NULL, ast_id, return_id, |
+ GETTER_CALL_RETURN, TailCallMode::kDisallow); |
+ } |
+ return false; |
} |
bool HOptimizedGraphBuilder::TryInlineSetter(Handle<Object> setter, |
@@ -8914,9 +8918,62 @@ bool HOptimizedGraphBuilder::CanInlineArrayResizeOperation( |
!IsReadOnlyLengthDescriptor(receiver_map); |
} |
+bool HOptimizedGraphBuilder::TryInlineBuiltinGetterCall( |
+ Handle<JSFunction> function, Handle<Map> receiver_map, BailoutId ast_id) { |
+ if (!function->shared()->HasBuiltinFunctionId()) return false; |
+ BuiltinFunctionId id = function->shared()->builtin_function_id(); |
+ |
+ // Try to inline getter calls like DataView.prototype.byteLength/byteOffset |
+ // as operations in the calling function. |
+ switch (id) { |
+ case kDataViewBuffer: { |
+ if (!receiver_map->IsJSDataViewMap()) return false; |
+ HObjectAccess access = HObjectAccess::ForMapAndOffset( |
+ receiver_map, JSDataView::kBufferOffset); |
+ HValue* object = Pop(); // receiver |
+ HInstruction* result = New<HLoadNamedField>(object, object, access); |
+ ast_context()->ReturnInstruction(result, ast_id); |
+ return true; |
+ } |
+ case kDataViewByteLength: |
+ case kDataViewByteOffset: { |
+ if (!receiver_map->IsJSDataViewMap()) return false; |
+ int offset = (id == kDataViewByteLength) ? JSDataView::kByteLengthOffset |
+ : JSDataView::kByteOffsetOffset; |
+ HObjectAccess access = |
+ HObjectAccess::ForMapAndOffset(receiver_map, offset); |
+ HValue* object = Pop(); // receiver |
+ HValue* checked_object = Add<HCheckArrayBufferNotNeutered>(object); |
+ HInstruction* result = |
+ New<HLoadNamedField>(object, checked_object, access); |
+ ast_context()->ReturnInstruction(result, ast_id); |
+ return true; |
+ } |
+ case kTypedArrayByteLength: |
+ case kTypedArrayByteOffset: |
+ case kTypedArrayLength: { |
+ if (!receiver_map->IsJSTypedArrayMap()) return false; |
+ int offset = (id == kTypedArrayLength) |
+ ? JSTypedArray::kLengthOffset |
+ : (id == kTypedArrayByteLength) |
+ ? JSTypedArray::kByteLengthOffset |
+ : JSTypedArray::kByteOffsetOffset; |
+ HObjectAccess access = |
+ HObjectAccess::ForMapAndOffset(receiver_map, offset); |
+ HValue* object = Pop(); // receiver |
+ HValue* checked_object = Add<HCheckArrayBufferNotNeutered>(object); |
+ HInstruction* result = |
+ New<HLoadNamedField>(object, checked_object, access); |
+ ast_context()->ReturnInstruction(result, ast_id); |
+ return true; |
+ } |
+ default: |
+ return false; |
+ } |
+} |
bool HOptimizedGraphBuilder::TryInlineBuiltinMethodCall( |
- Call* expr, Handle<JSFunction> function, Handle<Map> receiver_map, |
+ Handle<JSFunction> function, Handle<Map> receiver_map, BailoutId ast_id, |
int args_count_no_receiver) { |
if (!function->shared()->HasBuiltinFunctionId()) return false; |
BuiltinFunctionId id = function->shared()->builtin_function_id(); |
@@ -8961,12 +9018,12 @@ bool HOptimizedGraphBuilder::TryInlineBuiltinMethodCall( |
HInstruction* char_code = |
BuildStringCharCodeAt(string, index); |
if (id == kStringCharCodeAt) { |
- ast_context()->ReturnInstruction(char_code, expr->id()); |
+ ast_context()->ReturnInstruction(char_code, ast_id); |
return true; |
} |
AddInstruction(char_code); |
HInstruction* result = NewUncasted<HStringCharFromCode>(char_code); |
- ast_context()->ReturnInstruction(result, expr->id()); |
+ ast_context()->ReturnInstruction(result, ast_id); |
return true; |
} |
break; |
@@ -8978,7 +9035,7 @@ bool HOptimizedGraphBuilder::TryInlineBuiltinMethodCall( |
argument, Representation::Integer32()); |
argument->SetFlag(HValue::kTruncatingToInt32); |
HInstruction* result = NewUncasted<HStringCharFromCode>(argument); |
- ast_context()->ReturnInstruction(result, expr->id()); |
+ ast_context()->ReturnInstruction(result, ast_id); |
return true; |
} |
break; |
@@ -8996,7 +9053,7 @@ bool HOptimizedGraphBuilder::TryInlineBuiltinMethodCall( |
HValue* argument = Pop(); |
Drop(2); // Receiver and function. |
HInstruction* op = NewUncasted<HUnaryMathOperation>(argument, id); |
- ast_context()->ReturnInstruction(op, expr->id()); |
+ ast_context()->ReturnInstruction(op, ast_id); |
return true; |
} |
break; |
@@ -9027,7 +9084,7 @@ bool HOptimizedGraphBuilder::TryInlineBuiltinMethodCall( |
if (result == NULL) { |
result = NewUncasted<HPower>(left, right); |
} |
- ast_context()->ReturnInstruction(result, expr->id()); |
+ ast_context()->ReturnInstruction(result, ast_id); |
return true; |
} |
break; |
@@ -9040,7 +9097,7 @@ bool HOptimizedGraphBuilder::TryInlineBuiltinMethodCall( |
HMathMinMax::Operation op = (id == kMathMin) ? HMathMinMax::kMathMin |
: HMathMinMax::kMathMax; |
HInstruction* result = NewUncasted<HMathMinMax>(left, right, op); |
- ast_context()->ReturnInstruction(result, expr->id()); |
+ ast_context()->ReturnInstruction(result, ast_id); |
return true; |
} |
break; |
@@ -9051,7 +9108,7 @@ bool HOptimizedGraphBuilder::TryInlineBuiltinMethodCall( |
Drop(2); // Receiver and function. |
HInstruction* result = |
HMul::NewImul(isolate(), zone(), context(), left, right); |
- ast_context()->ReturnInstruction(result, expr->id()); |
+ ast_context()->ReturnInstruction(result, ast_id); |
return true; |
} |
break; |
@@ -9107,7 +9164,7 @@ bool HOptimizedGraphBuilder::TryInlineBuiltinMethodCall( |
length_checker.End(); |
} |
result = ast_context()->IsEffect() ? graph()->GetConstant0() : Top(); |
- Add<HSimulate>(expr->id(), REMOVABLE_SIMULATE); |
+ Add<HSimulate>(ast_id, REMOVABLE_SIMULATE); |
if (!ast_context()->IsEffect()) Drop(1); |
ast_context()->ReturnValue(result); |
@@ -9160,7 +9217,7 @@ bool HOptimizedGraphBuilder::TryInlineBuiltinMethodCall( |
STORE, NEVER_RETURN_HOLE, STORE_AND_GROW_NO_TRANSITION); |
if (!ast_context()->IsEffect()) Push(new_size); |
- Add<HSimulate>(expr->id(), REMOVABLE_SIMULATE); |
+ Add<HSimulate>(ast_id, REMOVABLE_SIMULATE); |
if (!ast_context()->IsEffect()) Drop(1); |
} |
@@ -9274,7 +9331,7 @@ bool HOptimizedGraphBuilder::TryInlineBuiltinMethodCall( |
if_lengthiszero.End(); |
} |
result = ast_context()->IsEffect() ? graph()->GetConstant0() : Top(); |
- Add<HSimulate>(expr->id(), REMOVABLE_SIMULATE); |
+ Add<HSimulate>(ast_id, REMOVABLE_SIMULATE); |
if (!ast_context()->IsEffect()) Drop(1); |
ast_context()->ReturnValue(result); |
return true; |
@@ -9311,7 +9368,7 @@ bool HOptimizedGraphBuilder::TryInlineBuiltinMethodCall( |
HValue* index = BuildArrayIndexOf(receiver, search_element, kind, mode); |
if (!ast_context()->IsEffect()) Push(index); |
- Add<HSimulate>(expr->id(), REMOVABLE_SIMULATE); |
+ Add<HSimulate>(ast_id, REMOVABLE_SIMULATE); |
if (!ast_context()->IsEffect()) Drop(1); |
ast_context()->ReturnValue(index); |
return true; |
@@ -9508,7 +9565,7 @@ void HOptimizedGraphBuilder::HandleIndirectCall(Call* expr, HValue* function, |
HConstant::cast(function)->handle(isolate())->IsJSFunction()) { |
known_function = |
Handle<JSFunction>::cast(HConstant::cast(function)->handle(isolate())); |
- if (TryInlineBuiltinMethodCall(expr, known_function, Handle<Map>(), |
+ if (TryInlineBuiltinMethodCall(known_function, Handle<Map>(), expr->id(), |
args_count_no_receiver)) { |
if (FLAG_trace_inlining) { |
PrintF("Inlining builtin "); |
@@ -9909,7 +9966,7 @@ void HOptimizedGraphBuilder::VisitCall(Call* expr) { |
CHECK_ALIVE(VisitExpressions(expr->arguments())); |
Handle<Map> map = maps->length() == 1 ? maps->first() : Handle<Map>(); |
- if (TryInlineBuiltinMethodCall(expr, known_function, map, |
+ if (TryInlineBuiltinMethodCall(known_function, map, expr->id(), |
expr->arguments()->length())) { |
if (FLAG_trace_inlining) { |
PrintF("Inlining builtin "); |