Chromium Code Reviews| Index: vm/dart_api_impl.cc |
| =================================================================== |
| --- vm/dart_api_impl.cc (revision 849) |
| +++ vm/dart_api_impl.cc (working copy) |
| @@ -853,7 +853,18 @@ |
| Zone zone; // Setup a VM zone as we are creating some handles. |
| HandleScope scope; // Setup a VM handle scope. |
| const Object& obj = Object::Handle(Api::UnwrapHandle(object)); |
| - return obj.IsArray(); |
| + if (obj.IsArray()) { |
| + return true; |
| + } |
| + // TODO(5526318): Make access to GrowableObjectArray more efficient. |
| + if (obj.IsInstance()) { |
|
Mads Ager (google)
2011/10/28 07:50:18
Maybe extract this into an ImplementsListInterface
siva
2011/10/31 20:30:49
Done.
|
| + Instance& instance = Instance::Handle(); |
| + instance ^= obj.raw(); |
| + Isolate* isolate = Isolate::Current(); |
| + const Type& type = Type::Handle(isolate->object_store()->list_interface()); |
| + return instance.Is(type); |
|
turnidge
2011/10/27 21:29:46
A thought. Given that all of the other Is*() func
siva
2011/10/31 20:30:49
Regis and I discussed this, he felt that the only
|
| + } |
| + return false; |
| } |
| @@ -875,10 +886,93 @@ |
| *len = array_obj.Length(); |
| return Api::Success(); |
| } |
| - return Api::Error("Object is not an Array"); |
| + // TODO(5526318): Make access to GrowableObjectArray more efficient. |
| + // Now check and handle a dart object that implements the List interface. |
| + if (obj.IsInstance()) { |
| + Instance& instance = Instance::Handle(); |
| + instance ^= obj.raw(); |
| + Isolate* isolate = Isolate::Current(); |
| + ASSERT(isolate != NULL); |
| + const Type& type = Type::Handle(isolate->object_store()->list_interface()); |
| + if (instance.Is(type)) { |
| + String& name = String::Handle(String::New("length")); |
| + name = Field::GetterName(name); |
| + const Function& function = Function::Handle( |
| + Resolver::ResolveDynamic(instance, name, 1, 0)); |
| + if (!function.IsNull()) { |
| + GrowableArray<const Object*> args(0); |
| + LongJump* base = isolate->long_jump_base(); |
| + LongJump jump; |
| + isolate->set_long_jump_base(&jump); |
| + Dart_Handle result; |
| + if (setjmp(*jump.Set()) == 0) { |
| + const Array& kNoArgumentNames = Array::Handle(); |
| + const Instance& retval = Instance::Handle( |
| + DartEntry::InvokeDynamic(instance, |
| + function, |
| + args, |
| + kNoArgumentNames)); |
| + result = Api::Success(); |
| + if (retval.IsSmi() || retval.IsMint()) { |
| + Integer& integer = Integer::Handle(); |
| + integer ^= retval.raw(); |
| + *len = integer.AsInt64Value(); |
| + } else if (retval.IsBigint()) { |
| + Bigint& bigint = Bigint::Handle(); |
| + bigint ^= retval.raw(); |
| + if (BigintOperations::FitsIntoInt64(bigint)) { |
| + *len = BigintOperations::ToInt64(bigint); |
| + } else { |
| + result = Api::Error("Object has an Invalid length"); |
|
turnidge
2011/10/27 21:29:46
Is it possible to create a List at the Dart level
siva
2011/10/31 20:30:49
Yes it is possible that an arbitrary List implemen
|
| + } |
| + } else { |
| + result = Api::Error("Object has an Invalid length"); |
|
turnidge
2011/10/27 21:29:46
Invalid -> "non-integer"?
siva
2011/10/31 20:30:49
Done.
|
| + } |
| + } else { |
| + SetupErrorResult(&result); |
| + } |
| + isolate->set_long_jump_base(base); |
| + return result; |
| + } |
| + } |
| + } |
| + return Api::Error("Object does not implement the list inteface"); |
| } |
| +static RawObject* GetArrayAt(const Instance& instance, |
| + const Integer& index, |
| + const Function& function, |
| + Dart_Handle* result) { |
| + Isolate* isolate = Isolate::Current(); |
| + ASSERT(isolate != NULL); |
| + ASSERT(result != NULL); |
| + LongJump* base = isolate->long_jump_base(); |
|
Mads Ager (google)
2011/10/28 07:50:18
Maybe a scoped object would be nice for this at so
siva
2011/10/31 20:30:49
Yes Todd had indicated the same thing, he is going
|
| + LongJump jump; |
| + isolate->set_long_jump_base(&jump); |
| + if (setjmp(*jump.Set()) == 0) { |
| + Instance& retval = Instance::Handle(); |
| + GrowableArray<const Object*> args(0); |
| + args.Add(&index); |
| + const Array& kNoArgumentNames = Array::Handle(); |
| + retval = DartEntry::InvokeDynamic(instance, |
| + function, |
| + args, |
| + kNoArgumentNames); |
| + if (retval.IsUnhandledException()) { |
| + *result = Api::Error("Invalid implementation of '[]'"); |
|
turnidge
2011/10/27 21:29:46
What do you think of a more informative error mess
siva
2011/10/31 20:30:49
Done.
|
| + } else { |
| + *result = Api::Success(); |
| + } |
| + isolate->set_long_jump_base(base); |
| + return retval.raw(); |
| + } |
| + SetupErrorResult(result); |
| + isolate->set_long_jump_base(base); |
| + return Object::null(); |
| +} |
| + |
| + |
| DART_EXPORT Dart_Handle Dart_ArrayGet(Dart_Handle array, |
| intptr_t offset, |
| uint8_t* native_array, |
| @@ -904,7 +998,39 @@ |
| } |
| return Api::Error("Invalid length passed in to access array elements"); |
| } |
| - return Api::Error("Object is not an Array"); |
| + // TODO(5526318): Make access to GrowableObjectArray more efficient. |
| + // Now check and handle a dart object that implements the List interface. |
| + if (obj.IsInstance()) { |
| + Instance& instance = Instance::Handle(); |
| + instance ^= obj.raw(); |
| + Isolate* isolate = Isolate::Current(); |
| + ASSERT(isolate != NULL); |
| + const Type& type = Type::Handle(isolate->object_store()->list_interface()); |
| + if (instance.Is(type)) { |
| + String& name = String::Handle(String::New("[]")); |
|
turnidge
2011/10/27 21:29:46
An aside: it will be nice when we can start using
siva
2011/10/31 20:30:49
Agree, there is a TODO somewhere in the VM code fo
|
| + const Function& function = Function::Handle( |
| + Resolver::ResolveDynamic(instance, name, 2, 0)); |
| + if (!function.IsNull()) { |
| + Object& element = Object::Handle(); |
| + Integer& intobj = Integer::Handle(); |
| + Dart_Handle result; |
| + for (int i = 0; i < length; i++) { |
| + intobj = Integer::New(offset + i); |
| + element = GetArrayAt(instance, intobj, function, &result); |
| + if (!Dart_IsValid(result)) { |
| + return result; // Error condition. |
| + } |
| + intobj ^= element.raw(); |
| + ASSERT(intobj.AsInt64Value() <= 0xff); |
| + // TODO(hpayer): value should always be smaller then 0xff. Add error |
| + // handling. |
| + native_array[i] = static_cast<uint8_t>(intobj.AsInt64Value() & 0xff); |
| + } |
| + return Api::Success(); |
| + } |
| + } |
| + } |
| + return Api::Error("Object does not implement the List interface"); |
| } |
| @@ -921,10 +1047,68 @@ |
| } |
| return Api::Error("Invalid index passed in to access array element"); |
| } |
| + // TODO(5526318): Make access to GrowableObjectArray more efficient. |
| + // Now check and handle a dart object that implements the List interface. |
| + if (obj.IsInstance()) { |
| + Instance& instance = Instance::Handle(); |
| + instance ^= obj.raw(); |
| + Isolate* isolate = Isolate::Current(); |
| + ASSERT(isolate != NULL); |
| + const Type& type = Type::Handle(isolate->object_store()->list_interface()); |
| + if (instance.Is(type)) { |
| + String& name = String::Handle(String::New("[]")); |
| + const Function& function = Function::Handle( |
| + Resolver::ResolveDynamic(instance, name, 2, 0)); |
| + if (!function.IsNull()) { |
| + Object& element = Object::Handle(); |
| + Integer& indexobj = Integer::Handle(); |
| + Dart_Handle result; |
| + indexobj = Integer::New(index); |
| + element = GetArrayAt(instance, indexobj, function, &result); |
| + if (!Dart_IsValid(result)) { |
| + return result; // Error condition. |
| + } |
| + return Api::NewLocalHandle(element); |
| + } |
| + } |
| + } |
| return Api::Error("Object is not an Array"); |
|
turnidge
2011/10/27 21:29:46
Inconsistent w/ error msg above -> "Object does no
siva
2011/10/31 20:30:49
Done.
|
| } |
| +static void SetArrayAt(const Instance& instance, |
| + const Integer& index, |
| + const Object& value, |
| + const Function& function, |
| + Dart_Handle* result) { |
| + Isolate* isolate = Isolate::Current(); |
| + ASSERT(isolate != NULL); |
| + ASSERT(result != NULL); |
| + LongJump* base = isolate->long_jump_base(); |
| + LongJump jump; |
| + isolate->set_long_jump_base(&jump); |
| + if (setjmp(*jump.Set()) == 0) { |
| + GrowableArray<const Object*> args(1); |
| + args.Add(&index); |
| + args.Add(&value); |
| + Instance& retval = Instance::Handle(); |
| + const Array& kNoArgumentNames = Array::Handle(); |
| + retval = DartEntry::InvokeDynamic(instance, |
| + function, |
| + args, |
| + kNoArgumentNames); |
| + if (retval.IsUnhandledException()) { |
| + *result = Api::Error("Invalid implementation of '[]='"); |
|
turnidge
2011/10/27 21:29:46
Maybe different error msg here?
siva
2011/10/31 20:30:49
Done.
|
| + } else { |
| + *result = Api::Success(); |
| + } |
| + } else { |
| + SetupErrorResult(result); |
| + } |
| + isolate->set_long_jump_base(base); |
| +} |
| + |
| + |
| DART_EXPORT Dart_Handle Dart_ArraySet(Dart_Handle array, |
| intptr_t offset, |
| uint8_t* native_array, |
| @@ -945,9 +1129,38 @@ |
| } |
| return Api::Error("Invalid length passed in to set array elements"); |
| } |
| - return Api::Error("Object is not an Array"); |
| + // TODO(5526318): Make access to GrowableObjectArray more efficient. |
| + // Now check and handle a dart object that implements the List interface. |
| + if (obj.IsInstance()) { |
| + Instance& instance = Instance::Handle(); |
| + instance ^= obj.raw(); |
| + Isolate* isolate = Isolate::Current(); |
| + ASSERT(isolate != NULL); |
| + const Type& type = Type::Handle(isolate->object_store()->list_interface()); |
|
turnidge
2011/10/27 21:29:46
We are checking whether an object is a list many t
siva
2011/10/31 20:30:49
Done.
|
| + if (instance.Is(type)) { |
| + String& name = String::Handle(String::New("[]=")); |
| + const Function& function = Function::Handle( |
| + Resolver::ResolveDynamic(instance, name, 3, 0)); |
| + if (!function.IsNull()) { |
| + Integer& indexobj = Integer::Handle(); |
| + Integer& valueobj = Integer::Handle(); |
| + Dart_Handle result; |
| + for (int i = 0; i < length; i++) { |
| + indexobj = Integer::New(offset + i); |
| + valueobj ^= Integer::New(native_array[i]); |
| + SetArrayAt(instance, indexobj, valueobj, function, &result); |
| + if (!Dart_IsValid(result)) { |
| + return result; // Error condition. |
| + } |
| + } |
| + return Api::Success(); |
| + } |
| + } |
| + } |
| + return Api::Error("Object does not implement the list interface"); |
| } |
| + |
| DART_EXPORT Dart_Handle Dart_ArraySetAt(Dart_Handle array, |
| intptr_t index, |
| Dart_Handle value) { |
| @@ -964,7 +1177,28 @@ |
| } |
| return Api::Error("Invalid index passed in to set array element"); |
| } |
| - return Api::Error("Object is not an Array"); |
| + // TODO(5526318): Make access to GrowableObjectArray more efficient. |
| + // Now check and handle a dart object that implements the List interface. |
| + if (obj.IsInstance()) { |
| + Instance& instance = Instance::Handle(); |
| + instance ^= obj.raw(); |
| + Isolate* isolate = Isolate::Current(); |
| + ASSERT(isolate != NULL); |
| + const Type& type = Type::Handle(isolate->object_store()->list_interface()); |
| + if (instance.Is(type)) { |
| + String& name = String::Handle(String::New("[]=")); |
| + const Function& function = Function::Handle( |
| + Resolver::ResolveDynamic(instance, name, 3, 0)); |
| + if (!function.IsNull()) { |
| + Dart_Handle result; |
| + const Integer& index_obj = Integer::Handle(Integer::New(index)); |
| + const Object& value_obj = Object::Handle(Api::UnwrapHandle(value)); |
| + SetArrayAt(instance, index_obj, value_obj, function, &result); |
| + return result; |
| + } |
| + } |
| + } |
| + return Api::Error("Object does not implement the list interface"); |
| } |