OLD | NEW |
1 // Copyright (c) 2011, the Dart project authors. Please see the AUTHORS file | 1 // Copyright (c) 2011, the Dart project authors. Please see the AUTHORS file |
2 // for details. All rights reserved. Use of this source code is governed by a | 2 // for details. All rights reserved. Use of this source code is governed by a |
3 // BSD-style license that can be found in the LICENSE file. | 3 // BSD-style license that can be found in the LICENSE file. |
4 | 4 |
5 #include "vm/bootstrap_natives.h" | 5 #include "vm/bootstrap_natives.h" |
6 | 6 |
7 #include "lib/invocation_mirror.h" | 7 #include "lib/invocation_mirror.h" |
| 8 #include "vm/code_patcher.h" |
8 #include "vm/exceptions.h" | 9 #include "vm/exceptions.h" |
9 #include "vm/heap.h" | 10 #include "vm/heap.h" |
10 #include "vm/native_entry.h" | 11 #include "vm/native_entry.h" |
11 #include "vm/object.h" | 12 #include "vm/object.h" |
12 #include "vm/stack_frame.h" | 13 #include "vm/stack_frame.h" |
13 #include "vm/symbols.h" | 14 #include "vm/symbols.h" |
14 | 15 |
15 namespace dart { | 16 namespace dart { |
16 | 17 |
17 DECLARE_FLAG(bool, enable_type_checks); | 18 DECLARE_FLAG(bool, enable_type_checks); |
18 DECLARE_FLAG(bool, trace_type_checks); | 19 DECLARE_FLAG(bool, trace_type_checks); |
| 20 DECLARE_FLAG(bool, warn_on_javascript_compatibility); |
19 | 21 |
20 | 22 |
21 DEFINE_NATIVE_ENTRY(Object_equals, 1) { | 23 DEFINE_NATIVE_ENTRY(Object_equals, 1) { |
22 // Implemented in the flow graph builder. | 24 // Implemented in the flow graph builder. |
23 UNREACHABLE(); | 25 UNREACHABLE(); |
24 return Object::null(); | 26 return Object::null(); |
25 } | 27 } |
26 | 28 |
27 | 29 |
28 DEFINE_NATIVE_ENTRY(Object_cid, 1) { | 30 DEFINE_NATIVE_ENTRY(Object_cid, 1) { |
(...skipping 73 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
102 | 104 |
103 | 105 |
104 DEFINE_NATIVE_ENTRY(Object_runtimeType, 1) { | 106 DEFINE_NATIVE_ENTRY(Object_runtimeType, 1) { |
105 const Instance& instance = Instance::CheckedHandle(arguments->NativeArgAt(0)); | 107 const Instance& instance = Instance::CheckedHandle(arguments->NativeArgAt(0)); |
106 // Special handling for following types outside this native. | 108 // Special handling for following types outside this native. |
107 ASSERT(!instance.IsString() && !instance.IsInteger() && !instance.IsDouble()); | 109 ASSERT(!instance.IsString() && !instance.IsInteger() && !instance.IsDouble()); |
108 return instance.GetType(); | 110 return instance.GetType(); |
109 } | 111 } |
110 | 112 |
111 | 113 |
| 114 static void JSWarning(const char* msg) { |
| 115 DartFrameIterator iterator; |
| 116 iterator.NextFrame(); // Skip native call. |
| 117 StackFrame* caller_frame = iterator.NextFrame(); |
| 118 ASSERT(caller_frame != NULL); |
| 119 const Code& caller_code = Code::Handle(caller_frame->LookupDartCode()); |
| 120 ASSERT(!caller_code.IsNull()); |
| 121 const uword caller_pc = caller_frame->pc(); |
| 122 // Assume an instance call. |
| 123 ICData& ic_data = ICData::Handle(); |
| 124 CodePatcher::GetInstanceCallAt(caller_pc, caller_code, &ic_data); |
| 125 ASSERT(!ic_data.IsNull()); |
| 126 // Report warning only if not already reported at this location. |
| 127 if (!ic_data.IssuedJSWarning()) { |
| 128 ic_data.SetIssuedJSWarning(); |
| 129 Exceptions::JSWarning(caller_frame, "%s", msg); |
| 130 } |
| 131 } |
| 132 |
| 133 |
| 134 static void WarnOnJSIntegralNumTypeTest( |
| 135 const Instance& instance, |
| 136 const TypeArguments& instantiator_type_arguments, |
| 137 const AbstractType& type) { |
| 138 const bool instance_is_int = instance.IsInteger(); |
| 139 const bool instance_is_double = instance.IsDouble(); |
| 140 if (!(instance_is_int || instance_is_double)) { |
| 141 return; |
| 142 } |
| 143 AbstractType& instantiated_type = AbstractType::Handle(type.raw()); |
| 144 if (!type.IsInstantiated()) { |
| 145 instantiated_type = type.InstantiateFrom(instantiator_type_arguments, NULL); |
| 146 } |
| 147 if (instance_is_double) { |
| 148 if (instantiated_type.IsIntType()) { |
| 149 const double value = Double::Cast(instance).value(); |
| 150 if (floor(value) == value) { |
| 151 JSWarning("integral value of type 'double' is also considered to be " |
| 152 "of type 'int'"); |
| 153 } |
| 154 } |
| 155 } else { |
| 156 ASSERT(instance_is_int); |
| 157 if (instantiated_type.IsDoubleType()) { |
| 158 JSWarning("integer value is also considered to be of type 'double'"); |
| 159 } |
| 160 } |
| 161 } |
| 162 |
| 163 |
112 DEFINE_NATIVE_ENTRY(Object_instanceOf, 5) { | 164 DEFINE_NATIVE_ENTRY(Object_instanceOf, 5) { |
113 const Instance& instance = Instance::CheckedHandle(arguments->NativeArgAt(0)); | 165 const Instance& instance = Instance::CheckedHandle(arguments->NativeArgAt(0)); |
114 // Instantiator at position 1 is not used. It is passed along so that the call | 166 // Instantiator at position 1 is not used. It is passed along so that the call |
115 // can be easily converted to an optimized implementation. Instantiator is | 167 // can be easily converted to an optimized implementation. Instantiator is |
116 // used to populate the subtype cache. | 168 // used to populate the subtype cache. |
117 const TypeArguments& instantiator_type_arguments = | 169 const TypeArguments& instantiator_type_arguments = |
118 TypeArguments::CheckedHandle(arguments->NativeArgAt(2)); | 170 TypeArguments::CheckedHandle(arguments->NativeArgAt(2)); |
119 const AbstractType& type = | 171 const AbstractType& type = |
120 AbstractType::CheckedHandle(arguments->NativeArgAt(3)); | 172 AbstractType::CheckedHandle(arguments->NativeArgAt(3)); |
121 const Bool& negate = Bool::CheckedHandle(arguments->NativeArgAt(4)); | 173 const Bool& negate = Bool::CheckedHandle(arguments->NativeArgAt(4)); |
122 ASSERT(type.IsFinalized()); | 174 ASSERT(type.IsFinalized()); |
123 ASSERT(!type.IsMalformed()); | 175 ASSERT(!type.IsMalformed()); |
124 ASSERT(!type.IsMalbounded()); | 176 ASSERT(!type.IsMalbounded()); |
| 177 |
| 178 // Check for javascript compatibility. |
| 179 if (FLAG_warn_on_javascript_compatibility) { |
| 180 WarnOnJSIntegralNumTypeTest(instance, instantiator_type_arguments, type); |
| 181 } |
| 182 |
125 Error& bound_error = Error::Handle(); | 183 Error& bound_error = Error::Handle(); |
126 const bool is_instance_of = instance.IsInstanceOf(type, | 184 const bool is_instance_of = instance.IsInstanceOf(type, |
127 instantiator_type_arguments, | 185 instantiator_type_arguments, |
128 &bound_error); | 186 &bound_error); |
129 if (FLAG_trace_type_checks) { | 187 if (FLAG_trace_type_checks) { |
130 const char* result_str = is_instance_of ? "true" : "false"; | 188 const char* result_str = is_instance_of ? "true" : "false"; |
131 OS::Print("Native Object.instanceOf: result %s\n", result_str); | 189 OS::Print("Native Object.instanceOf: result %s\n", result_str); |
132 const Type& instance_type = Type::Handle(instance.GetType()); | 190 const Type& instance_type = Type::Handle(instance.GetType()); |
133 OS::Print(" instance type: %s\n", | 191 OS::Print(" instance type: %s\n", |
134 String::Handle(instance_type.Name()).ToCString()); | 192 String::Handle(instance_type.Name()).ToCString()); |
(...skipping 28 matching lines...) Expand all Loading... |
163 TypeArguments::CheckedHandle(arguments->NativeArgAt(2)); | 221 TypeArguments::CheckedHandle(arguments->NativeArgAt(2)); |
164 const AbstractType& type = | 222 const AbstractType& type = |
165 AbstractType::CheckedHandle(arguments->NativeArgAt(3)); | 223 AbstractType::CheckedHandle(arguments->NativeArgAt(3)); |
166 ASSERT(type.IsFinalized()); | 224 ASSERT(type.IsFinalized()); |
167 ASSERT(!type.IsMalformed()); | 225 ASSERT(!type.IsMalformed()); |
168 ASSERT(!type.IsMalbounded()); | 226 ASSERT(!type.IsMalbounded()); |
169 Error& bound_error = Error::Handle(); | 227 Error& bound_error = Error::Handle(); |
170 if (instance.IsNull()) { | 228 if (instance.IsNull()) { |
171 return instance.raw(); | 229 return instance.raw(); |
172 } | 230 } |
| 231 |
| 232 // Check for javascript compatibility. |
| 233 if (FLAG_warn_on_javascript_compatibility) { |
| 234 WarnOnJSIntegralNumTypeTest(instance, instantiator_type_arguments, type); |
| 235 } |
| 236 |
173 const bool is_instance_of = instance.IsInstanceOf(type, | 237 const bool is_instance_of = instance.IsInstanceOf(type, |
174 instantiator_type_arguments, | 238 instantiator_type_arguments, |
175 &bound_error); | 239 &bound_error); |
176 if (FLAG_trace_type_checks) { | 240 if (FLAG_trace_type_checks) { |
177 const char* result_str = is_instance_of ? "true" : "false"; | 241 const char* result_str = is_instance_of ? "true" : "false"; |
178 OS::Print("Object.as: result %s\n", result_str); | 242 OS::Print("Object.as: result %s\n", result_str); |
179 const Type& instance_type = Type::Handle(instance.GetType()); | 243 const Type& instance_type = Type::Handle(instance.GetType()); |
180 OS::Print(" instance type: %s\n", | 244 OS::Print(" instance type: %s\n", |
181 String::Handle(instance_type.Name()).ToCString()); | 245 String::Handle(instance_type.Name()).ToCString()); |
182 OS::Print(" cast type: %s\n", String::Handle(type.Name()).ToCString()); | 246 OS::Print(" cast type: %s\n", String::Handle(type.Name()).ToCString()); |
(...skipping 49 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
232 | 296 |
233 | 297 |
234 DEFINE_NATIVE_ENTRY(LibraryPrefix_load, 1) { | 298 DEFINE_NATIVE_ENTRY(LibraryPrefix_load, 1) { |
235 const LibraryPrefix& prefix = | 299 const LibraryPrefix& prefix = |
236 LibraryPrefix::CheckedHandle(arguments->NativeArgAt(0)); | 300 LibraryPrefix::CheckedHandle(arguments->NativeArgAt(0)); |
237 prefix.LoadLibrary(); | 301 prefix.LoadLibrary(); |
238 return Bool::Get(true).raw(); | 302 return Bool::Get(true).raw(); |
239 } | 303 } |
240 | 304 |
241 } // namespace dart | 305 } // namespace dart |
OLD | NEW |