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

Side by Side Diff: src/builtins.cc

Issue 2021143003: [builtins] Migrate String.fromCharCode to TurboFan code stub. (Closed) Base URL: https://chromium.googlesource.com/v8/v8.git@master
Patch Set: Created 4 years, 6 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 | « src/builtins.h ('k') | src/code-stub-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 2012 the V8 project authors. All rights reserved. 1 // Copyright 2012 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.h" 5 #include "src/builtins.h"
6 6
7 #include "src/api-arguments.h" 7 #include "src/api-arguments.h"
8 #include "src/api-natives.h" 8 #include "src/api-natives.h"
9 #include "src/api.h" 9 #include "src/api.h"
10 #include "src/base/once.h" 10 #include "src/base/once.h"
(...skipping 4291 matching lines...) Expand 10 before | Expand all | Expand 10 after
4302 BUILTIN(ObjectProtoToString) { 4302 BUILTIN(ObjectProtoToString) {
4303 HandleScope scope(isolate); 4303 HandleScope scope(isolate);
4304 Handle<Object> object = args.at<Object>(0); 4304 Handle<Object> object = args.at<Object>(0);
4305 RETURN_RESULT_OR_FAILURE(isolate, 4305 RETURN_RESULT_OR_FAILURE(isolate,
4306 Object::ObjectProtoToString(isolate, object)); 4306 Object::ObjectProtoToString(isolate, object));
4307 } 4307 }
4308 4308
4309 // ----------------------------------------------------------------------------- 4309 // -----------------------------------------------------------------------------
4310 // ES6 section 21.1 String Objects 4310 // ES6 section 21.1 String Objects
4311 4311
4312 namespace { 4312 // ES6 section 21.1.2.1 String.fromCharCode ( ...codeUnits )
4313 void Builtins::Generate_StringFromCharCode(CodeStubAssembler* assembler) {
4314 typedef CodeStubAssembler::Label Label;
4315 typedef compiler::Node Node;
4316 typedef CodeStubAssembler::Variable Variable;
4313 4317
4314 bool ToUint16(Handle<Object> value, uint16_t* result) { 4318 Node* code = assembler->Parameter(1);
4315 if (value->IsNumber() || Object::ToNumber(value).ToHandle(&value)) { 4319 Node* context = assembler->Parameter(4);
4316 *result = DoubleToUint32(value->Number()); 4320
4317 return true; 4321 // Check if we have exactly one arguments (plus the implicit receiver), i.e.
4322 // if the parent frame is not an arguments adaptor frame.
4323 Label if_oneargument(assembler), if_notoneargument(assembler);
4324 Node* parent_frame_pointer = assembler->LoadParentFramePointer();
4325 Node* parent_frame_type =
4326 assembler->Load(MachineType::Pointer(), parent_frame_pointer,
4327 assembler->IntPtrConstant(
4328 CommonFrameConstants::kContextOrFrameTypeOffset));
4329 assembler->Branch(
4330 assembler->WordEqual(
4331 parent_frame_type,
4332 assembler->SmiConstant(Smi::FromInt(StackFrame::ARGUMENTS_ADAPTOR))),
4333 &if_notoneargument, &if_oneargument);
4334
4335 assembler->Bind(&if_oneargument);
4336 {
4337 // Single argument case, perform fast single character string cache lookup
4338 // for one-byte code units, or fall back to creating a single character
4339 // string on the fly otherwise.
4340 Node* code32 = assembler->TruncateTaggedToWord32(context, code);
4341 Node* code16 = assembler->Word32And(
4342 code32, assembler->Int32Constant(String::kMaxUtf16CodeUnit));
4343 Node* result = assembler->StringFromCharCode(code16);
4344 assembler->Return(result);
4318 } 4345 }
4319 return false;
4320 }
4321 4346
4322 } // namespace 4347 assembler->Bind(&if_notoneargument);
4348 {
4349 // Determine the resulting string length.
4350 Node* parent_frame_length =
4351 assembler->Load(MachineType::Pointer(), parent_frame_pointer,
4352 assembler->IntPtrConstant(
4353 ArgumentsAdaptorFrameConstants::kLengthOffset));
4354 Node* length = assembler->SmiToWord(parent_frame_length);
4323 4355
4324 // ES6 21.1.2.1 String.fromCharCode ( ...codeUnits ) 4356 // Assume that the resulting string contains only one-byte characters.
4325 BUILTIN(StringFromCharCode) { 4357 Node* result = assembler->AllocateSeqOneByteString(context, length);
4326 HandleScope scope(isolate); 4358
4327 // Check resulting string length. 4359 // Truncate all input parameters and append them to the resulting string.
4328 int index = 0; 4360 Variable var_offset(assembler, MachineType::PointerRepresentation());
4329 Handle<String> result; 4361 Label loop(assembler, &var_offset), done_loop(assembler);
4330 int const length = args.length() - 1; 4362 var_offset.Bind(assembler->IntPtrConstant(0));
4331 if (length == 0) return isolate->heap()->empty_string(); 4363 assembler->Goto(&loop);
4332 DCHECK_LT(0, length); 4364 assembler->Bind(&loop);
4333 // Load the first character code. 4365 {
4334 uint16_t code; 4366 // Load the current {offset}.
4335 if (!ToUint16(args.at<Object>(1), &code)) return isolate->heap()->exception(); 4367 Node* offset = var_offset.value();
4336 // Assume that the resulting String contains only one byte characters. 4368
4337 if (code <= String::kMaxOneByteCharCodeU) { 4369 // Check if we're done with the string.
4338 // Check for single one-byte character fast case. 4370 assembler->GotoIf(assembler->WordEqual(offset, length), &done_loop);
4339 if (length == 1) { 4371
4340 return *isolate->factory()->LookupSingleCharacterStringFromCode(code); 4372 // Load the next code point and truncate it to a 16-bit value.
4341 } 4373 Node* code = assembler->Load(
4342 ASSIGN_RETURN_FAILURE_ON_EXCEPTION( 4374 MachineType::AnyTagged(), parent_frame_pointer,
4343 isolate, result, isolate->factory()->NewRawOneByteString(length)); 4375 assembler->IntPtrAdd(
4344 do { 4376 assembler->WordShl(assembler->IntPtrSub(length, offset),
4345 Handle<SeqOneByteString>::cast(result)->Set(index, code); 4377 assembler->IntPtrConstant(kPointerSizeLog2)),
4346 if (++index == length) break; 4378 assembler->IntPtrConstant(
4347 if (!ToUint16(args.at<Object>(1 + index), &code)) { 4379 CommonFrameConstants::kFixedFrameSizeAboveFp -
4348 return isolate->heap()->exception(); 4380 kPointerSize)));
4381 Node* code32 = assembler->TruncateTaggedToWord32(context, code);
4382 Node* code16 = assembler->Word32And(
4383 code32, assembler->Int32Constant(String::kMaxUtf16CodeUnit));
4384
4385 // Check if {code16} fits into a one-byte string.
4386 Label if_codeisonebyte(assembler), if_codeistwobyte(assembler);
4387 assembler->Branch(
4388 assembler->Int32LessThanOrEqual(
4389 code16, assembler->Int32Constant(String::kMaxOneByteCharCode)),
4390 &if_codeisonebyte, &if_codeistwobyte);
4391
4392 assembler->Bind(&if_codeisonebyte);
4393 {
4394 // The {code16} fits into the SeqOneByteString {result}.
4395 assembler->StoreNoWriteBarrier(
4396 MachineRepresentation::kWord8, result,
4397 assembler->IntPtrAdd(
4398 assembler->IntPtrConstant(SeqOneByteString::kHeaderSize -
4399 kHeapObjectTag),
4400 offset),
4401 code16);
4402 var_offset.Bind(
4403 assembler->IntPtrAdd(offset, assembler->IntPtrConstant(1)));
4404 assembler->Goto(&loop);
4349 } 4405 }
4350 } while (code <= String::kMaxOneByteCharCodeU); 4406
4351 } 4407 assembler->Bind(&if_codeistwobyte);
4352 // Check if all characters fit into the one byte range. 4408 {
4353 if (index < length) { 4409 // Allocate a SeqTwoByteString to hold the resulting string.
4354 // Fallback to two byte string. 4410 Node* cresult = assembler->AllocateSeqTwoByteString(context, length);
4355 Handle<String> new_result; 4411
4356 ASSIGN_RETURN_FAILURE_ON_EXCEPTION( 4412 // Copy all characters that were previously written to the
4357 isolate, new_result, isolate->factory()->NewRawTwoByteString(length)); 4413 // SeqOneByteString in {result} over to the new {cresult}.
4358 for (int new_index = 0; new_index < index; ++new_index) { 4414 Variable var_coffset(assembler, MachineType::PointerRepresentation());
4359 uint16_t new_code = 4415 Label cloop(assembler, &var_coffset), done_cloop(assembler);
4360 Handle<SeqOneByteString>::cast(result)->Get(new_index); 4416 var_coffset.Bind(assembler->IntPtrConstant(0));
4361 Handle<SeqTwoByteString>::cast(new_result)->Set(new_index, new_code); 4417 assembler->Goto(&cloop);
4362 } 4418 assembler->Bind(&cloop);
4363 while (true) { 4419 {
4364 Handle<SeqTwoByteString>::cast(new_result)->Set(index, code); 4420 Node* coffset = var_coffset.value();
4365 if (++index == length) break; 4421 assembler->GotoIf(assembler->WordEqual(coffset, offset), &done_cloop);
4366 if (!ToUint16(args.at<Object>(1 + index), &code)) { 4422 Node* ccode = assembler->Load(
4367 return isolate->heap()->exception(); 4423 MachineType::Uint8(), result,
4424 assembler->IntPtrAdd(
4425 assembler->IntPtrConstant(SeqOneByteString::kHeaderSize -
4426 kHeapObjectTag),
4427 coffset));
4428 assembler->StoreNoWriteBarrier(
4429 MachineRepresentation::kWord16, cresult,
4430 assembler->IntPtrAdd(
4431 assembler->IntPtrConstant(SeqTwoByteString::kHeaderSize -
4432 kHeapObjectTag),
4433 assembler->WordShl(coffset, 1)),
4434 ccode);
4435 var_coffset.Bind(
4436 assembler->IntPtrAdd(coffset, assembler->IntPtrConstant(1)));
4437 assembler->Goto(&cloop);
4438 }
4439
4440 // Write the pending {code16} to {offset}.
4441 assembler->Bind(&done_cloop);
4442 assembler->StoreNoWriteBarrier(
4443 MachineRepresentation::kWord16, cresult,
4444 assembler->IntPtrAdd(
4445 assembler->IntPtrConstant(SeqTwoByteString::kHeaderSize -
4446 kHeapObjectTag),
4447 assembler->WordShl(offset, 1)),
4448 code16);
4449
4450 // Copy the remaining parameters to the SeqTwoByteString {cresult}.
4451 Label floop(assembler, &var_offset), done_floop(assembler);
4452 assembler->Goto(&floop);
4453 assembler->Bind(&floop);
4454 {
4455 // Compute the next {offset}.
4456 Node* offset = assembler->IntPtrAdd(var_offset.value(),
4457 assembler->IntPtrConstant(1));
4458
4459 // Check if we're done with the string.
4460 assembler->GotoIf(assembler->WordEqual(offset, length), &done_floop);
4461
4462 // Load the next code point and truncate it to a 16-bit value.
4463 Node* code = assembler->Load(
4464 MachineType::AnyTagged(), parent_frame_pointer,
4465 assembler->IntPtrAdd(
4466 assembler->WordShl(
4467 assembler->IntPtrSub(length, offset),
4468 assembler->IntPtrConstant(kPointerSizeLog2)),
4469 assembler->IntPtrConstant(
4470 CommonFrameConstants::kFixedFrameSizeAboveFp -
4471 kPointerSize)));
4472 Node* code32 = assembler->TruncateTaggedToWord32(context, code);
4473 Node* code16 = assembler->Word32And(
4474 code32, assembler->Int32Constant(String::kMaxUtf16CodeUnit));
4475
4476 // Store the truncated {code} point at the next offset.
4477 assembler->StoreNoWriteBarrier(
4478 MachineRepresentation::kWord16, cresult,
4479 assembler->IntPtrAdd(
4480 assembler->IntPtrConstant(SeqTwoByteString::kHeaderSize -
4481 kHeapObjectTag),
4482 assembler->WordShl(offset, 1)),
4483 code16);
4484 var_offset.Bind(offset);
4485 assembler->Goto(&floop);
4486 }
4487
4488 // Return the SeqTwoByteString.
4489 assembler->Bind(&done_floop);
4490 assembler->Return(cresult);
4368 } 4491 }
4369 } 4492 }
4370 result = new_result; 4493
4494 assembler->Bind(&done_loop);
4495 assembler->Return(result);
4371 } 4496 }
4372 return *result;
4373 } 4497 }
4374 4498
4375 // ES6 section 21.1.3.1 String.prototype.charAt ( pos ) 4499 // ES6 section 21.1.3.1 String.prototype.charAt ( pos )
4376 void Builtins::Generate_StringPrototypeCharAt(CodeStubAssembler* assembler) { 4500 void Builtins::Generate_StringPrototypeCharAt(CodeStubAssembler* assembler) {
4377 typedef CodeStubAssembler::Label Label; 4501 typedef CodeStubAssembler::Label Label;
4378 typedef compiler::Node Node; 4502 typedef compiler::Node Node;
4379 typedef CodeStubAssembler::Variable Variable; 4503 typedef CodeStubAssembler::Variable Variable;
4380 4504
4381 Node* receiver = assembler->Parameter(0); 4505 Node* receiver = assembler->Parameter(0);
4382 Node* position = assembler->Parameter(1); 4506 Node* position = assembler->Parameter(1);
(...skipping 1222 matching lines...) Expand 10 before | Expand all | Expand 10 after
5605 BUILTIN_LIST_T(DEFINE_BUILTIN_ACCESSOR_T) 5729 BUILTIN_LIST_T(DEFINE_BUILTIN_ACCESSOR_T)
5606 BUILTIN_LIST_H(DEFINE_BUILTIN_ACCESSOR_H) 5730 BUILTIN_LIST_H(DEFINE_BUILTIN_ACCESSOR_H)
5607 BUILTIN_LIST_DEBUG_A(DEFINE_BUILTIN_ACCESSOR_A) 5731 BUILTIN_LIST_DEBUG_A(DEFINE_BUILTIN_ACCESSOR_A)
5608 #undef DEFINE_BUILTIN_ACCESSOR_C 5732 #undef DEFINE_BUILTIN_ACCESSOR_C
5609 #undef DEFINE_BUILTIN_ACCESSOR_A 5733 #undef DEFINE_BUILTIN_ACCESSOR_A
5610 #undef DEFINE_BUILTIN_ACCESSOR_T 5734 #undef DEFINE_BUILTIN_ACCESSOR_T
5611 #undef DEFINE_BUILTIN_ACCESSOR_H 5735 #undef DEFINE_BUILTIN_ACCESSOR_H
5612 5736
5613 } // namespace internal 5737 } // namespace internal
5614 } // namespace v8 5738 } // namespace v8
OLDNEW
« no previous file with comments | « src/builtins.h ('k') | src/code-stub-assembler.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698