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

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

Issue 1201383002: Port irregexp bytecode compiler and interpreter from V8 r24065. (Closed) Base URL: git@github.com:dart-lang/sdk.git@master
Patch Set: Created 5 years, 5 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
« no previous file with comments | « runtime/vm/regexp.h ('k') | runtime/vm/regexp_assembler.h » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 // Copyright (c) 2014, the Dart project authors. Please see the AUTHORS file 1 // Copyright (c) 2014, 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/regexp.h" 5 #include "vm/regexp.h"
6 6
7 #include "vm/dart_entry.h" 7 #include "vm/dart_entry.h"
8 #include "vm/regexp_assembler.h" 8 #include "vm/regexp_assembler.h"
9 #include "vm/regexp_assembler_bytecode.h"
10 #include "vm/regexp_assembler_ir.h"
9 #include "vm/regexp_ast.h" 11 #include "vm/regexp_ast.h"
10 #include "vm/unibrow-inl.h" 12 #include "vm/unibrow-inl.h"
11 #include "vm/unicode.h" 13 #include "vm/unicode.h"
12 #include "vm/symbols.h" 14 #include "vm/symbols.h"
13 #include "vm/thread.h" 15 #include "vm/thread.h"
14 16
15 #define Z (zone()) 17 #define Z (zone())
16 18
17 namespace dart { 19 namespace dart {
18 20
19 DECLARE_FLAG(bool, trace_irregexp); 21 DECLARE_FLAG(bool, trace_irregexp);
22 DEFINE_FLAG(bool, interpret_irregexp, false,
23 "Use irregexp bytecode interpreter");
20 24
21 // Default to generating optimized regexp code. 25 // Default to generating optimized regexp code.
22 static const bool kRegexpOptimization = true; 26 static const bool kRegexpOptimization = true;
23 27
24 // More makes code generation slower, less makes V8 benchmark score lower. 28 // More makes code generation slower, less makes V8 benchmark score lower.
25 static const intptr_t kMaxLookaheadForBoyerMoore = 8; 29 static const intptr_t kMaxLookaheadForBoyerMoore = 8;
26 30
27 ContainedInLattice AddRange(ContainedInLattice containment, 31 ContainedInLattice AddRange(ContainedInLattice containment,
28 const intptr_t* ranges, 32 const intptr_t* ranges,
29 intptr_t ranges_length, 33 intptr_t ranges_length,
(...skipping 257 matching lines...) Expand 10 before | Expand all | Expand 10 after
287 private: 291 private:
288 CharacterFrequency frequencies_[RegExpMacroAssembler::kTableSize]; 292 CharacterFrequency frequencies_[RegExpMacroAssembler::kTableSize];
289 intptr_t total_samples_; 293 intptr_t total_samples_;
290 }; 294 };
291 295
292 296
293 class RegExpCompiler : public ValueObject { 297 class RegExpCompiler : public ValueObject {
294 public: 298 public:
295 RegExpCompiler(intptr_t capture_count, 299 RegExpCompiler(intptr_t capture_count,
296 bool ignore_case, 300 bool ignore_case,
297 intptr_t specialization_cid); 301 bool is_one_byte);
298 302
299 intptr_t AllocateRegister() { 303 intptr_t AllocateRegister() {
300 return next_register_++; 304 return next_register_++;
301 } 305 }
302 306
303 RegExpEngine::CompilationResult Assemble(IRRegExpMacroAssembler* assembler, 307 RegExpEngine::CompilationResult Assemble(
304 RegExpNode* start, 308 IRRegExpMacroAssembler* assembler,
305 intptr_t capture_count, 309 RegExpNode* start,
306 const String& pattern); 310 intptr_t capture_count,
311 const String& pattern);
312
313 RegExpEngine::CompilationResult Assemble(
314 BytecodeRegExpMacroAssembler* assembler,
315 RegExpNode* start,
316 intptr_t capture_count,
317 const String& pattern);
307 318
308 inline void AddWork(RegExpNode* node) { work_list_->Add(node); } 319 inline void AddWork(RegExpNode* node) { work_list_->Add(node); }
309 320
310 static const intptr_t kImplementationOffset = 0; 321 static const intptr_t kImplementationOffset = 0;
311 static const intptr_t kNumberOfRegistersOffset = 0; 322 static const intptr_t kNumberOfRegistersOffset = 0;
312 static const intptr_t kCodeOffset = 1; 323 static const intptr_t kCodeOffset = 1;
313 324
314 IRRegExpMacroAssembler* macro_assembler() { return macro_assembler_; } 325 RegExpMacroAssembler* macro_assembler() { return macro_assembler_; }
315 EndNode* accept() { return accept_; } 326 EndNode* accept() { return accept_; }
316 327
317 static const intptr_t kMaxRecursion = 100; 328 static const intptr_t kMaxRecursion = 100;
318 inline intptr_t recursion_depth() { return recursion_depth_; } 329 inline intptr_t recursion_depth() { return recursion_depth_; }
319 inline void IncrementRecursionDepth() { recursion_depth_++; } 330 inline void IncrementRecursionDepth() { recursion_depth_++; }
320 inline void DecrementRecursionDepth() { recursion_depth_--; } 331 inline void DecrementRecursionDepth() { recursion_depth_--; }
321 332
322 void SetRegExpTooBig() { reg_exp_too_big_ = true; } 333 void SetRegExpTooBig() { reg_exp_too_big_ = true; }
323 334
324 inline bool ignore_case() { return ignore_case_; } 335 inline bool ignore_case() { return ignore_case_; }
325 inline bool one_byte() const { 336 inline bool one_byte() const { return is_one_byte_; }
326 return (specialization_cid_ == kOneByteStringCid ||
327 specialization_cid_ == kExternalOneByteStringCid);
328 }
329 inline intptr_t specialization_cid() { return specialization_cid_; }
330 FrequencyCollator* frequency_collator() { return &frequency_collator_; } 337 FrequencyCollator* frequency_collator() { return &frequency_collator_; }
331 338
332 intptr_t current_expansion_factor() { return current_expansion_factor_; } 339 intptr_t current_expansion_factor() { return current_expansion_factor_; }
333 void set_current_expansion_factor(intptr_t value) { 340 void set_current_expansion_factor(intptr_t value) {
334 current_expansion_factor_ = value; 341 current_expansion_factor_ = value;
335 } 342 }
336 343
337 Zone* zone() const { return zone_; } 344 Zone* zone() const { return zone_; }
338 345
339 static const intptr_t kNoRegister = -1; 346 static const intptr_t kNoRegister = -1;
340 347
341 private: 348 private:
342 EndNode* accept_; 349 EndNode* accept_;
343 intptr_t next_register_; 350 intptr_t next_register_;
344 ZoneGrowableArray<RegExpNode*>* work_list_; 351 ZoneGrowableArray<RegExpNode*>* work_list_;
345 intptr_t recursion_depth_; 352 intptr_t recursion_depth_;
346 IRRegExpMacroAssembler* macro_assembler_; 353 RegExpMacroAssembler* macro_assembler_;
347 bool ignore_case_; 354 bool ignore_case_;
348 intptr_t specialization_cid_; 355 bool is_one_byte_;
349 bool reg_exp_too_big_; 356 bool reg_exp_too_big_;
350 intptr_t current_expansion_factor_; 357 intptr_t current_expansion_factor_;
351 FrequencyCollator frequency_collator_; 358 FrequencyCollator frequency_collator_;
352 Zone* zone_; 359 Zone* zone_;
353 }; 360 };
354 361
355 362
356 class RecursionCheck : public ValueObject { 363 class RecursionCheck : public ValueObject {
357 public: 364 public:
358 explicit RecursionCheck(RegExpCompiler* compiler) : compiler_(compiler) { 365 explicit RecursionCheck(RegExpCompiler* compiler) : compiler_(compiler) {
359 compiler->IncrementRecursionDepth(); 366 compiler->IncrementRecursionDepth();
360 } 367 }
361 ~RecursionCheck() { compiler_->DecrementRecursionDepth(); } 368 ~RecursionCheck() { compiler_->DecrementRecursionDepth(); }
362 private: 369 private:
363 RegExpCompiler* compiler_; 370 RegExpCompiler* compiler_;
364 }; 371 };
365 372
366 373
367 static RegExpEngine::CompilationResult IrregexpRegExpTooBig() { 374 static RegExpEngine::CompilationResult IrregexpRegExpTooBig() {
368 return RegExpEngine::CompilationResult("RegExp too big"); 375 return RegExpEngine::CompilationResult("RegExp too big");
369 } 376 }
370 377
371 378
372 // Attempts to compile the regexp using an Irregexp code generator. Returns 379 // Attempts to compile the regexp using an Irregexp code generator. Returns
373 // a fixed array or a null handle depending on whether it succeeded. 380 // a fixed array or a null handle depending on whether it succeeded.
374 RegExpCompiler::RegExpCompiler(intptr_t capture_count, bool ignore_case, 381 RegExpCompiler::RegExpCompiler(intptr_t capture_count,
375 intptr_t specialization_cid) 382 bool ignore_case,
383 bool is_one_byte)
376 : next_register_(2 * (capture_count + 1)), 384 : next_register_(2 * (capture_count + 1)),
377 work_list_(NULL), 385 work_list_(NULL),
378 recursion_depth_(0), 386 recursion_depth_(0),
379 ignore_case_(ignore_case), 387 ignore_case_(ignore_case),
380 specialization_cid_(specialization_cid), 388 is_one_byte_(is_one_byte),
381 reg_exp_too_big_(false), 389 reg_exp_too_big_(false),
382 current_expansion_factor_(1), 390 current_expansion_factor_(1),
383 zone_(Thread::Current()->zone()) { 391 zone_(Thread::Current()->zone()) {
384 accept_ = new(Z) EndNode(EndNode::ACCEPT, Z); 392 accept_ = new(Z) EndNode(EndNode::ACCEPT, Z);
385 } 393 }
386 394
387 395
388 RegExpEngine::CompilationResult RegExpCompiler::Assemble( 396 RegExpEngine::CompilationResult RegExpCompiler::Assemble(
389 IRRegExpMacroAssembler* macro_assembler, 397 IRRegExpMacroAssembler* macro_assembler,
390 RegExpNode* start, 398 RegExpNode* start,
391 intptr_t capture_count, 399 intptr_t capture_count,
392 const String& pattern) { 400 const String& pattern) {
393 static const bool use_slow_safe_regexp_compiler = false; 401 macro_assembler->set_slow_safe(false /* use_slow_safe_regexp_compiler */);
394
395 macro_assembler->set_slow_safe(use_slow_safe_regexp_compiler);
396 macro_assembler_ = macro_assembler; 402 macro_assembler_ = macro_assembler;
397 403
398 ZoneGrowableArray<RegExpNode*> work_list(0); 404 ZoneGrowableArray<RegExpNode*> work_list(0);
399 work_list_ = &work_list; 405 work_list_ = &work_list;
400 BlockLabel fail; 406 BlockLabel fail;
401 macro_assembler_->PushBacktrack(&fail); 407 macro_assembler_->PushBacktrack(&fail);
402 Trace new_trace; 408 Trace new_trace;
403 start->Emit(this, &new_trace); 409 start->Emit(this, &new_trace);
404 macro_assembler_->BindBlock(&fail); 410 macro_assembler_->BindBlock(&fail);
405 macro_assembler_->Fail(); 411 macro_assembler_->Fail();
406 while (!work_list.is_empty()) { 412 while (!work_list.is_empty()) {
407 work_list.RemoveLast()->Emit(this, &new_trace); 413 work_list.RemoveLast()->Emit(this, &new_trace);
408 } 414 }
409 if (reg_exp_too_big_) return IrregexpRegExpTooBig(); 415 if (reg_exp_too_big_) return IrregexpRegExpTooBig();
410 416
411 macro_assembler->GenerateBacktrackBlock(); 417 macro_assembler->GenerateBacktrackBlock();
412 macro_assembler->FinalizeRegistersArray(); 418 macro_assembler->FinalizeRegistersArray();
413 419
414 return RegExpEngine::CompilationResult(macro_assembler->backtrack_goto(), 420 return RegExpEngine::CompilationResult(macro_assembler->backtrack_goto(),
415 macro_assembler->graph_entry(), 421 macro_assembler->graph_entry(),
416 macro_assembler->num_blocks(), 422 macro_assembler->num_blocks(),
417 macro_assembler->num_stack_locals()); 423 macro_assembler->num_stack_locals(),
424 next_register_);
418 } 425 }
419 426
420 427
428 RegExpEngine::CompilationResult RegExpCompiler::Assemble(
429 BytecodeRegExpMacroAssembler* macro_assembler,
430 RegExpNode* start,
431 intptr_t capture_count,
432 const String& pattern) {
433 macro_assembler->set_slow_safe(false /* use_slow_safe_regexp_compiler */);
434 macro_assembler_ = macro_assembler;
435
436 ZoneGrowableArray<RegExpNode*> work_list(0);
437 work_list_ = &work_list;
438 BlockLabel fail;
439 macro_assembler_->PushBacktrack(&fail);
440 Trace new_trace;
441 start->Emit(this, &new_trace);
442 macro_assembler_->BindBlock(&fail);
443 macro_assembler_->Fail();
444 while (!work_list.is_empty()) {
445 work_list.RemoveLast()->Emit(this, &new_trace);
446 }
447 if (reg_exp_too_big_) return IrregexpRegExpTooBig();
448
449 TypedData& bytecode = TypedData::ZoneHandle(macro_assembler->GetBytecode());
450 return RegExpEngine::CompilationResult(&bytecode, next_register_);
451 }
452
453
421 bool Trace::DeferredAction::Mentions(intptr_t that) { 454 bool Trace::DeferredAction::Mentions(intptr_t that) {
422 if (action_type() == ActionNode::CLEAR_CAPTURES) { 455 if (action_type() == ActionNode::CLEAR_CAPTURES) {
423 Interval range = static_cast<DeferredClearCaptures*>(this)->range(); 456 Interval range = static_cast<DeferredClearCaptures*>(this)->range();
424 return range.Contains(that); 457 return range.Contains(that);
425 } else { 458 } else {
426 return reg() == that; 459 return reg() == that;
427 } 460 }
428 } 461 }
429 462
430 463
(...skipping 4538 matching lines...) Expand 10 before | Expand all | Expand 10 after
4969 return; 5002 return;
4970 } 5003 }
4971 on_success()->FillInBMInfo(offset, 5004 on_success()->FillInBMInfo(offset,
4972 budget - 1, 5005 budget - 1,
4973 bm, 5006 bm,
4974 true); // Not at start after a text node. 5007 true); // Not at start after a text node.
4975 if (initial_offset == 0) set_bm_info(not_at_start, bm); 5008 if (initial_offset == 0) set_bm_info(not_at_start, bm);
4976 } 5009 }
4977 5010
4978 5011
4979 RegExpEngine::CompilationResult RegExpEngine::Compile( 5012 RegExpEngine::CompilationResult RegExpEngine::CompileIR(
4980 RegExpCompileData* data, 5013 RegExpCompileData* data,
4981 const ParsedFunction* parsed_function, 5014 const ParsedFunction* parsed_function,
4982 const ZoneGrowableArray<const ICData*>& ic_data_array) { 5015 const ZoneGrowableArray<const ICData*>& ic_data_array) {
5016 ASSERT(!FLAG_interpret_irregexp);
4983 Zone* zone = Thread::Current()->zone(); 5017 Zone* zone = Thread::Current()->zone();
4984 5018
4985 const Function& function = parsed_function->function(); 5019 const Function& function = parsed_function->function();
4986 const intptr_t specialization_cid = function.regexp_cid(); 5020 const intptr_t specialization_cid = function.regexp_cid();
4987 const bool is_one_byte = (specialization_cid == kOneByteStringCid || 5021 const bool is_one_byte = (specialization_cid == kOneByteStringCid ||
4988 specialization_cid == kExternalOneByteStringCid); 5022 specialization_cid == kExternalOneByteStringCid);
4989 JSRegExp& regexp = JSRegExp::Handle(zone, function.regexp()); 5023 JSRegExp& regexp = JSRegExp::Handle(zone, function.regexp());
4990 const String& pattern = String::Handle(zone, regexp.pattern()); 5024 const String& pattern = String::Handle(zone, regexp.pattern());
4991 5025
4992 ASSERT(!regexp.IsNull()); 5026 ASSERT(!regexp.IsNull());
4993 ASSERT(!pattern.IsNull()); 5027 ASSERT(!pattern.IsNull());
4994 5028
4995 const bool ignore_case = regexp.is_ignore_case(); 5029 const bool ignore_case = regexp.is_ignore_case();
4996 const bool is_global = regexp.is_global(); 5030 const bool is_global = regexp.is_global();
4997 5031
4998 RegExpCompiler compiler(data->capture_count, ignore_case, specialization_cid); 5032 RegExpCompiler compiler(data->capture_count, ignore_case, is_one_byte);
4999 5033
5000 // TODO(zerny): Frequency sampling is currently disabled because of several 5034 // TODO(zerny): Frequency sampling is currently disabled because of several
5001 // issues. We do not want to store subject strings in the regexp object since 5035 // issues. We do not want to store subject strings in the regexp object since
5002 // they might be long and we should not prevent their garbage collection. 5036 // they might be long and we should not prevent their garbage collection.
5003 // Passing them to this function explicitly does not help, since we must 5037 // Passing them to this function explicitly does not help, since we must
5004 // generate exactly the same IR for both the unoptimizing and optimizing 5038 // generate exactly the same IR for both the unoptimizing and optimizing
5005 // pipelines (otherwise it gets confused when i.e. deopt id's differ). 5039 // pipelines (otherwise it gets confused when i.e. deopt id's differ).
5006 // An option would be to store sampling results in the regexp object, but 5040 // An option would be to store sampling results in the regexp object, but
5007 // I'm not sure the performance gains are relevant enough. 5041 // I'm not sure the performance gains are relevant enough.
5008 5042
(...skipping 82 matching lines...) Expand 10 before | Expand all | Expand 10 after
5091 pattern); 5125 pattern);
5092 5126
5093 if (FLAG_trace_irregexp) { 5127 if (FLAG_trace_irregexp) {
5094 macro_assembler->PrintBlocks(); 5128 macro_assembler->PrintBlocks();
5095 } 5129 }
5096 5130
5097 return result; 5131 return result;
5098 } 5132 }
5099 5133
5100 5134
5135 RegExpEngine::CompilationResult RegExpEngine::CompileBytecode(
5136 RegExpCompileData* data,
5137 const JSRegExp& regexp,
5138 bool is_one_byte,
5139 Zone* zone) {
5140 ASSERT(FLAG_interpret_irregexp);
5141 const String& pattern = String::Handle(zone, regexp.pattern());
5142
5143 ASSERT(!regexp.IsNull());
5144 ASSERT(!pattern.IsNull());
5145
5146 const bool ignore_case = regexp.is_ignore_case();
5147 const bool is_global = regexp.is_global();
5148
5149 RegExpCompiler compiler(data->capture_count, ignore_case, is_one_byte);
5150
5151 // TODO(zerny): Frequency sampling is currently disabled because of several
5152 // issues. We do not want to store subject strings in the regexp object since
5153 // they might be long and we should not prevent their garbage collection.
5154 // Passing them to this function explicitly does not help, since we must
5155 // generate exactly the same IR for both the unoptimizing and optimizing
5156 // pipelines (otherwise it gets confused when i.e. deopt id's differ).
5157 // An option would be to store sampling results in the regexp object, but
5158 // I'm not sure the performance gains are relevant enough.
5159
5160 // Wrap the body of the regexp in capture #0.
5161 RegExpNode* captured_body = RegExpCapture::ToNode(data->tree,
5162 0,
5163 &compiler,
5164 compiler.accept());
5165
5166 RegExpNode* node = captured_body;
5167 bool is_end_anchored = data->tree->IsAnchoredAtEnd();
5168 bool is_start_anchored = data->tree->IsAnchoredAtStart();
5169 intptr_t max_length = data->tree->max_match();
5170 if (!is_start_anchored) {
5171 // Add a .*? at the beginning, outside the body capture, unless
5172 // this expression is anchored at the beginning.
5173 RegExpNode* loop_node =
5174 RegExpQuantifier::ToNode(0,
5175 RegExpTree::kInfinity,
5176 false,
5177 new(zone) RegExpCharacterClass('*'),
5178 &compiler,
5179 captured_body,
5180 data->contains_anchor);
5181
5182 if (data->contains_anchor) {
5183 // Unroll loop once, to take care of the case that might start
5184 // at the start of input.
5185 ChoiceNode* first_step_node = new(zone) ChoiceNode(2, zone);
5186 first_step_node->AddAlternative(GuardedAlternative(captured_body));
5187 first_step_node->AddAlternative(GuardedAlternative(
5188 new(zone) TextNode(
5189 new(zone) RegExpCharacterClass('*'), loop_node)));
5190 node = first_step_node;
5191 } else {
5192 node = loop_node;
5193 }
5194 }
5195 if (is_one_byte) {
5196 node = node->FilterOneByte(RegExpCompiler::kMaxRecursion, ignore_case);
5197 // Do it again to propagate the new nodes to places where they were not
5198 // put because they had not been calculated yet.
5199 if (node != NULL) {
5200 node = node->FilterOneByte(RegExpCompiler::kMaxRecursion, ignore_case);
5201 }
5202 }
5203
5204 if (node == NULL) node = new(zone) EndNode(EndNode::BACKTRACK, zone);
5205 data->node = node;
5206 Analysis analysis(ignore_case, is_one_byte);
5207 analysis.EnsureAnalyzed(node);
5208 if (analysis.has_failed()) {
5209 const char* error_message = analysis.error_message();
5210 return CompilationResult(error_message);
5211 }
5212
5213 // Bytecode regexp implementation.
5214
5215 ZoneGrowableArray<uint8_t> buffer(zone, 1024);
5216 BytecodeRegExpMacroAssembler* macro_assembler =
5217 new(zone) BytecodeRegExpMacroAssembler(&buffer, zone);
5218
5219 // Inserted here, instead of in Assembler, because it depends on information
5220 // in the AST that isn't replicated in the Node structure.
5221 static const intptr_t kMaxBacksearchLimit = 1024;
5222 if (is_end_anchored &&
5223 !is_start_anchored &&
5224 max_length < kMaxBacksearchLimit) {
5225 macro_assembler->SetCurrentPositionFromEnd(max_length);
5226 }
5227
5228 if (is_global) {
5229 macro_assembler->set_global_mode(
5230 (data->tree->min_match() > 0)
5231 ? RegExpMacroAssembler::GLOBAL_NO_ZERO_LENGTH_CHECK
5232 : RegExpMacroAssembler::GLOBAL);
5233 }
5234
5235 RegExpEngine::CompilationResult result =
5236 compiler.Assemble(macro_assembler,
5237 node,
5238 data->capture_count,
5239 pattern);
5240
5241 if (FLAG_trace_irregexp) {
5242 macro_assembler->PrintBlocks();
5243 }
5244
5245 return result;
5246 }
5247
5248
5101 static void CreateSpecializedFunction(Zone* zone, 5249 static void CreateSpecializedFunction(Zone* zone,
5102 const JSRegExp& regexp, 5250 const JSRegExp& regexp,
5103 intptr_t specialization_cid, 5251 intptr_t specialization_cid,
5104 const Object& owner) { 5252 const Object& owner) {
5105 const intptr_t kParamCount = RegExpMacroAssembler::kParamCount; 5253 const intptr_t kParamCount = RegExpMacroAssembler::kParamCount;
5106 5254
5107 Function& fn = Function::Handle(zone, Function::New( 5255 Function& fn = Function::Handle(zone, Function::New(
5108 // Append the regexp pattern to the function name. 5256 // Append the regexp pattern to the function name.
5109 String::Handle(zone, Symbols::New( 5257 String::Handle(zone, Symbols::New(
5110 String::Handle(zone, String::Concat( 5258 String::Handle(zone, String::Concat(
(...skipping 60 matching lines...) Expand 10 before | Expand all | Expand 10 after
5171 CreateSpecializedFunction(zone, regexp, kOneByteStringCid, owner); 5319 CreateSpecializedFunction(zone, regexp, kOneByteStringCid, owner);
5172 CreateSpecializedFunction(zone, regexp, kTwoByteStringCid, owner); 5320 CreateSpecializedFunction(zone, regexp, kTwoByteStringCid, owner);
5173 CreateSpecializedFunction(zone, regexp, kExternalOneByteStringCid, owner); 5321 CreateSpecializedFunction(zone, regexp, kExternalOneByteStringCid, owner);
5174 CreateSpecializedFunction(zone, regexp, kExternalTwoByteStringCid, owner); 5322 CreateSpecializedFunction(zone, regexp, kExternalTwoByteStringCid, owner);
5175 5323
5176 return regexp.raw(); 5324 return regexp.raw();
5177 } 5325 }
5178 5326
5179 5327
5180 } // namespace dart 5328 } // namespace dart
OLDNEW
« no previous file with comments | « runtime/vm/regexp.h ('k') | runtime/vm/regexp_assembler.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698