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.h" | 5 #include "src/builtins/builtins.h" |
6 #include "src/builtins/builtins-utils.h" | 6 #include "src/builtins/builtins-utils.h" |
7 | 7 |
8 #include "src/code-factory.h" | 8 #include "src/code-factory.h" |
9 | 9 |
10 namespace v8 { | 10 namespace v8 { |
(...skipping 276 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
287 CopyChars(result->GetChars() + one_byte_buffer.length(), | 287 CopyChars(result->GetChars() + one_byte_buffer.length(), |
288 two_byte_buffer.ToConstVector().start(), two_byte_buffer.length()); | 288 two_byte_buffer.ToConstVector().start(), two_byte_buffer.length()); |
289 | 289 |
290 return *result; | 290 return *result; |
291 } | 291 } |
292 | 292 |
293 // ES6 section 21.1.3.1 String.prototype.charAt ( pos ) | 293 // ES6 section 21.1.3.1 String.prototype.charAt ( pos ) |
294 void Builtins::Generate_StringPrototypeCharAt(CodeStubAssembler* assembler) { | 294 void Builtins::Generate_StringPrototypeCharAt(CodeStubAssembler* assembler) { |
295 typedef CodeStubAssembler::Label Label; | 295 typedef CodeStubAssembler::Label Label; |
296 typedef compiler::Node Node; | 296 typedef compiler::Node Node; |
297 typedef CodeStubAssembler::Variable Variable; | |
298 | 297 |
299 Node* receiver = assembler->Parameter(0); | 298 Node* receiver = assembler->Parameter(0); |
300 Node* position = assembler->Parameter(1); | 299 Node* position = assembler->Parameter(1); |
301 Node* context = assembler->Parameter(4); | 300 Node* context = assembler->Parameter(4); |
302 | 301 |
303 // Check that {receiver} is coercible to Object and convert it to a String. | 302 // Check that {receiver} is coercible to Object and convert it to a String. |
304 receiver = | 303 receiver = |
305 assembler->ToThisString(context, receiver, "String.prototype.charAt"); | 304 assembler->ToThisString(context, receiver, "String.prototype.charAt"); |
306 | 305 |
307 // Convert the {position} to a Smi and check that it's in bounds of the | 306 // Convert the {position} to a Smi and check that it's in bounds of the |
308 // {receiver}. | 307 // {receiver}. |
309 // TODO(bmeurer): Find an abstraction for this! | |
310 { | 308 { |
311 // Check if the {position} is already a Smi. | 309 Label return_emptystring(assembler, Label::kDeferred); |
312 Variable var_position(assembler, MachineRepresentation::kTagged); | 310 position = assembler->ToInteger(context, position, |
313 var_position.Bind(position); | 311 CodeStubAssembler::kTruncateMinusZero); |
314 Label if_positionissmi(assembler), | 312 assembler->GotoUnless(assembler->WordIsSmi(position), &return_emptystring); |
315 if_positionisnotsmi(assembler, Label::kDeferred); | |
316 assembler->Branch(assembler->WordIsSmi(position), &if_positionissmi, | |
317 &if_positionisnotsmi); | |
318 assembler->Bind(&if_positionisnotsmi); | |
319 { | |
320 // Convert the {position} to an Integer via the ToIntegerStub. | |
321 Node* index = assembler->ToInteger(context, position); | |
322 | |
323 // Check if the resulting {index} is now a Smi. | |
324 Label if_indexissmi(assembler, Label::kDeferred), | |
325 if_indexisnotsmi(assembler, Label::kDeferred); | |
326 assembler->Branch(assembler->WordIsSmi(index), &if_indexissmi, | |
327 &if_indexisnotsmi); | |
328 | |
329 assembler->Bind(&if_indexissmi); | |
330 { | |
331 var_position.Bind(index); | |
332 assembler->Goto(&if_positionissmi); | |
333 } | |
334 | |
335 assembler->Bind(&if_indexisnotsmi); | |
336 { | |
337 // The ToIntegerStub canonicalizes everything in Smi range to Smi | |
338 // representation, so any HeapNumber returned is not in Smi range. | |
339 // The only exception here is -0.0, which we treat as 0. | |
340 Node* index_value = assembler->LoadHeapNumberValue(index); | |
341 Label if_indexiszero(assembler, Label::kDeferred), | |
342 if_indexisnotzero(assembler, Label::kDeferred); | |
343 assembler->Branch(assembler->Float64Equal( | |
344 index_value, assembler->Float64Constant(0.0)), | |
345 &if_indexiszero, &if_indexisnotzero); | |
346 | |
347 assembler->Bind(&if_indexiszero); | |
348 { | |
349 var_position.Bind(assembler->SmiConstant(Smi::FromInt(0))); | |
350 assembler->Goto(&if_positionissmi); | |
351 } | |
352 | |
353 assembler->Bind(&if_indexisnotzero); | |
354 { | |
355 // The {index} is some other integral Number, that is definitely | |
356 // neither -0.0 nor in Smi range. | |
357 assembler->Return(assembler->EmptyStringConstant()); | |
358 } | |
359 } | |
360 } | |
361 assembler->Bind(&if_positionissmi); | |
362 position = var_position.value(); | |
363 | 313 |
364 // Determine the actual length of the {receiver} String. | 314 // Determine the actual length of the {receiver} String. |
365 Node* receiver_length = | 315 Node* receiver_length = |
366 assembler->LoadObjectField(receiver, String::kLengthOffset); | 316 assembler->LoadObjectField(receiver, String::kLengthOffset); |
367 | 317 |
368 // Return "" if the Smi {position} is outside the bounds of the {receiver}. | 318 // Return "" if the Smi {position} is outside the bounds of the {receiver}. |
369 Label if_positioninbounds(assembler), | 319 Label if_positioninbounds(assembler); |
370 if_positionnotinbounds(assembler, Label::kDeferred); | |
371 assembler->Branch(assembler->SmiAboveOrEqual(position, receiver_length), | 320 assembler->Branch(assembler->SmiAboveOrEqual(position, receiver_length), |
372 &if_positionnotinbounds, &if_positioninbounds); | 321 &return_emptystring, &if_positioninbounds); |
373 assembler->Bind(&if_positionnotinbounds); | 322 |
| 323 assembler->Bind(&return_emptystring); |
374 assembler->Return(assembler->EmptyStringConstant()); | 324 assembler->Return(assembler->EmptyStringConstant()); |
| 325 |
375 assembler->Bind(&if_positioninbounds); | 326 assembler->Bind(&if_positioninbounds); |
376 } | 327 } |
377 | 328 |
378 // Load the character code at the {position} from the {receiver}. | 329 // Load the character code at the {position} from the {receiver}. |
379 Node* code = assembler->StringCharCodeAt(receiver, position); | 330 Node* code = assembler->StringCharCodeAt(receiver, position); |
380 | 331 |
381 // And return the single character string with only that {code}. | 332 // And return the single character string with only that {code}. |
382 Node* result = assembler->StringFromCharCode(code); | 333 Node* result = assembler->StringFromCharCode(code); |
383 assembler->Return(result); | 334 assembler->Return(result); |
384 } | 335 } |
385 | 336 |
386 // ES6 section 21.1.3.2 String.prototype.charCodeAt ( pos ) | 337 // ES6 section 21.1.3.2 String.prototype.charCodeAt ( pos ) |
387 void Builtins::Generate_StringPrototypeCharCodeAt( | 338 void Builtins::Generate_StringPrototypeCharCodeAt( |
388 CodeStubAssembler* assembler) { | 339 CodeStubAssembler* assembler) { |
389 typedef CodeStubAssembler::Label Label; | 340 typedef CodeStubAssembler::Label Label; |
390 typedef compiler::Node Node; | 341 typedef compiler::Node Node; |
391 typedef CodeStubAssembler::Variable Variable; | |
392 | 342 |
393 Node* receiver = assembler->Parameter(0); | 343 Node* receiver = assembler->Parameter(0); |
394 Node* position = assembler->Parameter(1); | 344 Node* position = assembler->Parameter(1); |
395 Node* context = assembler->Parameter(4); | 345 Node* context = assembler->Parameter(4); |
396 | 346 |
397 // Check that {receiver} is coercible to Object and convert it to a String. | 347 // Check that {receiver} is coercible to Object and convert it to a String. |
398 receiver = | 348 receiver = |
399 assembler->ToThisString(context, receiver, "String.prototype.charCodeAt"); | 349 assembler->ToThisString(context, receiver, "String.prototype.charCodeAt"); |
400 | 350 |
401 // Convert the {position} to a Smi and check that it's in bounds of the | 351 // Convert the {position} to a Smi and check that it's in bounds of the |
402 // {receiver}. | 352 // {receiver}. |
403 // TODO(bmeurer): Find an abstraction for this! | |
404 { | 353 { |
405 // Check if the {position} is already a Smi. | 354 Label return_nan(assembler, Label::kDeferred); |
406 Variable var_position(assembler, MachineRepresentation::kTagged); | 355 position = assembler->ToInteger(context, position, |
407 var_position.Bind(position); | 356 CodeStubAssembler::kTruncateMinusZero); |
408 Label if_positionissmi(assembler), | 357 assembler->GotoUnless(assembler->WordIsSmi(position), &return_nan); |
409 if_positionisnotsmi(assembler, Label::kDeferred); | |
410 assembler->Branch(assembler->WordIsSmi(position), &if_positionissmi, | |
411 &if_positionisnotsmi); | |
412 assembler->Bind(&if_positionisnotsmi); | |
413 { | |
414 // Convert the {position} to an Integer via the ToIntegerStub. | |
415 Node* index = assembler->ToInteger(context, position); | |
416 | |
417 // Check if the resulting {index} is now a Smi. | |
418 Label if_indexissmi(assembler, Label::kDeferred), | |
419 if_indexisnotsmi(assembler, Label::kDeferred); | |
420 assembler->Branch(assembler->WordIsSmi(index), &if_indexissmi, | |
421 &if_indexisnotsmi); | |
422 | |
423 assembler->Bind(&if_indexissmi); | |
424 { | |
425 var_position.Bind(index); | |
426 assembler->Goto(&if_positionissmi); | |
427 } | |
428 | |
429 assembler->Bind(&if_indexisnotsmi); | |
430 { | |
431 // The ToIntegerStub canonicalizes everything in Smi range to Smi | |
432 // representation, so any HeapNumber returned is not in Smi range. | |
433 // The only exception here is -0.0, which we treat as 0. | |
434 Node* index_value = assembler->LoadHeapNumberValue(index); | |
435 Label if_indexiszero(assembler, Label::kDeferred), | |
436 if_indexisnotzero(assembler, Label::kDeferred); | |
437 assembler->Branch(assembler->Float64Equal( | |
438 index_value, assembler->Float64Constant(0.0)), | |
439 &if_indexiszero, &if_indexisnotzero); | |
440 | |
441 assembler->Bind(&if_indexiszero); | |
442 { | |
443 var_position.Bind(assembler->SmiConstant(Smi::FromInt(0))); | |
444 assembler->Goto(&if_positionissmi); | |
445 } | |
446 | |
447 assembler->Bind(&if_indexisnotzero); | |
448 { | |
449 // The {index} is some other integral Number, that is definitely | |
450 // neither -0.0 nor in Smi range. | |
451 assembler->Return(assembler->NaNConstant()); | |
452 } | |
453 } | |
454 } | |
455 assembler->Bind(&if_positionissmi); | |
456 position = var_position.value(); | |
457 | 358 |
458 // Determine the actual length of the {receiver} String. | 359 // Determine the actual length of the {receiver} String. |
459 Node* receiver_length = | 360 Node* receiver_length = |
460 assembler->LoadObjectField(receiver, String::kLengthOffset); | 361 assembler->LoadObjectField(receiver, String::kLengthOffset); |
461 | 362 |
462 // Return NaN if the Smi {position} is outside the bounds of the {receiver}. | 363 // Return NaN if the Smi {position} is outside the bounds of the {receiver}. |
463 Label if_positioninbounds(assembler), | 364 Label if_positioninbounds(assembler); |
464 if_positionnotinbounds(assembler, Label::kDeferred); | |
465 assembler->Branch(assembler->SmiAboveOrEqual(position, receiver_length), | 365 assembler->Branch(assembler->SmiAboveOrEqual(position, receiver_length), |
466 &if_positionnotinbounds, &if_positioninbounds); | 366 &return_nan, &if_positioninbounds); |
467 assembler->Bind(&if_positionnotinbounds); | 367 |
| 368 assembler->Bind(&return_nan); |
468 assembler->Return(assembler->NaNConstant()); | 369 assembler->Return(assembler->NaNConstant()); |
| 370 |
469 assembler->Bind(&if_positioninbounds); | 371 assembler->Bind(&if_positioninbounds); |
470 } | 372 } |
471 | 373 |
472 // Load the character at the {position} from the {receiver}. | 374 // Load the character at the {position} from the {receiver}. |
473 Node* value = assembler->StringCharCodeAt(receiver, position); | 375 Node* value = assembler->StringCharCodeAt(receiver, position); |
474 Node* result = assembler->SmiFromWord32(value); | 376 Node* result = assembler->SmiFromWord32(value); |
475 assembler->Return(result); | 377 assembler->Return(result); |
476 } | 378 } |
477 | 379 |
478 // ES6 section 21.1.3.9 | 380 // ES6 section 21.1.3.9 |
(...skipping 184 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
663 } | 565 } |
664 | 566 |
665 iterator->set_string(isolate->heap()->empty_string()); | 567 iterator->set_string(isolate->heap()->empty_string()); |
666 | 568 |
667 return *isolate->factory()->NewJSIteratorResult( | 569 return *isolate->factory()->NewJSIteratorResult( |
668 isolate->factory()->undefined_value(), true); | 570 isolate->factory()->undefined_value(), true); |
669 } | 571 } |
670 | 572 |
671 } // namespace internal | 573 } // namespace internal |
672 } // namespace v8 | 574 } // namespace v8 |
OLD | NEW |