Index: src/builtins.cc |
diff --git a/src/builtins.cc b/src/builtins.cc |
index 5c8e32b4269d554d9d4452e05e55d439c9951602..3f4920d9636c7b425d6978f41f157b6a0cb12d32 100644 |
--- a/src/builtins.cc |
+++ b/src/builtins.cc |
@@ -1263,12 +1263,28 @@ BUILTIN(StrictModePoisonPill) { |
// |
+// Searches the hidden prototype chain of the given object for the first |
+// object that is an instance of the given type. If no such object can |
+// be found then Heap::null_value() is returned. |
+static inline Object* FindHidden(Heap* heap, |
+ Object* object, |
+ FunctionTemplateInfo* type) { |
+ if (object->IsInstanceOf(type)) return object; |
+ Object* proto = object->GetPrototype(); |
+ if (proto->IsJSObject() && |
+ JSObject::cast(proto)->map()->is_hidden_prototype()) { |
+ return FindHidden(heap, proto, type); |
+ } |
+ return heap->null_value(); |
+} |
+ |
+ |
// Returns the holder JSObject if the function can legally be called |
// with this receiver. Returns Heap::null_value() if the call is |
// illegal. Any arguments that don't fit the expected type is |
-// overwritten with undefined. Arguments that do fit the expected |
-// type is overwritten with the object in the prototype chain that |
-// actually has that type. |
+// overwritten with undefined. Note that holder and the arguments are |
+// implicitly rewritten with the first object in the hidden prototype |
+// chain that actually has the expected type. |
static inline Object* TypeCheck(Heap* heap, |
int argc, |
Object** argv, |
@@ -1281,15 +1297,10 @@ static inline Object* TypeCheck(Heap* heap, |
SignatureInfo* sig = SignatureInfo::cast(sig_obj); |
// If necessary, check the receiver |
Object* recv_type = sig->receiver(); |
- |
Object* holder = recv; |
if (!recv_type->IsUndefined()) { |
- for (; holder != heap->null_value(); holder = holder->GetPrototype()) { |
- if (holder->IsInstanceOf(FunctionTemplateInfo::cast(recv_type))) { |
- break; |
- } |
- } |
- if (holder == heap->null_value()) return holder; |
+ holder = FindHidden(heap, holder, FunctionTemplateInfo::cast(recv_type)); |
+ if (holder == heap->null_value()) return heap->null_value(); |
} |
Object* args_obj = sig->args(); |
// If there is no argument signature we're done |
@@ -1302,13 +1313,9 @@ static inline Object* TypeCheck(Heap* heap, |
if (argtype->IsUndefined()) continue; |
Object** arg = &argv[-1 - i]; |
Object* current = *arg; |
- for (; current != heap->null_value(); current = current->GetPrototype()) { |
- if (current->IsInstanceOf(FunctionTemplateInfo::cast(argtype))) { |
- *arg = current; |
- break; |
- } |
- } |
- if (current == heap->null_value()) *arg = heap->undefined_value(); |
+ current = FindHidden(heap, current, FunctionTemplateInfo::cast(argtype)); |
+ if (current == heap->null_value()) current = heap->undefined_value(); |
+ *arg = current; |
} |
return holder; |
} |