Chromium Code Reviews| Index: src/builtins/builtins-object-gen.cc |
| diff --git a/src/builtins/builtins-object-gen.cc b/src/builtins/builtins-object-gen.cc |
| index 09930c21b804fff1c204d37441e72433018f1623..1f7a4ad225ed3e368e68bc795e7d2f52e5aca7af 100644 |
| --- a/src/builtins/builtins-object-gen.cc |
| +++ b/src/builtins/builtins-object-gen.cc |
| @@ -192,6 +192,53 @@ TF_BUILTIN(ObjectKeys, ObjectBuiltinsAssembler) { |
| } |
| } |
| +// ES #sec-object.prototype.isprototypeof |
| +TF_BUILTIN(ObjectPrototypeIsPrototypeOf, ObjectBuiltinsAssembler) { |
| + Node* receiver = Parameter(Descriptor::kReceiver); |
| + Node* value = Parameter(Descriptor::kValue); |
| + Node* context = Parameter(Descriptor::kContext); |
| + Label if_receiverisnullorundefined(this, Label::kDeferred), |
| + if_valueisnotreceiver(this, Label::kDeferred); |
| + |
| + // We only check whether {value} is a Smi here, so that the |
| + // prototype chain walk below can safely access the {value}s |
| + // map. We don't rule out Primitive {value}s, since all of |
| + // them have null as their prototype, so the chain walk below |
| + // immediately aborts and returns false anyways. |
| + GotoIf(TaggedIsSmi(value), &if_valueisnotreceiver); |
| + |
| + // Check if {receiver} is either null or undefined and in that case, |
| + // invoke the ToObject builtin, which raises the appropriate error. |
| + // Otherwise we don't need to invoke ToObject, since {receiver} is |
| + // either already a JSReceiver, in which case ToObject is a no-op, |
| + // or it's a Primitive and ToObject would allocate a fresh JSValue |
| + // wrapper, which wouldn't be identical to any existing JSReceiver |
| + // found in the prototype chain of {value}, hence it will return |
| + // false no matter if we search for the Primitive {receiver} or |
| + // a newly allocated JSValue wrapper for {receiver}. |
| + GotoIf(WordEqual(receiver, NullConstant()), &if_receiverisnullorundefined); |
|
jgruber
2017/06/13 07:49:51
Nit: IsNull, IsUndefined (predicates are autogener
Benedikt Meurer
2017/06/13 18:22:44
Done.
|
| + GotoIf(WordEqual(receiver, UndefinedConstant()), |
| + &if_receiverisnullorundefined); |
| + |
| + // Loop through the prototype chain looking for the {receiver}. |
| + Return(HasInPrototypeChain(context, value, receiver)); |
| + |
| + BIND(&if_receiverisnullorundefined); |
| + { |
| + // If {value} is a primitive HeapObject, we need to return |
| + // false instead of throwing an exception per order of the |
| + // steps in the specification, so check that first here. |
| + GotoIfNot(IsJSReceiver(value), &if_valueisnotreceiver); |
| + |
| + // Simulate the ToObject invocation on {receiver}. |
| + CallBuiltin(Builtins::kToObject, context, receiver); |
| + Unreachable(); |
| + } |
| + |
| + BIND(&if_valueisnotreceiver); |
| + Return(BooleanConstant(false)); |
| +} |
| + |
| // ES6 #sec-object.prototype.tostring |
| TF_BUILTIN(ObjectProtoToString, ObjectBuiltinsAssembler) { |
| Label return_undefined(this, Label::kDeferred), |