OLD | NEW |
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 Loading... |
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 Loading... |
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 |
OLD | NEW |