Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(842)

Side by Side Diff: runtime/vm/intrinsifier.cc

Issue 513213002: Generate some intrinsics using our IR. (Closed) Base URL: http://dart.googlecode.com/svn/branches/bleeding_edge/dart/
Patch Set: addressed comments Created 6 years, 3 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
OLDNEW
1 // Copyright (c) 2012, the Dart project authors. Please see the AUTHORS file 1 // Copyright (c) 2012, 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 // Class for intrinsifying functions. 4 // Class for intrinsifying functions.
5 5
6 #include "vm/assembler.h" 6 #include "vm/assembler.h"
7 #include "vm/intrinsifier.h" 7 #include "vm/intrinsifier.h"
8 #include "vm/flags.h" 8 #include "vm/flags.h"
9 #include "vm/object.h" 9 #include "vm/object.h"
10 #include "vm/symbols.h" 10 #include "vm/symbols.h"
11 11
12 #include "vm/flow_graph.h"
13 #include "vm/flow_graph_compiler.h"
14 #include "vm/flow_graph_allocator.h"
15 #include "vm/flow_graph_builder.h"
16 #include "vm/il_printer.h"
17 #include "vm/intermediate_language.h"
18 #include "vm/parser.h"
19
12 namespace dart { 20 namespace dart {
13 21
14 DEFINE_FLAG(bool, intrinsify, true, "Instrinsify when possible"); 22 DEFINE_FLAG(bool, intrinsify, true, "Instrinsify when possible");
15 DECLARE_FLAG(bool, throw_on_javascript_int_overflow); 23 DECLARE_FLAG(bool, throw_on_javascript_int_overflow);
24 DECLARE_FLAG(bool, code_comments);
25 DECLARE_FLAG(bool, print_flow_graph);
26 DECLARE_FLAG(bool, print_flow_graph_optimized);
16 27
17 bool Intrinsifier::CanIntrinsify(const Function& function) { 28 bool Intrinsifier::CanIntrinsify(const Function& function) {
18 if (!FLAG_intrinsify) return false; 29 if (!FLAG_intrinsify) return false;
19 if (function.IsClosureFunction()) return false; 30 if (function.IsClosureFunction()) return false;
20 // Can occur because of compile-all flag. 31 // Can occur because of compile-all flag.
21 if (function.is_external()) return false; 32 if (function.is_external()) return false;
22 return function.is_intrinsic(); 33 return function.is_intrinsic();
23 } 34 }
24 35
25 36
(...skipping 26 matching lines...) Expand all
52 func = cls.LookupFunctionAllowPrivate(str); \ 63 func = cls.LookupFunctionAllowPrivate(str); \
53 } \ 64 } \
54 ASSERT(!func.IsNull()); \ 65 ASSERT(!func.IsNull()); \
55 func.set_is_intrinsic(true); 66 func.set_is_intrinsic(true);
56 67
57 // Set up all core lib functions that can be intrisified. 68 // Set up all core lib functions that can be intrisified.
58 lib = Library::CoreLibrary(); 69 lib = Library::CoreLibrary();
59 ASSERT(!lib.IsNull()); 70 ASSERT(!lib.IsNull());
60 CORE_LIB_INTRINSIC_LIST(SETUP_FUNCTION); 71 CORE_LIB_INTRINSIC_LIST(SETUP_FUNCTION);
61 CORE_INTEGER_LIB_INTRINSIC_LIST(SETUP_FUNCTION); 72 CORE_INTEGER_LIB_INTRINSIC_LIST(SETUP_FUNCTION);
73 GRAPH_CORE_INTRINSICS_LIST(SETUP_FUNCTION);
62 74
63 // Set up all math lib functions that can be intrisified. 75 // Set up all math lib functions that can be intrisified.
64 lib = Library::MathLibrary(); 76 lib = Library::MathLibrary();
65 ASSERT(!lib.IsNull()); 77 ASSERT(!lib.IsNull());
66 MATH_LIB_INTRINSIC_LIST(SETUP_FUNCTION); 78 MATH_LIB_INTRINSIC_LIST(SETUP_FUNCTION);
67 79
68 // Set up all dart:typed_data lib functions that can be intrisified. 80 // Set up all dart:typed_data lib functions that can be intrisified.
69 lib = Library::TypedDataLibrary(); 81 lib = Library::TypedDataLibrary();
70 ASSERT(!lib.IsNull()); 82 ASSERT(!lib.IsNull());
71 TYPED_DATA_LIB_INTRINSIC_LIST(SETUP_FUNCTION); 83 TYPED_DATA_LIB_INTRINSIC_LIST(SETUP_FUNCTION);
84 GRAPH_TYPED_DATA_INTRINSICS_LIST(SETUP_FUNCTION);
72 85
73 // Setup all dart:profiler lib functions that can be intrinsified. 86 // Setup all dart:profiler lib functions that can be intrinsified.
74 lib = Library::ProfilerLibrary(); 87 lib = Library::ProfilerLibrary();
75 ASSERT(!lib.IsNull()); 88 ASSERT(!lib.IsNull());
76 PROFILER_LIB_INTRINSIC_LIST(SETUP_FUNCTION); 89 PROFILER_LIB_INTRINSIC_LIST(SETUP_FUNCTION);
77 90
78 #undef SETUP_FUNCTION 91 #undef SETUP_FUNCTION
79 } 92 }
80 93
81 94
82 void Intrinsifier::Intrinsify(const Function& function, Assembler* assembler) { 95 static void EmitCodeFor(FlowGraphCompiler* compiler,
83 if (!CanIntrinsify(function)) return; 96 FlowGraph* graph) {
srdjan 2014/09/08 17:34:07 Maybe briefly document why 'graph' is not the same
Florian Schneider 2014/09/09 09:57:08 Agree, I need it only for emitting code (assembler
97 compiler->assembler()->Comment("Graph intrinsic");
98 for (intptr_t i = 0; i < graph->reverse_postorder().length(); i++) {
99 BlockEntryInstr* block = graph->reverse_postorder()[i];
100 if (block->IsGraphEntry()) continue; // No code for graph entry needed.
101 for (ForwardInstructionIterator it(block); !it.Done(); it.Advance()) {
102 Instruction* instr = it.Current();
103 if (FLAG_code_comments) compiler->EmitComment(instr);
104 if (instr->IsParallelMove()) {
105 compiler->parallel_move_resolver()->EmitNativeCode(
106 instr->AsParallelMove());
107 } else {
108 ASSERT(instr->locs() != NULL);
109 // Calls are not supported in intrinsics code.
110 ASSERT(!instr->locs()->always_calls());
111 instr->EmitNativeCode(compiler);
112 }
113 }
114 }
115 }
116
117
118 bool Intrinsifier::GraphIntrinsify(const ParsedFunction& parsed_function,
119 FlowGraphCompiler* compiler) {
120 ZoneGrowableArray<const ICData*>* ic_data_array =
121 new ZoneGrowableArray<const ICData*>();
122 FlowGraphBuilder builder(const_cast<ParsedFunction*>(&parsed_function),
srdjan 2014/09/08 17:34:07 I feel this is dangerous (removing const-ness from
Florian Schneider 2014/09/09 09:57:08 Done. That was only temporary, anyway. We have a m
123 *ic_data_array,
124 NULL, // NULL = not inlining.
125 -1); // No OSR id.
srdjan 2014/09/08 17:34:07 Use Isolate::kNoDeoptId.
Florian Schneider 2014/09/09 09:57:08 Done.
126
127 intptr_t block_id = builder.AllocateBlockId();
128 TargetEntryInstr* normal_entry =
129 new TargetEntryInstr(block_id,
130 CatchClauseNode::kInvalidTryIndex);
131 GraphEntryInstr* graph_entry = new GraphEntryInstr(
132 &parsed_function, normal_entry, -1); // No OSR id.
133 FlowGraph* graph = new FlowGraph(builder, graph_entry, block_id);
134 const Function& function = parsed_function.function();
135 switch (function.recognized_kind()) {
136 #define EMIT_CASE(test_class_name, test_function_name, enum_name, fp) \
137 case MethodRecognizer::k##enum_name: \
138 ASSERT(function.CheckSourceFingerprint(fp)); \
139 if (!Build_##enum_name(graph)) return false; \
140 break;
141
142 GRAPH_INTRINSICS_LIST(EMIT_CASE);
143 default:
144 return false;
145 #undef EMIT_CASE
146 }
147
148 if (FLAG_print_flow_graph || FLAG_print_flow_graph_optimized) {
149 OS::Print("Intrinsic graph before\n");
150 FlowGraphPrinter printer(*graph);
151 printer.PrintBlocks();
152 }
153
154 // Perform register allocation on the SSA graph.
155 FlowGraphAllocator allocator(*graph, true); // Intrinsic mode.
156 allocator.AllocateRegisters();
157
158 if (FLAG_print_flow_graph || FLAG_print_flow_graph_optimized) {
159 OS::Print("Intrinsic graph after\n");
160 FlowGraphPrinter printer(*graph);
161 printer.PrintBlocks();
162 }
163 EmitCodeFor(compiler, graph);
164 return true;
165 }
166
167
168 void Intrinsifier::Intrinsify(const ParsedFunction& parsed_function,
169 FlowGraphCompiler* compiler) {
170 const Function& function = parsed_function.function();
171 if (!CanIntrinsify(function)) {
172 return;
173 }
174
175 if (GraphIntrinsify(parsed_function, compiler)) {
176 return;
177 }
84 178
85 #define EMIT_CASE(test_class_name, test_function_name, enum_name, fp) \ 179 #define EMIT_CASE(test_class_name, test_function_name, enum_name, fp) \
86 case MethodRecognizer::k##enum_name: \ 180 case MethodRecognizer::k##enum_name: \
87 ASSERT(function.CheckSourceFingerprint(fp)); \ 181 ASSERT(function.CheckSourceFingerprint(fp)); \
88 assembler->Comment("Intrinsic"); \ 182 compiler->assembler()->Comment("Intrinsic"); \
89 enum_name(assembler); \ 183 enum_name(compiler->assembler()); \
90 break; 184 break;
91 185
92 if (FLAG_throw_on_javascript_int_overflow && (Smi::kBits >= 32)) { 186 if (FLAG_throw_on_javascript_int_overflow && (Smi::kBits >= 32)) {
93 // Integer intrinsics are in the core library, but we don't want to 187 // Integer intrinsics are in the core library, but we don't want to
94 // intrinsify when Smi > 32 bits if we are looking for javascript integer 188 // intrinsify when Smi > 32 bits if we are looking for javascript integer
95 // overflow. 189 // overflow.
96 switch (function.recognized_kind()) { 190 switch (function.recognized_kind()) {
97 CORE_LIB_INTRINSIC_LIST(EMIT_CASE); 191 ALL_INTRINSICS_NO_INTEGER_LIB_LIST(EMIT_CASE);
98 MATH_LIB_INTRINSIC_LIST(EMIT_CASE);
99 TYPED_DATA_LIB_INTRINSIC_LIST(EMIT_CASE);
100 PROFILER_LIB_INTRINSIC_LIST(EMIT_CASE);
101 default: 192 default:
102 break; 193 break;
103 } 194 }
104 } else { 195 } else {
105 switch (function.recognized_kind()) { 196 switch (function.recognized_kind()) {
106 CORE_LIB_INTRINSIC_LIST(EMIT_CASE); 197 ALL_INTRINSICS_LIST(EMIT_CASE);
107 CORE_INTEGER_LIB_INTRINSIC_LIST(EMIT_CASE);
108 MATH_LIB_INTRINSIC_LIST(EMIT_CASE);
109 TYPED_DATA_LIB_INTRINSIC_LIST(EMIT_CASE);
110 PROFILER_LIB_INTRINSIC_LIST(EMIT_CASE);
111 default: 198 default:
112 UNREACHABLE(); 199 UNREACHABLE();
113 break; 200 break;
114 } 201 }
115 } 202 }
116 #undef EMIT_INTRINSIC 203 #undef EMIT_INTRINSIC
117 } 204 }
118 205
206
207 class BlockBuilder : public ValueObject {
208 public:
209 BlockBuilder(FlowGraph* flow_graph, TargetEntryInstr* entry)
210 : flow_graph_(flow_graph), entry_(entry), current_(entry) { }
211
212 Definition* AddToInitialDefinitions(Definition* def) {
213 def->set_ssa_temp_index(flow_graph_->alloc_ssa_temp_index());
214 flow_graph_->AddToInitialDefinitions(def);
215 return def;
216 }
217
218 Definition* AddDefinition(Definition* def) {
219 def->set_ssa_temp_index(flow_graph_->alloc_ssa_temp_index());
220 current_ = current_->AppendInstruction(def);
221 return def;
222 }
223
224 Instruction* AddInstruction(Instruction* instr) {
225 current_ = current_->AppendInstruction(instr);
226 return instr;
227 }
228
229 void AddIntrinsicReturn(Value* value) {
230 ReturnInstr* instr = new ReturnInstr(TokenPos(), value);
231 AddInstruction(instr);
232 entry_->set_last_instruction(instr);
233 }
234
235 Definition* AddParameter(intptr_t index) {
236 intptr_t adjustment = Intrinsifier::ParameterSlotFromSp();
237 return AddToInitialDefinitions(
238 new ParameterInstr(adjustment + index,
239 flow_graph_->graph_entry(),
240 SPREG));
241 }
242
243 intptr_t TokenPos() {
244 return flow_graph_->parsed_function().function().token_pos();
245 }
246
247 private:
248 FlowGraph* flow_graph_;
249 BlockEntryInstr* entry_;
250 Instruction* current_;
251 };
252
253
254 static void PrepareIndexedOp(BlockBuilder* builder,
255 Definition* array,
256 Definition* index,
257 intptr_t length_offset) {
258 intptr_t token_pos = builder->TokenPos();
259 builder->AddInstruction(
260 new CheckSmiInstr(new Value(index),
261 Isolate::kNoDeoptId,
262 token_pos));
263
264 Definition* length = builder->AddDefinition(
265 new LoadFieldInstr(new Value(array),
266 length_offset,
267 Type::ZoneHandle(Type::SmiType()),
268 true)); // immutable
269 builder->AddInstruction(
270 new CheckArrayBoundInstr(new Value(length),
271 new Value(index),
272 Isolate::kNoDeoptId));
273 }
274
275
276 bool Intrinsifier::Build_ObjectArrayGetIndexed(FlowGraph* flow_graph) {
277 GraphEntryInstr* graph_entry = flow_graph->graph_entry();
278 TargetEntryInstr* normal_entry = graph_entry->normal_entry();
279 BlockBuilder builder(flow_graph, normal_entry);
280
281 Definition* index = builder.AddParameter(1);
282 Definition* array = builder.AddParameter(2);
283
284 PrepareIndexedOp(&builder, array, index, Array::length_offset());
285
286 Definition* result = builder.AddDefinition(
287 new LoadIndexedInstr(new Value(array),
288 new Value(index),
289 Instance::ElementSizeFor(kArrayCid), // index scale
290 kArrayCid,
291 Isolate::kNoDeoptId,
292 builder.TokenPos()));
293 builder.AddIntrinsicReturn(new Value(result));
294 return true;
295 }
296
297
298 bool Intrinsifier::Build_ImmutableArrayGetIndexed(FlowGraph* flow_graph) {
299 return Build_ObjectArrayGetIndexed(flow_graph);
300 }
301
302
303 bool Intrinsifier::Build_Uint8ArrayGetIndexed(FlowGraph* flow_graph) {
304 GraphEntryInstr* graph_entry = flow_graph->graph_entry();
305 TargetEntryInstr* normal_entry = graph_entry->normal_entry();
306 BlockBuilder builder(flow_graph, normal_entry);
307
308 Definition* index = builder.AddParameter(1);
309 Definition* array = builder.AddParameter(2);
310
311 PrepareIndexedOp(&builder, array, index, TypedData::length_offset());
312
313 Definition* result = builder.AddDefinition(
314 new LoadIndexedInstr(new Value(array),
315 new Value(index),
316 1, // index scale
317 kTypedDataUint8ArrayCid,
318 Isolate::kNoDeoptId,
319 builder.TokenPos()));
320 builder.AddIntrinsicReturn(new Value(result));
321 return true;
322 }
323
324
325 bool Intrinsifier::Build_ExternalUint8ArrayGetIndexed(FlowGraph* flow_graph) {
326 GraphEntryInstr* graph_entry = flow_graph->graph_entry();
327 TargetEntryInstr* normal_entry = graph_entry->normal_entry();
328 BlockBuilder builder(flow_graph, normal_entry);
329
330 Definition* index = builder.AddParameter(1);
331 Definition* array = builder.AddParameter(2);
332
333 PrepareIndexedOp(&builder, array, index, ExternalTypedData::length_offset());
334
335 Definition* elements = builder.AddDefinition(
336 new LoadUntaggedInstr(new Value(array),
337 ExternalTypedData::data_offset()));
338 Definition* result = builder.AddDefinition(
339 new LoadIndexedInstr(new Value(elements),
340 new Value(index),
341 1, // index scale
342 kExternalTypedDataUint8ArrayCid,
343 Isolate::kNoDeoptId,
344 builder.TokenPos()));
345 builder.AddIntrinsicReturn(new Value(result));
346 return true;
347 }
348
349
350 bool Intrinsifier::Build_Uint8ArraySetIndexed(FlowGraph* flow_graph) {
351 GraphEntryInstr* graph_entry = flow_graph->graph_entry();
352 TargetEntryInstr* normal_entry = graph_entry->normal_entry();
353 BlockBuilder builder(flow_graph, normal_entry);
354
355 Definition* value = builder.AddParameter(1);
356 Definition* index = builder.AddParameter(2);
357 Definition* array = builder.AddParameter(3);
358
359 PrepareIndexedOp(&builder, array, index, TypedData::length_offset());
360
361 builder.AddInstruction(
362 new CheckSmiInstr(new Value(value),
363 Isolate::kNoDeoptId,
364 builder.TokenPos()));
365
366 builder.AddInstruction(
367 new StoreIndexedInstr(new Value(array),
368 new Value(index),
369 new Value(value),
370 kNoStoreBarrier,
371 1, // index scale
372 kTypedDataUint8ArrayCid,
373 Isolate::kNoDeoptId,
374 builder.TokenPos()));
375 // Return null.
376 Definition* null_def = builder.AddDefinition(
377 new ConstantInstr(Object::ZoneHandle(Object::null())));
378 builder.AddIntrinsicReturn(new Value(null_def));
379 return true;
380 }
381
382
383 bool Intrinsifier::Build_ExternalUint8ArraySetIndexed(FlowGraph* flow_graph) {
384 GraphEntryInstr* graph_entry = flow_graph->graph_entry();
385 TargetEntryInstr* normal_entry = graph_entry->normal_entry();
386 BlockBuilder builder(flow_graph, normal_entry);
387
388 Definition* value = builder.AddParameter(1);
389 Definition* index = builder.AddParameter(2);
390 Definition* array = builder.AddParameter(3);
391
392 PrepareIndexedOp(&builder, array, index, ExternalTypedData::length_offset());
393
394 builder.AddInstruction(
395 new CheckSmiInstr(new Value(value),
396 Isolate::kNoDeoptId,
397 builder.TokenPos()));
398 Definition* elements = builder.AddDefinition(
399 new LoadUntaggedInstr(new Value(array),
400 ExternalTypedData::data_offset()));
401 builder.AddInstruction(
402 new StoreIndexedInstr(new Value(elements),
403 new Value(index),
404 new Value(value),
405 kNoStoreBarrier,
406 1, // index scale
407 kExternalTypedDataUint8ArrayCid,
408 Isolate::kNoDeoptId,
409 builder.TokenPos()));
410 // Return null.
411 Definition* null_def = builder.AddDefinition(
412 new ConstantInstr(Object::ZoneHandle(Object::null())));
413 builder.AddIntrinsicReturn(new Value(null_def));
414 return true;
415 }
416
417
418 bool Intrinsifier::Build_Float64ArraySetIndexed(FlowGraph* flow_graph) {
419 if (!FlowGraphCompiler::SupportsUnboxedDoubles()) return false;
420
421 GraphEntryInstr* graph_entry = flow_graph->graph_entry();
422 TargetEntryInstr* normal_entry = graph_entry->normal_entry();
423 BlockBuilder builder(flow_graph, normal_entry);
424
425 Definition* value = builder.AddParameter(1);
426 Definition* index = builder.AddParameter(2);
427 Definition* array = builder.AddParameter(3);
428
429 PrepareIndexedOp(&builder, array, index, TypedData::length_offset());
430
431 const ICData& value_check = ICData::ZoneHandle(ICData::New(
432 flow_graph->parsed_function().function(),
433 String::Handle(flow_graph->parsed_function().function().name()),
434 Object::empty_array(), // Dummy args. descr.
435 Isolate::kNoDeoptId,
436 1));
437 value_check.AddReceiverCheck(kDoubleCid,
438 flow_graph->parsed_function().function());
439 builder.AddInstruction(
440 new CheckClassInstr(new Value(value),
441 Isolate::kNoDeoptId,
442 value_check,
443 builder.TokenPos()));
444 Definition* double_value = builder.AddDefinition(
445 new UnboxDoubleInstr(new Value(value), Isolate::kNoDeoptId));
446 // Manually adjust reaching type because there is no type propagation
447 // when building intrinsics.
448 double_value->AsUnboxDouble()->value()->SetReachingType(
449 ZoneCompileType::Wrap(CompileType::FromCid(kDoubleCid)));
450
451 builder.AddInstruction(
452 new StoreIndexedInstr(new Value(array),
453 new Value(index),
454 new Value(double_value),
455 kNoStoreBarrier,
456 8, // index scale
457 kTypedDataFloat64ArrayCid,
458 Isolate::kNoDeoptId,
459 builder.TokenPos()));
460 // Return null.
461 Definition* null_def = builder.AddDefinition(
462 new ConstantInstr(Object::ZoneHandle(Object::null())));
463 builder.AddIntrinsicReturn(new Value(null_def));
464 return true;
465 }
466
467
468 bool Intrinsifier::Build_Float64ArrayGetIndexed(FlowGraph* flow_graph) {
469 if (!FlowGraphCompiler::SupportsUnboxedDoubles()) return false;
470
471 GraphEntryInstr* graph_entry = flow_graph->graph_entry();
472 TargetEntryInstr* normal_entry = graph_entry->normal_entry();
473 BlockBuilder builder(flow_graph, normal_entry);
474
475 Definition* index = builder.AddParameter(1);
476 Definition* array = builder.AddParameter(2);
477
478 PrepareIndexedOp(&builder, array, index, TypedData::length_offset());
479
480 Definition* unboxed_value = builder.AddDefinition(
481 new LoadIndexedInstr(new Value(array),
482 new Value(index),
483 8, // index scale
484 kTypedDataFloat64ArrayCid,
485 Isolate::kNoDeoptId,
486 builder.TokenPos()));
487 Definition* result = builder.AddDefinition(
488 new BoxDoubleInstr(new Value(unboxed_value)));
489 builder.AddIntrinsicReturn(new Value(result));
490 return true;
491 }
492
493
494 static bool BuildLoadField(FlowGraph* flow_graph, intptr_t offset) {
495 GraphEntryInstr* graph_entry = flow_graph->graph_entry();
496 TargetEntryInstr* normal_entry = graph_entry->normal_entry();
497 BlockBuilder builder(flow_graph, normal_entry);
498
499 Definition* array = builder.AddParameter(1);
500
501 Definition* length = builder.AddDefinition(
502 new LoadFieldInstr(new Value(array),
503 offset,
504 Type::ZoneHandle(),
505 builder.TokenPos()));
506 builder.AddIntrinsicReturn(new Value(length));
507 return true;
508 }
509
510
511 bool Intrinsifier::Build_ObjectArrayLength(FlowGraph* flow_graph) {
512 return BuildLoadField(flow_graph, Array::length_offset());
513 }
514
515
516 bool Intrinsifier::Build_ImmutableArrayLength(FlowGraph* flow_graph) {
517 return BuildLoadField(flow_graph, Array::length_offset());
518 }
519
520
521 bool Intrinsifier::Build_GrowableArrayLength(FlowGraph* flow_graph) {
522 return BuildLoadField(flow_graph, GrowableObjectArray::length_offset());
523 }
524
525
526 bool Intrinsifier::Build_StringBaseLength(FlowGraph* flow_graph) {
527 return BuildLoadField(flow_graph, String::length_offset());
528 }
529
530
531 bool Intrinsifier::Build_TypedDataLength(FlowGraph* flow_graph) {
532 return BuildLoadField(flow_graph, TypedData::length_offset());
533 }
534
535
536 bool Intrinsifier::Build_GrowableArrayCapacity(FlowGraph* flow_graph) {
537 GraphEntryInstr* graph_entry = flow_graph->graph_entry();
538 TargetEntryInstr* normal_entry = graph_entry->normal_entry();
539 BlockBuilder builder(flow_graph, normal_entry);
540
541 Definition* array = builder.AddParameter(1);
542
543 Definition* backing_store = builder.AddDefinition(
544 new LoadFieldInstr(new Value(array),
545 GrowableObjectArray::data_offset(),
546 Type::ZoneHandle(),
547 builder.TokenPos()));
548 Definition* capacity = builder.AddDefinition(
549 new LoadFieldInstr(new Value(backing_store),
550 Array::length_offset(),
551 Type::ZoneHandle(),
552 builder.TokenPos()));
553 builder.AddIntrinsicReturn(new Value(capacity));
554 return true;
555 }
556
557
119 } // namespace dart 558 } // namespace dart
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698