| OLD | NEW |
| 1 // Copyright 2016 the V8 project authors. All rights reserved. | 1 // Copyright 2016 the V8 project authors. All rights reserved. |
| 2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
| 4 | 4 |
| 5 #include "src/builtins/builtins-regexp.h" | 5 #include "src/builtins/builtins-regexp.h" |
| 6 | 6 |
| 7 #include "src/builtins/builtins-constructor.h" | 7 #include "src/builtins/builtins-constructor.h" |
| 8 #include "src/builtins/builtins-utils.h" | 8 #include "src/builtins/builtins-utils.h" |
| 9 #include "src/builtins/builtins.h" | 9 #include "src/builtins/builtins.h" |
| 10 #include "src/code-factory.h" | 10 #include "src/code-factory.h" |
| (...skipping 198 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 209 Branch(IntPtrGreaterThanOrEqual(var_i.value(), names_length), &out, | 209 Branch(IntPtrGreaterThanOrEqual(var_i.value(), names_length), &out, |
| 210 &loop); | 210 &loop); |
| 211 } | 211 } |
| 212 } | 212 } |
| 213 | 213 |
| 214 Bind(&out); | 214 Bind(&out); |
| 215 return result; | 215 return result; |
| 216 } | 216 } |
| 217 | 217 |
| 218 void RegExpBuiltinsAssembler::GetStringPointers( | 218 void RegExpBuiltinsAssembler::GetStringPointers( |
| 219 Node* const string, Node* const offset, Node* const last_index, | 219 Node* const string_data, Node* const offset, Node* const last_index, |
| 220 Node* const string_length, bool is_one_byte, Variable* var_string_start, | 220 Node* const string_length, String::Encoding encoding, |
| 221 Variable* var_string_end) { | 221 Variable* var_string_start, Variable* var_string_end) { |
| 222 DCHECK_EQ(var_string_start->rep(), MachineType::PointerRepresentation()); | 222 DCHECK_EQ(var_string_start->rep(), MachineType::PointerRepresentation()); |
| 223 DCHECK_EQ(var_string_end->rep(), MachineType::PointerRepresentation()); | 223 DCHECK_EQ(var_string_end->rep(), MachineType::PointerRepresentation()); |
| 224 | 224 |
| 225 STATIC_ASSERT(SeqOneByteString::kHeaderSize == SeqTwoByteString::kHeaderSize); | 225 const ElementsKind kind = (encoding == String::ONE_BYTE_ENCODING) |
| 226 const int kHeaderSize = SeqOneByteString::kHeaderSize - kHeapObjectTag; | 226 ? UINT8_ELEMENTS |
| 227 const ElementsKind kind = is_one_byte ? UINT8_ELEMENTS : UINT16_ELEMENTS; | 227 : UINT16_ELEMENTS; |
| 228 | 228 |
| 229 Node* const from_offset = ElementOffsetFromIndex( | 229 Node* const from_offset = ElementOffsetFromIndex( |
| 230 IntPtrAdd(offset, last_index), kind, INTPTR_PARAMETERS, kHeaderSize); | 230 IntPtrAdd(offset, last_index), kind, INTPTR_PARAMETERS); |
| 231 var_string_start->Bind(IntPtrAdd(string, from_offset)); | 231 var_string_start->Bind(IntPtrAdd(string_data, from_offset)); |
| 232 | 232 |
| 233 Node* const to_offset = ElementOffsetFromIndex( | 233 Node* const to_offset = ElementOffsetFromIndex( |
| 234 IntPtrAdd(offset, string_length), kind, INTPTR_PARAMETERS, kHeaderSize); | 234 IntPtrAdd(offset, string_length), kind, INTPTR_PARAMETERS); |
| 235 var_string_end->Bind(IntPtrAdd(string, to_offset)); | 235 var_string_end->Bind(IntPtrAdd(string_data, to_offset)); |
| 236 } | 236 } |
| 237 | 237 |
| 238 Node* RegExpBuiltinsAssembler::IrregexpExec(Node* const context, | 238 Node* RegExpBuiltinsAssembler::IrregexpExec(Node* const context, |
| 239 Node* const regexp, | 239 Node* const regexp, |
| 240 Node* const string, | 240 Node* const string, |
| 241 Node* const last_index, | 241 Node* const last_index, |
| 242 Node* const match_info) { | 242 Node* const match_info) { |
| 243 // Just jump directly to runtime if native RegExp is not selected at compile | 243 // Just jump directly to runtime if native RegExp is not selected at compile |
| 244 // time or if regexp entry in generated code is turned off runtime switch or | 244 // time or if regexp entry in generated code is turned off runtime switch or |
| 245 // at compilation. | 245 // at compilation. |
| 246 #ifdef V8_INTERPRETED_REGEXP | 246 #ifdef V8_INTERPRETED_REGEXP |
| 247 return CallRuntime(Runtime::kRegExpExec, context, regexp, string, last_index, | 247 return CallRuntime(Runtime::kRegExpExec, context, regexp, string, last_index, |
| 248 match_info); | 248 match_info); |
| 249 #else // V8_INTERPRETED_REGEXP | 249 #else // V8_INTERPRETED_REGEXP |
| 250 CSA_ASSERT(this, TaggedIsNotSmi(regexp)); | 250 CSA_ASSERT(this, TaggedIsNotSmi(regexp)); |
| 251 CSA_ASSERT(this, HasInstanceType(regexp, JS_REGEXP_TYPE)); | 251 CSA_ASSERT(this, HasInstanceType(regexp, JS_REGEXP_TYPE)); |
| 252 | 252 |
| 253 CSA_ASSERT(this, TaggedIsNotSmi(string)); | 253 CSA_ASSERT(this, TaggedIsNotSmi(string)); |
| 254 CSA_ASSERT(this, IsString(string)); | 254 CSA_ASSERT(this, IsString(string)); |
| 255 | 255 |
| 256 CSA_ASSERT(this, IsHeapNumberMap(LoadReceiverMap(last_index))); | 256 CSA_ASSERT(this, IsHeapNumberMap(LoadReceiverMap(last_index))); |
| 257 CSA_ASSERT(this, IsFixedArrayMap(LoadReceiverMap(match_info))); | 257 CSA_ASSERT(this, IsFixedArrayMap(LoadReceiverMap(match_info))); |
| 258 | 258 |
| 259 Node* const int_zero = IntPtrConstant(0); | 259 Node* const int_zero = IntPtrConstant(0); |
| 260 | 260 |
| 261 ToDirectStringAssembler to_direct(state(), string); |
| 262 |
| 261 Variable var_result(this, MachineRepresentation::kTagged); | 263 Variable var_result(this, MachineRepresentation::kTagged); |
| 262 Variable var_string(this, MachineType::PointerRepresentation(), int_zero); | |
| 263 Variable var_string_offset(this, MachineType::PointerRepresentation(), | |
| 264 int_zero); | |
| 265 Variable var_string_instance_type(this, MachineRepresentation::kWord32, | |
| 266 Int32Constant(0)); | |
| 267 | |
| 268 Label out(this), runtime(this, Label::kDeferred); | 264 Label out(this), runtime(this, Label::kDeferred); |
| 269 | 265 |
| 270 // External constants. | 266 // External constants. |
| 271 Node* const regexp_stack_memory_size_address = ExternalConstant( | 267 Node* const regexp_stack_memory_size_address = ExternalConstant( |
| 272 ExternalReference::address_of_regexp_stack_memory_size(isolate())); | 268 ExternalReference::address_of_regexp_stack_memory_size(isolate())); |
| 273 Node* const static_offsets_vector_address = ExternalConstant( | 269 Node* const static_offsets_vector_address = ExternalConstant( |
| 274 ExternalReference::address_of_static_offsets_vector(isolate())); | 270 ExternalReference::address_of_static_offsets_vector(isolate())); |
| 275 Node* const pending_exception_address = ExternalConstant( | 271 Node* const pending_exception_address = ExternalConstant( |
| 276 ExternalReference(Isolate::kPendingExceptionAddress, isolate())); | 272 ExternalReference(Isolate::kPendingExceptionAddress, isolate())); |
| 277 | 273 |
| (...skipping 23 matching lines...) Expand all Loading... |
| 301 | 297 |
| 302 STATIC_ASSERT(Isolate::kJSRegexpStaticOffsetsVectorSize >= 2); | 298 STATIC_ASSERT(Isolate::kJSRegexpStaticOffsetsVectorSize >= 2); |
| 303 GotoIf(SmiAbove( | 299 GotoIf(SmiAbove( |
| 304 capture_count, | 300 capture_count, |
| 305 SmiConstant(Isolate::kJSRegexpStaticOffsetsVectorSize / 2 - 1)), | 301 SmiConstant(Isolate::kJSRegexpStaticOffsetsVectorSize / 2 - 1)), |
| 306 &runtime); | 302 &runtime); |
| 307 } | 303 } |
| 308 | 304 |
| 309 // Unpack the string if possible. | 305 // Unpack the string if possible. |
| 310 | 306 |
| 311 var_string.Bind(BitcastTaggedToWord(string)); | 307 to_direct.TryToDirect(&runtime); |
| 312 var_string_offset.Bind(int_zero); | |
| 313 var_string_instance_type.Bind(LoadInstanceType(string)); | |
| 314 | |
| 315 { | |
| 316 TryUnpackString(&var_string, &var_string_offset, &var_string_instance_type, | |
| 317 &runtime); | |
| 318 | |
| 319 // At this point, {var_string} may contain a faked sequential string (i.e. | |
| 320 // an external string with an adjusted offset) so we cannot assert | |
| 321 // IsString({var_string}). We also cannot allocate after this point since | |
| 322 // GC could move {var_string}'s underlying string. | |
| 323 } | |
| 324 | 308 |
| 325 Node* const smi_string_length = LoadStringLength(string); | 309 Node* const smi_string_length = LoadStringLength(string); |
| 326 | 310 |
| 327 // Bail out to runtime for invalid {last_index} values. | 311 // Bail out to runtime for invalid {last_index} values. |
| 328 GotoIfNot(TaggedIsSmi(last_index), &runtime); | 312 GotoIfNot(TaggedIsSmi(last_index), &runtime); |
| 329 GotoIf(SmiAboveOrEqual(last_index, smi_string_length), &runtime); | 313 GotoIf(SmiAboveOrEqual(last_index, smi_string_length), &runtime); |
| 330 | 314 |
| 331 // Load the irregexp code object and offsets into the subject string. Both | 315 // Load the irregexp code object and offsets into the subject string. Both |
| 332 // depend on whether the string is one- or two-byte. | 316 // depend on whether the string is one- or two-byte. |
| 333 | 317 |
| 334 Node* const int_last_index = SmiUntag(last_index); | 318 Node* const int_last_index = SmiUntag(last_index); |
| 335 | 319 |
| 336 Variable var_string_start(this, MachineType::PointerRepresentation()); | 320 Variable var_string_start(this, MachineType::PointerRepresentation()); |
| 337 Variable var_string_end(this, MachineType::PointerRepresentation()); | 321 Variable var_string_end(this, MachineType::PointerRepresentation()); |
| 338 Variable var_code(this, MachineRepresentation::kTagged); | 322 Variable var_code(this, MachineRepresentation::kTagged); |
| 339 | 323 |
| 340 { | 324 { |
| 341 Node* const int_string_length = SmiUntag(smi_string_length); | 325 Node* const int_string_length = SmiUntag(smi_string_length); |
| 342 | 326 Node* const direct_string_data = to_direct.PointerToData(&runtime); |
| 343 Node* const string_instance_type = var_string_instance_type.value(); | |
| 344 CSA_ASSERT(this, IsSequentialStringInstanceType(string_instance_type)); | |
| 345 | 327 |
| 346 Label next(this), if_isonebyte(this), if_istwobyte(this, Label::kDeferred); | 328 Label next(this), if_isonebyte(this), if_istwobyte(this, Label::kDeferred); |
| 347 Branch(IsOneByteStringInstanceType(string_instance_type), &if_isonebyte, | 329 Branch(IsOneByteStringInstanceType(to_direct.instance_type()), |
| 348 &if_istwobyte); | 330 &if_isonebyte, &if_istwobyte); |
| 349 | 331 |
| 350 Bind(&if_isonebyte); | 332 Bind(&if_isonebyte); |
| 351 { | 333 { |
| 352 const bool kIsOneByte = true; | 334 GetStringPointers(direct_string_data, to_direct.offset(), int_last_index, |
| 353 GetStringPointers(var_string.value(), var_string_offset.value(), | 335 int_string_length, String::ONE_BYTE_ENCODING, |
| 354 int_last_index, int_string_length, kIsOneByte, | |
| 355 &var_string_start, &var_string_end); | 336 &var_string_start, &var_string_end); |
| 356 var_code.Bind( | 337 var_code.Bind( |
| 357 LoadFixedArrayElement(data, JSRegExp::kIrregexpLatin1CodeIndex)); | 338 LoadFixedArrayElement(data, JSRegExp::kIrregexpLatin1CodeIndex)); |
| 358 Goto(&next); | 339 Goto(&next); |
| 359 } | 340 } |
| 360 | 341 |
| 361 Bind(&if_istwobyte); | 342 Bind(&if_istwobyte); |
| 362 { | 343 { |
| 363 const bool kIsOneByte = false; | 344 GetStringPointers(direct_string_data, to_direct.offset(), int_last_index, |
| 364 GetStringPointers(var_string.value(), var_string_offset.value(), | 345 int_string_length, String::TWO_BYTE_ENCODING, |
| 365 int_last_index, int_string_length, kIsOneByte, | |
| 366 &var_string_start, &var_string_end); | 346 &var_string_start, &var_string_end); |
| 367 var_code.Bind( | 347 var_code.Bind( |
| 368 LoadFixedArrayElement(data, JSRegExp::kIrregexpUC16CodeIndex)); | 348 LoadFixedArrayElement(data, JSRegExp::kIrregexpUC16CodeIndex)); |
| 369 Goto(&next); | 349 Goto(&next); |
| 370 } | 350 } |
| 371 | 351 |
| 372 Bind(&next); | 352 Bind(&next); |
| 373 } | 353 } |
| 374 | 354 |
| 375 // Check that the irregexp code has been generated for the actual string | 355 // Check that the irregexp code has been generated for the actual string |
| (...skipping 2465 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2841 Bind(&if_matched); | 2821 Bind(&if_matched); |
| 2842 { | 2822 { |
| 2843 Node* result = | 2823 Node* result = |
| 2844 ConstructNewResultFromMatchInfo(context, regexp, match_indices, string); | 2824 ConstructNewResultFromMatchInfo(context, regexp, match_indices, string); |
| 2845 Return(result); | 2825 Return(result); |
| 2846 } | 2826 } |
| 2847 } | 2827 } |
| 2848 | 2828 |
| 2849 } // namespace internal | 2829 } // namespace internal |
| 2850 } // namespace v8 | 2830 } // namespace v8 |
| OLD | NEW |