| OLD | NEW |
| 1 // Copyright (c) 2013, the Dart project authors. Please see the AUTHORS file | 1 // Copyright (c) 2013, 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/intermediate_language.h" | 5 #include "vm/intermediate_language.h" |
| 6 | 6 |
| 7 #include "vm/bigint_operations.h" | 7 #include "vm/bigint_operations.h" |
| 8 #include "vm/bit_vector.h" | 8 #include "vm/bit_vector.h" |
| 9 #include "vm/cpu.h" | 9 #include "vm/cpu.h" |
| 10 #include "vm/dart_entry.h" | 10 #include "vm/dart_entry.h" |
| (...skipping 11 matching lines...) Expand all Loading... |
| 22 #include "vm/scopes.h" | 22 #include "vm/scopes.h" |
| 23 #include "vm/stub_code.h" | 23 #include "vm/stub_code.h" |
| 24 #include "vm/symbols.h" | 24 #include "vm/symbols.h" |
| 25 | 25 |
| 26 #include "vm/il_printer.h" | 26 #include "vm/il_printer.h" |
| 27 | 27 |
| 28 namespace dart { | 28 namespace dart { |
| 29 | 29 |
| 30 DEFINE_FLAG(bool, propagate_ic_data, true, | 30 DEFINE_FLAG(bool, propagate_ic_data, true, |
| 31 "Propagate IC data from unoptimized to optimized IC calls."); | 31 "Propagate IC data from unoptimized to optimized IC calls."); |
| 32 DEFINE_FLAG(bool, two_args_smi_icd, true, |
| 33 "Generate special IC stubs for two args Smi operations"); |
| 32 DEFINE_FLAG(bool, unbox_numeric_fields, true, | 34 DEFINE_FLAG(bool, unbox_numeric_fields, true, |
| 33 "Support unboxed double and float32x4 fields."); | 35 "Support unboxed double and float32x4 fields."); |
| 34 DECLARE_FLAG(bool, enable_type_checks); | 36 DECLARE_FLAG(bool, enable_type_checks); |
| 35 DECLARE_FLAG(bool, eliminate_type_checks); | 37 DECLARE_FLAG(bool, eliminate_type_checks); |
| 36 DECLARE_FLAG(bool, trace_optimization); | 38 DECLARE_FLAG(bool, trace_optimization); |
| 37 DECLARE_FLAG(bool, trace_constant_propagation); | 39 DECLARE_FLAG(bool, trace_constant_propagation); |
| 38 DECLARE_FLAG(bool, throw_on_javascript_int_overflow); | 40 DECLARE_FLAG(bool, throw_on_javascript_int_overflow); |
| 39 | 41 |
| 40 Definition::Definition() | 42 Definition::Definition() |
| 41 : range_(NULL), | 43 : range_(NULL), |
| (...skipping 2183 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2225 ASSERT((kind == Token::kEQ_STRICT) || (kind == Token::kNE_STRICT)); | 2227 ASSERT((kind == Token::kEQ_STRICT) || (kind == Token::kNE_STRICT)); |
| 2226 } | 2228 } |
| 2227 | 2229 |
| 2228 | 2230 |
| 2229 LocationSummary* InstanceCallInstr::MakeLocationSummary(Isolate* isolate, | 2231 LocationSummary* InstanceCallInstr::MakeLocationSummary(Isolate* isolate, |
| 2230 bool optimizing) const { | 2232 bool optimizing) const { |
| 2231 return MakeCallSummary(); | 2233 return MakeCallSummary(); |
| 2232 } | 2234 } |
| 2233 | 2235 |
| 2234 | 2236 |
| 2237 static uword TwoArgsSmiOpInlineCacheEntry(Token::Kind kind) { |
| 2238 if (!FLAG_two_args_smi_icd) { |
| 2239 return 0; |
| 2240 } |
| 2241 StubCode* stub_code = Isolate::Current()->stub_code(); |
| 2242 switch (kind) { |
| 2243 case Token::kADD: return stub_code->SmiAddInlineCacheEntryPoint(); |
| 2244 case Token::kSUB: return stub_code->SmiSubInlineCacheEntryPoint(); |
| 2245 case Token::kEQ: return stub_code->SmiEqualInlineCacheEntryPoint(); |
| 2246 default: return 0; |
| 2247 } |
| 2248 } |
| 2249 |
| 2250 |
| 2235 void InstanceCallInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 2251 void InstanceCallInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
| 2252 Isolate* isolate = compiler->isolate(); |
| 2236 const ICData* call_ic_data = NULL; | 2253 const ICData* call_ic_data = NULL; |
| 2237 if (!FLAG_propagate_ic_data || !compiler->is_optimizing()) { | 2254 if (!FLAG_propagate_ic_data || !compiler->is_optimizing()) { |
| 2238 const Array& arguments_descriptor = | 2255 const Array& arguments_descriptor = |
| 2239 Array::Handle(ArgumentsDescriptor::New(ArgumentCount(), | 2256 Array::Handle(isolate, ArgumentsDescriptor::New(ArgumentCount(), |
| 2240 argument_names())); | 2257 argument_names())); |
| 2241 call_ic_data = compiler->GetOrAddInstanceCallICData( | 2258 call_ic_data = compiler->GetOrAddInstanceCallICData( |
| 2242 deopt_id(), function_name(), arguments_descriptor, | 2259 deopt_id(), function_name(), arguments_descriptor, |
| 2243 checked_argument_count()); | 2260 checked_argument_count()); |
| 2244 } else { | 2261 } else { |
| 2245 call_ic_data = &ICData::ZoneHandle(ic_data()->raw()); | 2262 call_ic_data = &ICData::ZoneHandle(isolate, ic_data()->raw()); |
| 2246 } | 2263 } |
| 2247 if (compiler->is_optimizing()) { | 2264 if (compiler->is_optimizing()) { |
| 2248 ASSERT(HasICData()); | 2265 ASSERT(HasICData()); |
| 2249 if (ic_data()->NumberOfChecks() > 0) { | 2266 if (ic_data()->NumberOfUsedChecks() > 0) { |
| 2250 const ICData& unary_ic_data = | 2267 const ICData& unary_ic_data = |
| 2251 ICData::ZoneHandle(ic_data()->AsUnaryClassChecks()); | 2268 ICData::ZoneHandle(isolate, ic_data()->AsUnaryClassChecks()); |
| 2252 compiler->GenerateInstanceCall(deopt_id(), | 2269 compiler->GenerateInstanceCall(deopt_id(), |
| 2253 token_pos(), | 2270 token_pos(), |
| 2254 ArgumentCount(), | 2271 ArgumentCount(), |
| 2255 locs(), | 2272 locs(), |
| 2256 unary_ic_data); | 2273 unary_ic_data); |
| 2257 } else { | 2274 } else { |
| 2258 // Call was not visited yet, use original ICData in order to populate it. | 2275 // Call was not visited yet, use original ICData in order to populate it. |
| 2259 compiler->GenerateInstanceCall(deopt_id(), | 2276 compiler->GenerateInstanceCall(deopt_id(), |
| 2260 token_pos(), | 2277 token_pos(), |
| 2261 ArgumentCount(), | 2278 ArgumentCount(), |
| 2262 locs(), | 2279 locs(), |
| 2263 *call_ic_data); | 2280 *call_ic_data); |
| 2264 } | 2281 } |
| 2265 } else { | 2282 } else { |
| 2266 // Unoptimized code. | 2283 // Unoptimized code. |
| 2267 ASSERT(!HasICData()); | 2284 ASSERT(!HasICData()); |
| 2268 compiler->AddCurrentDescriptor(RawPcDescriptors::kDeopt, | 2285 compiler->AddCurrentDescriptor(RawPcDescriptors::kDeopt, |
| 2269 deopt_id(), | 2286 deopt_id(), |
| 2270 token_pos()); | 2287 token_pos()); |
| 2271 compiler->GenerateInstanceCall(deopt_id(), | 2288 bool is_smi_two_args_op = false; |
| 2272 token_pos(), | 2289 const uword label_address = TwoArgsSmiOpInlineCacheEntry(token_kind()); |
| 2273 ArgumentCount(), | 2290 if (label_address != 0) { |
| 2274 locs(), | 2291 // We have a dedicated inline cache stub for this operation, add an |
| 2275 *call_ic_data); | 2292 // an initial Smi/Smi check with count 0. |
| 2293 ASSERT(call_ic_data->NumArgsTested() == 2); |
| 2294 const String& name = String::Handle(isolate, call_ic_data->target_name()); |
| 2295 const Class& smi_class = Class::Handle(isolate, Smi::Class()); |
| 2296 const Function& smi_op_target = |
| 2297 Function::Handle(Resolver::ResolveDynamicAnyArgs(smi_class, name)); |
| 2298 if (call_ic_data->NumberOfChecks() == 0) { |
| 2299 GrowableArray<intptr_t> class_ids(2); |
| 2300 class_ids.Add(kSmiCid); |
| 2301 class_ids.Add(kSmiCid); |
| 2302 call_ic_data->AddCheck(class_ids, smi_op_target); |
| 2303 // 'AddCheck' sets the initial count to 1. |
| 2304 call_ic_data->SetCountAt(0, 0); |
| 2305 is_smi_two_args_op = true; |
| 2306 } else if (call_ic_data->NumberOfChecks() == 1) { |
| 2307 GrowableArray<intptr_t> class_ids(2); |
| 2308 Function& target = Function::Handle(isolate); |
| 2309 call_ic_data->GetCheckAt(0, &class_ids, &target); |
| 2310 if ((target.raw() == smi_op_target.raw()) && |
| 2311 (class_ids[0] == kSmiCid) && (class_ids[1] == kSmiCid)) { |
| 2312 is_smi_two_args_op = true; |
| 2313 } |
| 2314 } |
| 2315 } |
| 2316 if (is_smi_two_args_op) { |
| 2317 ASSERT(ArgumentCount() == 2); |
| 2318 ExternalLabel target_label(label_address); |
| 2319 compiler->EmitInstanceCall(&target_label, *call_ic_data, ArgumentCount(), |
| 2320 deopt_id(), token_pos(), locs()); |
| 2321 } else { |
| 2322 compiler->GenerateInstanceCall(deopt_id(), |
| 2323 token_pos(), |
| 2324 ArgumentCount(), |
| 2325 locs(), |
| 2326 *call_ic_data); |
| 2327 } |
| 2276 } | 2328 } |
| 2277 } | 2329 } |
| 2278 | 2330 |
| 2279 | 2331 |
| 2280 bool PolymorphicInstanceCallInstr::HasSingleRecognizedTarget() const { | 2332 bool PolymorphicInstanceCallInstr::HasSingleRecognizedTarget() const { |
| 2281 return ic_data().HasOneTarget() && | 2333 return ic_data().HasOneTarget() && |
| 2282 (MethodRecognizer::RecognizeKind( | 2334 (MethodRecognizer::RecognizeKind( |
| 2283 Function::Handle(ic_data().GetTargetAt(0))) != | 2335 Function::Handle(ic_data().GetTargetAt(0))) != |
| 2284 MethodRecognizer::kUnknown); | 2336 MethodRecognizer::kUnknown); |
| 2285 } | 2337 } |
| (...skipping 523 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2809 case Token::kTRUNCDIV: return 0; | 2861 case Token::kTRUNCDIV: return 0; |
| 2810 case Token::kMOD: return 1; | 2862 case Token::kMOD: return 1; |
| 2811 default: UNIMPLEMENTED(); return -1; | 2863 default: UNIMPLEMENTED(); return -1; |
| 2812 } | 2864 } |
| 2813 } | 2865 } |
| 2814 | 2866 |
| 2815 | 2867 |
| 2816 #undef __ | 2868 #undef __ |
| 2817 | 2869 |
| 2818 } // namespace dart | 2870 } // namespace dart |
| OLD | NEW |