| Index: runtime/vm/code_generator_x64.cc
|
| ===================================================================
|
| --- runtime/vm/code_generator_x64.cc (revision 5063)
|
| +++ runtime/vm/code_generator_x64.cc (working copy)
|
| @@ -1257,7 +1257,9 @@
|
| // All instances are of a subtype of the Object type.
|
| const Type& object_type =
|
| Type::Handle(Isolate::Current()->object_store()->object_type());
|
| - if (type.IsInstantiated() && object_type.IsSubtypeOf(type)) {
|
| + Error& malformed_error = Error::Handle();
|
| + if (type.IsInstantiated() &&
|
| + object_type.IsSubtypeOf(type, &malformed_error)) {
|
| __ PushObject(negate_result ? bool_false : bool_true);
|
| return;
|
| }
|
| @@ -1326,9 +1328,11 @@
|
| // Object is Smi.
|
| const Class& smi_class = Class::Handle(Smi::Class());
|
| // TODO(regis): We should introduce a SmiType.
|
| + Error& malformed_error = Error::Handle();
|
| if (smi_class.IsSubtypeOf(TypeArguments::Handle(),
|
| type_class,
|
| - TypeArguments::Handle())) {
|
| + TypeArguments::Handle(),
|
| + &malformed_error)) {
|
| __ PushObject(negate_result ? bool_false : bool_true);
|
| } else {
|
| __ PushObject(negate_result ? bool_true : bool_false);
|
| @@ -1359,6 +1363,9 @@
|
| }
|
| }
|
| __ PushObject(Object::ZoneHandle()); // Make room for the result.
|
| + const Immediate location =
|
| + Immediate(reinterpret_cast<int64_t>(Smi::New(token_index)));
|
| + __ pushq(location); // Push the source location.
|
| __ pushq(RAX); // Push the instance.
|
| __ PushObject(type); // Push the type.
|
| if (!type.IsInstantiated()) {
|
| @@ -1369,7 +1376,7 @@
|
| GenerateCallRuntime(node_id, token_index, kInstanceofRuntimeEntry);
|
| // Pop the two parameters supplied to the runtime entry. The result of the
|
| // instanceof runtime call will be left as the result of the operation.
|
| - __ addq(RSP, Immediate(3 * kWordSize));
|
| + __ addq(RSP, Immediate(4 * kWordSize));
|
| if (negate_result) {
|
| Label negate_done;
|
| __ popq(RDX);
|
| @@ -1411,23 +1418,6 @@
|
| ASSERT(!dst_type.IsNull());
|
| ASSERT(dst_type.IsFinalized());
|
|
|
| - // Generate throw new TypeError() if the type is malformed.
|
| - if (dst_type.IsMalformed()) {
|
| - const Error& error = Error::Handle(dst_type.malformed_error());
|
| - const String& error_message = String::ZoneHandle(
|
| - String::NewSymbol(error.ToErrorCString()));
|
| - __ PushObject(Object::ZoneHandle()); // Make room for the result.
|
| - const Immediate location =
|
| - Immediate(reinterpret_cast<int64_t>(Smi::New(token_index)));
|
| - __ pushq(location); // Push the source location.
|
| - __ pushq(RAX); // Push the source object.
|
| - __ PushObject(error_message);
|
| - GenerateCallRuntime(node_id, token_index, kMalformedTypeErrorRuntimeEntry);
|
| - // We should never return here.
|
| - __ int3();
|
| - return;
|
| - }
|
| -
|
| // Any expression is assignable to the Dynamic type and to the Object type.
|
| // Skip the test.
|
| if (dst_type.IsDynamicType() || dst_type.IsObjectType()) {
|
| @@ -1443,13 +1433,31 @@
|
| return;
|
| }
|
|
|
| - // A NULL object is always assignable and is returned as result.
|
| + // A null object is always assignable and is returned as result.
|
| const Immediate raw_null =
|
| Immediate(reinterpret_cast<intptr_t>(Object::null()));
|
| Label done, runtime_call;
|
| __ cmpq(RAX, raw_null);
|
| __ j(EQUAL, &done);
|
|
|
| + // Generate throw new TypeError() if the type is malformed.
|
| + if (dst_type.IsMalformed()) {
|
| + const Error& error = Error::Handle(dst_type.malformed_error());
|
| + const String& error_message = String::ZoneHandle(
|
| + String::NewSymbol(error.ToErrorCString()));
|
| + __ PushObject(Object::ZoneHandle()); // Make room for the result.
|
| + const Immediate location =
|
| + Immediate(reinterpret_cast<int64_t>(Smi::New(token_index)));
|
| + __ pushq(location); // Push the source location.
|
| + __ pushq(RAX); // Push the source object.
|
| + __ PushObject(dst_name); // Push the name of the destination.
|
| + __ PushObject(error_message);
|
| + GenerateCallRuntime(node_id, token_index, kMalformedTypeErrorRuntimeEntry);
|
| + // We should never return here.
|
| + __ int3();
|
| + return;
|
| + }
|
| +
|
| // If dst_type is instantiated and non-parameterized, we can inline code
|
| // checking whether the assigned instance is a Smi.
|
| if (dst_type.IsInstantiated()) {
|
| @@ -1487,9 +1495,11 @@
|
| // Object is Smi.
|
| const Class& smi_class = Class::Handle(Smi::Class());
|
| // TODO(regis): We should introduce a SmiType.
|
| + Error& malformed_error = Error::Handle();
|
| if (smi_class.IsSubtypeOf(TypeArguments::Handle(),
|
| dst_type_class,
|
| - TypeArguments::Handle())) {
|
| + TypeArguments::Handle(),
|
| + &malformed_error)) {
|
| // Successful assignable type check: return object in RAX.
|
| __ jmp(&done);
|
| } else {
|
| @@ -1506,13 +1516,14 @@
|
| } else {
|
| // However, for specific core library interfaces, we can check for
|
| // specific core library classes.
|
| + Error& malformed_error = Error::Handle();
|
| if (dst_type.IsBoolInterface()) {
|
| __ movq(RCX, FieldAddress(RAX, Object::class_offset()));
|
| const Class& bool_class = Class::ZoneHandle(
|
| Isolate::Current()->object_store()->bool_class());
|
| TestClassAndJump(bool_class, &done);
|
| } else if (dst_type.IsSubtypeOf(
|
| - Type::Handle(Type::NumberInterface()))) {
|
| + Type::Handle(Type::NumberInterface()), &malformed_error)) {
|
| __ movq(RCX, FieldAddress(RAX, Object::class_offset()));
|
| if (dst_type.IsIntInterface() || dst_type.IsNumberInterface()) {
|
| // We already checked for Smi above.
|
|
|