diff --git a/hphp/runtime/ext/ext_array.cpp b/hphp/runtime/ext/ext_array.cpp index e4d150253..9b49bf20b 100644 --- a/hphp/runtime/ext/ext_array.cpp +++ b/hphp/runtime/ext/ext_array.cpp @@ -194,10 +194,14 @@ bool f_array_key_exists(CVarRef key, CVarRef search) { if (LIKELY(saccType == KindOfArray)) { ad = Variant::GetArrayData(sacc); } else if (saccType == KindOfObject) { + ObjectData* obj = Variant::GetObjectData(sacc); + if (obj->isCollection()) { + return collectionOffsetContains(obj, key); + } return f_array_key_exists(key, toArray(search)); } else { throw_bad_type_exception("array_key_exists expects an array or an object; " - "false returned."); + "false returned."); return false; } Variant::TypedValueAccessor kacc = key.getTypedAccessor(); diff --git a/hphp/runtime/vm/translator/hopt/codegen.cpp b/hphp/runtime/vm/translator/hopt/codegen.cpp index 79641c93b..885ae4f44 100644 --- a/hphp/runtime/vm/translator/hopt/codegen.cpp +++ b/hphp/runtime/vm/translator/hopt/codegen.cpp @@ -30,6 +30,7 @@ #include "runtime/base/types.h" #include "runtime/ext/ext_closure.h" #include "runtime/ext/ext_continuation.h" +#include "runtime/ext/ext_collections.h" #include "runtime/vm/bytecode.h" #include "runtime/vm/runtime.h" #include "runtime/base/stats.h" @@ -4547,6 +4548,9 @@ static int64_t ak_exist_int(int64_t key, ArrayData* arr) { HOT_FUNC_VM static int64_t ak_exist_string_obj(StringData* key, ObjectData* obj) { + if (obj->isCollection()) { + return collectionOffsetContains(obj, key); + } CArrRef arr = obj->o_toArray(); int64_t res = ak_exist_string_helper(key, arr.get()); return res; @@ -4554,6 +4558,9 @@ static int64_t ak_exist_string_obj(StringData* key, ObjectData* obj) { HOT_FUNC_VM static int64_t ak_exist_int_obj(int64_t key, ObjectData* obj) { + if (obj->isCollection()) { + return collectionOffsetContains(obj, key); + } CArrRef arr = obj->o_toArray(); bool res = arr.get()->exists(key); return res; diff --git a/hphp/runtime/vm/translator/translator-x64.cpp b/hphp/runtime/vm/translator/translator-x64.cpp index c3ec1ccb9..59b61db4d 100644 --- a/hphp/runtime/vm/translator/translator-x64.cpp +++ b/hphp/runtime/vm/translator/translator-x64.cpp @@ -8215,6 +8215,9 @@ static int64_t ak_exist_int(int64_t key, ArrayData* arr) { } static int64_t ak_exist_string_obj(StringData* key, ObjectData* obj) { + if (obj->isCollection()) { + return collectionOffsetContains(obj, key); + } CArrRef arr = obj->o_toArray(); int64_t res = ak_exist_string_helper(key, arr.get()); decRefObj(obj); @@ -8223,6 +8226,9 @@ static int64_t ak_exist_string_obj(StringData* key, ObjectData* obj) { } static int64_t ak_exist_int_obj(int64_t key, ObjectData* obj) { + if (obj->isCollection()) { + return collectionOffsetContains(obj, key); + } CArrRef arr = obj->o_toArray(); bool res = arr.get()->exists(key); decRefObj(obj); diff --git a/hphp/test/slow/collection_classes/841.php b/hphp/test/slow/collection_classes/841.php new file mode 100644 index 000000000..1e951b7c7 --- /dev/null +++ b/hphp/test/slow/collection_classes/841.php @@ -0,0 +1,20 @@ + 'a', '2' => 'b'}; + var_dump(array_key_exists(1, $m)); + var_dump(array_key_exists('1', $m)); + var_dump(array_key_exists(2, $m)); + var_dump(array_key_exists('2', $m)); + var_dump(array_key_exists(3, $m)); + var_dump(array_key_exists('3', $m)); + echo "========\n"; + $x = 'array_key_exists'; + $x[0] = 'a'; + var_dump($x(1, $m)); + var_dump($x('1', $m)); + var_dump($x(2, $m)); + var_dump($x('2', $m)); + var_dump($x(3, $m)); + var_dump($x('3', $m)); +} +f(); diff --git a/hphp/test/slow/collection_classes/841.php.expect b/hphp/test/slow/collection_classes/841.php.expect new file mode 100644 index 000000000..42de964ac --- /dev/null +++ b/hphp/test/slow/collection_classes/841.php.expect @@ -0,0 +1,13 @@ +bool(true) +bool(false) +bool(false) +bool(true) +bool(false) +bool(false) +======== +bool(true) +bool(false) +bool(false) +bool(true) +bool(false) +bool(false)