Commit 6302753e authored by vabr's avatar vabr Committed by Commit bot

Fix typeof optimization for undetectable

Currently, typeof o, where o is an undetectable
callable object (such as document.all), returns 'function' if
optimised. It should, however, return 'undefined'.

This CL excludes undetectable objects from the optimization
resulting in type 'function' and renames the related code to
reflect that.

BUG=v8:5972
R=bmeurer@chromium.org

Review-Url: https://codereview.chromium.org/2697063002
Cr-Commit-Position: refs/heads/master@{#43298}
parent 6a797d7e
......@@ -717,8 +717,8 @@ bool EffectControlLinearizer::TryWireInStateEffect(Node* node,
case IrOpcode::kCheckedTruncateTaggedToWord32:
result = LowerCheckedTruncateTaggedToWord32(node, frame_state);
break;
case IrOpcode::kObjectIsCallable:
result = LowerObjectIsCallable(node);
case IrOpcode::kObjectIsDetectableCallable:
result = LowerObjectIsDetectableCallable(node);
break;
case IrOpcode::kObjectIsNonCallable:
result = LowerObjectIsNonCallable(node);
......@@ -1688,7 +1688,7 @@ Node* EffectControlLinearizer::LowerCheckedTruncateTaggedToWord32(
return done.PhiAt(0);
}
Node* EffectControlLinearizer::LowerObjectIsCallable(Node* node) {
Node* EffectControlLinearizer::LowerObjectIsDetectableCallable(Node* node) {
Node* value = node->InputAt(0);
auto if_smi = __ MakeDeferredLabel<1>();
......
......@@ -80,7 +80,7 @@ class V8_EXPORT_PRIVATE EffectControlLinearizer {
Node* LowerTruncateTaggedToFloat64(Node* node);
Node* LowerTruncateTaggedToWord32(Node* node);
Node* LowerCheckedTruncateTaggedToWord32(Node* node, Node* frame_state);
Node* LowerObjectIsCallable(Node* node);
Node* LowerObjectIsDetectableCallable(Node* node);
Node* LowerObjectIsNonCallable(Node* node);
Node* LowerObjectIsNumber(Node* node);
Node* LowerObjectIsReceiver(Node* node);
......
......@@ -829,7 +829,7 @@ bool EscapeStatusAnalysis::CheckUsesForEscape(Node* uses, Node* rep,
case IrOpcode::kStringCharAt:
case IrOpcode::kStringCharCodeAt:
case IrOpcode::kStringIndexOf:
case IrOpcode::kObjectIsCallable:
case IrOpcode::kObjectIsDetectableCallable:
case IrOpcode::kObjectIsNonCallable:
case IrOpcode::kObjectIsNumber:
case IrOpcode::kObjectIsReceiver:
......
......@@ -897,7 +897,7 @@ Reduction JSTypedLowering::ReduceJSEqualTypeOf(Node* node, bool invert) {
graph()->NewNode(simplified()->ReferenceEqual(), input,
jsgraph()->FalseConstant()));
} else if (String::Equals(type, factory()->function_string())) {
value = graph()->NewNode(simplified()->ObjectIsCallable(), input);
value = graph()->NewNode(simplified()->ObjectIsDetectableCallable(), input);
} else if (String::Equals(type, factory()->number_string())) {
value = graph()->NewNode(simplified()->ObjectIsNumber(), input);
} else if (String::Equals(type, factory()->object_string())) {
......
......@@ -332,7 +332,7 @@
V(StoreBuffer) \
V(StoreElement) \
V(StoreTypedElement) \
V(ObjectIsCallable) \
V(ObjectIsDetectableCallable) \
V(ObjectIsNonCallable) \
V(ObjectIsNumber) \
V(ObjectIsReceiver) \
......
......@@ -2521,8 +2521,8 @@ class RepresentationSelector {
}
return;
}
case IrOpcode::kObjectIsCallable: {
VisitObjectIs(node, Type::Callable(), lowering);
case IrOpcode::kObjectIsDetectableCallable: {
VisitObjectIs(node, Type::DetectableCallable(), lowering);
return;
}
case IrOpcode::kObjectIsNonCallable: {
......
......@@ -480,7 +480,7 @@ UnicodeEncoding UnicodeEncodingOf(const Operator* op) {
V(TruncateTaggedToBit, Operator::kNoProperties, 1, 0) \
V(TruncateTaggedToWord32, Operator::kNoProperties, 1, 0) \
V(TruncateTaggedToFloat64, Operator::kNoProperties, 1, 0) \
V(ObjectIsCallable, Operator::kNoProperties, 1, 0) \
V(ObjectIsDetectableCallable, Operator::kNoProperties, 1, 0) \
V(ObjectIsNonCallable, Operator::kNoProperties, 1, 0) \
V(ObjectIsNumber, Operator::kNoProperties, 1, 0) \
V(ObjectIsReceiver, Operator::kNoProperties, 1, 0) \
......
......@@ -411,7 +411,7 @@ class V8_EXPORT_PRIVATE SimplifiedOperatorBuilder final
const Operator* CheckTaggedHole();
const Operator* ConvertTaggedHoleToUndefined();
const Operator* ObjectIsCallable();
const Operator* ObjectIsDetectableCallable();
const Operator* ObjectIsNonCallable();
const Operator* ObjectIsNumber();
const Operator* ObjectIsReceiver();
......
......@@ -284,7 +284,7 @@ class Typer::Visitor : public Reducer {
SIMPLIFIED_SPECULATIVE_NUMBER_BINOP_LIST(DECLARE_METHOD)
#undef DECLARE_METHOD
static Type* ObjectIsCallable(Type*, Typer*);
static Type* ObjectIsDetectableCallable(Type*, Typer*);
static Type* ObjectIsNonCallable(Type*, Typer*);
static Type* ObjectIsNumber(Type*, Typer*);
static Type* ObjectIsReceiver(Type*, Typer*);
......@@ -503,9 +503,9 @@ Type* Typer::Visitor::ToString(Type* type, Typer* t) {
// Type checks.
Type* Typer::Visitor::ObjectIsCallable(Type* type, Typer* t) {
if (type->Is(Type::Callable())) return t->singleton_true_;
if (!type->Maybe(Type::Callable())) return t->singleton_false_;
Type* Typer::Visitor::ObjectIsDetectableCallable(Type* type, Typer* t) {
if (type->Is(Type::DetectableCallable())) return t->singleton_true_;
if (!type->Maybe(Type::DetectableCallable())) return t->singleton_false_;
return Type::Boolean();
}
......@@ -1901,8 +1901,8 @@ Type* Typer::Visitor::TypeStoreTypedElement(Node* node) {
return nullptr;
}
Type* Typer::Visitor::TypeObjectIsCallable(Node* node) {
return TypeUnaryOp(node, ObjectIsCallable);
Type* Typer::Visitor::TypeObjectIsDetectableCallable(Node* node) {
return TypeUnaryOp(node, ObjectIsDetectableCallable);
}
Type* Typer::Visitor::TypeObjectIsNonCallable(Node* node) {
......
......@@ -164,9 +164,9 @@ namespace compiler {
V(Primitive, kSymbol | kPlainPrimitive) \
V(OtherUndetectableOrUndefined, kOtherUndetectable | kUndefined) \
V(Proxy, kCallableProxy | kOtherProxy) \
V(Callable, kFunction | kBoundFunction | \
kOtherCallable | kCallableProxy | \
kOtherUndetectable) \
V(DetectableCallable, kFunction | kBoundFunction | \
kOtherCallable | kCallableProxy) \
V(Callable, kDetectableCallable | kOtherUndetectable) \
V(NonCallable, kOtherObject | kOtherProxy) \
V(NonCallableOrNull, kNonCallable | kNull) \
V(DetectableObject, kFunction | kBoundFunction | \
......
......@@ -952,7 +952,7 @@ void Verifier::Visitor::Check(Node* node) {
CheckTypeIs(node, Type::Boolean());
break;
case IrOpcode::kObjectIsCallable:
case IrOpcode::kObjectIsDetectableCallable:
case IrOpcode::kObjectIsNonCallable:
case IrOpcode::kObjectIsNumber:
case IrOpcode::kObjectIsReceiver:
......
// Copyright 2017 the V8 project authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
// Flags: --allow-natives-syntax
var undetectable = %GetUndetectable();
function foo(a) {
const o = a ? foo : undetectable;
return typeof o === 'function';
}
assertFalse(foo(false));
assertFalse(foo(false));
%OptimizeFunctionOnNextCall(foo);
assertFalse(foo(false));
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment