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

Side by Side Diff: src/x64/code-stubs-x64.cc

Issue 144023009: Get rid of the unused native code StringAddStub. (Closed) Base URL: https://v8.googlecode.com/svn/branches/bleeding_edge
Patch Set: Created 6 years, 11 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 | Annotate | Revision Log
OLDNEW
1 // Copyright 2013 the V8 project authors. All rights reserved. 1 // Copyright 2013 the V8 project authors. All rights reserved.
2 // Redistribution and use in source and binary forms, with or without 2 // Redistribution and use in source and binary forms, with or without
3 // modification, are permitted provided that the following conditions are 3 // modification, are permitted provided that the following conditions are
4 // met: 4 // met:
5 // 5 //
6 // * Redistributions of source code must retain the above copyright 6 // * Redistributions of source code must retain the above copyright
7 // notice, this list of conditions and the following disclaimer. 7 // notice, this list of conditions and the following disclaimer.
8 // * Redistributions in binary form must reproduce the above 8 // * Redistributions in binary form must reproduce the above
9 // copyright notice, this list of conditions and the following 9 // copyright notice, this list of conditions and the following
10 // disclaimer in the documentation and/or other materials provided 10 // disclaimer in the documentation and/or other materials provided
(...skipping 332 matching lines...) Expand 10 before | Expand all | Expand 10 after
343 Isolate* isolate, 343 Isolate* isolate,
344 CodeStubInterfaceDescriptor* descriptor) { 344 CodeStubInterfaceDescriptor* descriptor) {
345 static Register registers[] = { rcx, rdx, rax }; 345 static Register registers[] = { rcx, rdx, rax };
346 descriptor->register_param_count_ = 3; 346 descriptor->register_param_count_ = 3;
347 descriptor->register_params_ = registers; 347 descriptor->register_params_ = registers;
348 descriptor->deoptimization_handler_ = 348 descriptor->deoptimization_handler_ =
349 FUNCTION_ADDR(BinaryOpIC_MissWithAllocationSite); 349 FUNCTION_ADDR(BinaryOpIC_MissWithAllocationSite);
350 } 350 }
351 351
352 352
353 void NewStringAddStub::InitializeInterfaceDescriptor( 353 void StringAddStub::InitializeInterfaceDescriptor(
354 Isolate* isolate, 354 Isolate* isolate,
355 CodeStubInterfaceDescriptor* descriptor) { 355 CodeStubInterfaceDescriptor* descriptor) {
356 static Register registers[] = { rdx, rax }; 356 static Register registers[] = { rdx, rax };
357 descriptor->register_param_count_ = 2; 357 descriptor->register_param_count_ = 2;
358 descriptor->register_params_ = registers; 358 descriptor->register_params_ = registers;
359 descriptor->deoptimization_handler_ = 359 descriptor->deoptimization_handler_ =
360 Runtime::FunctionForId(Runtime::kStringAdd)->entry; 360 Runtime::FunctionForId(Runtime::kStringAdd)->entry;
361 } 361 }
362 362
363 363
(...skipping 2873 matching lines...) Expand 10 before | Expand all | Expand 10 after
3237 if (!result_.is(rax)) { 3237 if (!result_.is(rax)) {
3238 __ movp(result_, rax); 3238 __ movp(result_, rax);
3239 } 3239 }
3240 call_helper.AfterCall(masm); 3240 call_helper.AfterCall(masm);
3241 __ jmp(&exit_); 3241 __ jmp(&exit_);
3242 3242
3243 __ Abort(kUnexpectedFallthroughFromCharFromCodeSlowCase); 3243 __ Abort(kUnexpectedFallthroughFromCharFromCodeSlowCase);
3244 } 3244 }
3245 3245
3246 3246
3247 void StringAddStub::Generate(MacroAssembler* masm) {
3248 Label call_runtime, call_builtin;
3249 Builtins::JavaScript builtin_id = Builtins::ADD;
3250
3251 // Load the two arguments.
3252 StackArgumentsAccessor args(rsp, 2, ARGUMENTS_DONT_CONTAIN_RECEIVER);
3253 __ movp(rax, args.GetArgumentOperand(0)); // First argument (left).
3254 __ movp(rdx, args.GetArgumentOperand(1)); // Second argument (right).
3255
3256 // Make sure that both arguments are strings if not known in advance.
3257 // Otherwise, at least one of the arguments is definitely a string,
3258 // and we convert the one that is not known to be a string.
3259 if ((flags_ & STRING_ADD_CHECK_BOTH) == STRING_ADD_CHECK_BOTH) {
3260 ASSERT((flags_ & STRING_ADD_CHECK_LEFT) == STRING_ADD_CHECK_LEFT);
3261 ASSERT((flags_ & STRING_ADD_CHECK_RIGHT) == STRING_ADD_CHECK_RIGHT);
3262 __ JumpIfSmi(rax, &call_runtime);
3263 __ CmpObjectType(rax, FIRST_NONSTRING_TYPE, r8);
3264 __ j(above_equal, &call_runtime);
3265
3266 // First argument is a a string, test second.
3267 __ JumpIfSmi(rdx, &call_runtime);
3268 __ CmpObjectType(rdx, FIRST_NONSTRING_TYPE, r9);
3269 __ j(above_equal, &call_runtime);
3270 } else if ((flags_ & STRING_ADD_CHECK_LEFT) == STRING_ADD_CHECK_LEFT) {
3271 ASSERT((flags_ & STRING_ADD_CHECK_RIGHT) == 0);
3272 GenerateConvertArgument(masm, 2 * kPointerSize, rax, rbx, rcx, rdi,
3273 &call_builtin);
3274 builtin_id = Builtins::STRING_ADD_RIGHT;
3275 } else if ((flags_ & STRING_ADD_CHECK_RIGHT) == STRING_ADD_CHECK_RIGHT) {
3276 ASSERT((flags_ & STRING_ADD_CHECK_LEFT) == 0);
3277 GenerateConvertArgument(masm, 1 * kPointerSize, rdx, rbx, rcx, rdi,
3278 &call_builtin);
3279 builtin_id = Builtins::STRING_ADD_LEFT;
3280 }
3281
3282 // Both arguments are strings.
3283 // rax: first string
3284 // rdx: second string
3285 // Check if either of the strings are empty. In that case return the other.
3286 Label second_not_zero_length, both_not_zero_length;
3287 __ movp(rcx, FieldOperand(rdx, String::kLengthOffset));
3288 __ SmiTest(rcx);
3289 __ j(not_zero, &second_not_zero_length, Label::kNear);
3290 // Second string is empty, result is first string which is already in rax.
3291 Counters* counters = masm->isolate()->counters();
3292 __ IncrementCounter(counters->string_add_native(), 1);
3293 __ ret(2 * kPointerSize);
3294 __ bind(&second_not_zero_length);
3295 __ movp(rbx, FieldOperand(rax, String::kLengthOffset));
3296 __ SmiTest(rbx);
3297 __ j(not_zero, &both_not_zero_length, Label::kNear);
3298 // First string is empty, result is second string which is in rdx.
3299 __ movp(rax, rdx);
3300 __ IncrementCounter(counters->string_add_native(), 1);
3301 __ ret(2 * kPointerSize);
3302
3303 // Both strings are non-empty.
3304 // rax: first string
3305 // rbx: length of first string
3306 // rcx: length of second string
3307 // rdx: second string
3308 // r8: map of first string (if flags_ == NO_STRING_ADD_FLAGS)
3309 // r9: map of second string (if flags_ == NO_STRING_ADD_FLAGS)
3310 Label string_add_flat_result, longer_than_two;
3311 __ bind(&both_not_zero_length);
3312
3313 // If arguments where known to be strings, maps are not loaded to r8 and r9
3314 // by the code above.
3315 if ((flags_ & STRING_ADD_CHECK_BOTH) != STRING_ADD_CHECK_BOTH) {
3316 __ movp(r8, FieldOperand(rax, HeapObject::kMapOffset));
3317 __ movp(r9, FieldOperand(rdx, HeapObject::kMapOffset));
3318 }
3319 // Get the instance types of the two strings as they will be needed soon.
3320 __ movzxbl(r8, FieldOperand(r8, Map::kInstanceTypeOffset));
3321 __ movzxbl(r9, FieldOperand(r9, Map::kInstanceTypeOffset));
3322
3323 // Look at the length of the result of adding the two strings.
3324 STATIC_ASSERT(String::kMaxLength <= Smi::kMaxValue / 2);
3325 __ SmiAdd(rbx, rbx, rcx);
3326 // Use the string table when adding two one character strings, as it
3327 // helps later optimizations to return an internalized string here.
3328 __ SmiCompare(rbx, Smi::FromInt(2));
3329 __ j(not_equal, &longer_than_two);
3330
3331 // Check that both strings are non-external ASCII strings.
3332 __ JumpIfBothInstanceTypesAreNotSequentialAscii(r8, r9, rbx, rcx,
3333 &call_runtime);
3334
3335 // Get the two characters forming the sub string.
3336 __ movzxbq(rbx, FieldOperand(rax, SeqOneByteString::kHeaderSize));
3337 __ movzxbq(rcx, FieldOperand(rdx, SeqOneByteString::kHeaderSize));
3338
3339 // Try to lookup two character string in string table. If it is not found
3340 // just allocate a new one.
3341 Label make_two_character_string, make_flat_ascii_string;
3342 StringHelper::GenerateTwoCharacterStringTableProbe(
3343 masm, rbx, rcx, r14, r11, rdi, r15, &make_two_character_string);
3344 __ IncrementCounter(counters->string_add_native(), 1);
3345 __ ret(2 * kPointerSize);
3346
3347 __ bind(&make_two_character_string);
3348 __ Set(rdi, 2);
3349 __ AllocateAsciiString(rax, rdi, r8, r9, r11, &call_runtime);
3350 // rbx - first byte: first character
3351 // rbx - second byte: *maybe* second character
3352 // Make sure that the second byte of rbx contains the second character.
3353 __ movzxbq(rcx, FieldOperand(rdx, SeqOneByteString::kHeaderSize));
3354 __ shll(rcx, Immediate(kBitsPerByte));
3355 __ orl(rbx, rcx);
3356 // Write both characters to the new string.
3357 __ movw(FieldOperand(rax, SeqOneByteString::kHeaderSize), rbx);
3358 __ IncrementCounter(counters->string_add_native(), 1);
3359 __ ret(2 * kPointerSize);
3360
3361 __ bind(&longer_than_two);
3362 // Check if resulting string will be flat.
3363 __ SmiCompare(rbx, Smi::FromInt(ConsString::kMinLength));
3364 __ j(below, &string_add_flat_result);
3365 // Handle exceptionally long strings in the runtime system.
3366 STATIC_ASSERT((String::kMaxLength & 0x80000000) == 0);
3367 __ SmiCompare(rbx, Smi::FromInt(String::kMaxLength));
3368 __ j(above, &call_runtime);
3369
3370 // If result is not supposed to be flat, allocate a cons string object. If
3371 // both strings are ASCII the result is an ASCII cons string.
3372 // rax: first string
3373 // rbx: length of resulting flat string
3374 // rdx: second string
3375 // r8: instance type of first string
3376 // r9: instance type of second string
3377 Label non_ascii, allocated, ascii_data;
3378 __ movl(rcx, r8);
3379 __ and_(rcx, r9);
3380 STATIC_ASSERT((kStringEncodingMask & kOneByteStringTag) != 0);
3381 STATIC_ASSERT((kStringEncodingMask & kTwoByteStringTag) == 0);
3382 __ testl(rcx, Immediate(kStringEncodingMask));
3383 __ j(zero, &non_ascii);
3384 __ bind(&ascii_data);
3385 // Allocate an ASCII cons string.
3386 __ AllocateAsciiConsString(rcx, rdi, no_reg, &call_runtime);
3387 __ bind(&allocated);
3388 // Fill the fields of the cons string.
3389 __ movp(FieldOperand(rcx, ConsString::kLengthOffset), rbx);
3390 __ movp(FieldOperand(rcx, ConsString::kHashFieldOffset),
3391 Immediate(String::kEmptyHashField));
3392
3393 Label skip_write_barrier, after_writing;
3394 ExternalReference high_promotion_mode = ExternalReference::
3395 new_space_high_promotion_mode_active_address(masm->isolate());
3396 __ Load(rbx, high_promotion_mode);
3397 __ testb(rbx, Immediate(1));
3398 __ j(zero, &skip_write_barrier);
3399
3400 __ movp(FieldOperand(rcx, ConsString::kFirstOffset), rax);
3401 __ RecordWriteField(rcx,
3402 ConsString::kFirstOffset,
3403 rax,
3404 rbx,
3405 kDontSaveFPRegs);
3406 __ movp(FieldOperand(rcx, ConsString::kSecondOffset), rdx);
3407 __ RecordWriteField(rcx,
3408 ConsString::kSecondOffset,
3409 rdx,
3410 rbx,
3411 kDontSaveFPRegs);
3412 __ jmp(&after_writing);
3413
3414 __ bind(&skip_write_barrier);
3415 __ movp(FieldOperand(rcx, ConsString::kFirstOffset), rax);
3416 __ movp(FieldOperand(rcx, ConsString::kSecondOffset), rdx);
3417
3418 __ bind(&after_writing);
3419
3420 __ movp(rax, rcx);
3421 __ IncrementCounter(counters->string_add_native(), 1);
3422 __ ret(2 * kPointerSize);
3423 __ bind(&non_ascii);
3424 // At least one of the strings is two-byte. Check whether it happens
3425 // to contain only one byte characters.
3426 // rcx: first instance type AND second instance type.
3427 // r8: first instance type.
3428 // r9: second instance type.
3429 __ testb(rcx, Immediate(kOneByteDataHintMask));
3430 __ j(not_zero, &ascii_data);
3431 __ xor_(r8, r9);
3432 STATIC_ASSERT(kOneByteStringTag != 0 && kOneByteDataHintTag != 0);
3433 __ andb(r8, Immediate(kOneByteStringTag | kOneByteDataHintTag));
3434 __ cmpb(r8, Immediate(kOneByteStringTag | kOneByteDataHintTag));
3435 __ j(equal, &ascii_data);
3436 // Allocate a two byte cons string.
3437 __ AllocateTwoByteConsString(rcx, rdi, no_reg, &call_runtime);
3438 __ jmp(&allocated);
3439
3440 // We cannot encounter sliced strings or cons strings here since:
3441 STATIC_ASSERT(SlicedString::kMinLength >= ConsString::kMinLength);
3442 // Handle creating a flat result from either external or sequential strings.
3443 // Locate the first characters' locations.
3444 // rax: first string
3445 // rbx: length of resulting flat string as smi
3446 // rdx: second string
3447 // r8: instance type of first string
3448 // r9: instance type of first string
3449 Label first_prepared, second_prepared;
3450 Label first_is_sequential, second_is_sequential;
3451 __ bind(&string_add_flat_result);
3452
3453 __ SmiToInteger32(r14, FieldOperand(rax, SeqString::kLengthOffset));
3454 // r14: length of first string
3455 STATIC_ASSERT(kSeqStringTag == 0);
3456 __ testb(r8, Immediate(kStringRepresentationMask));
3457 __ j(zero, &first_is_sequential, Label::kNear);
3458 // Rule out short external string and load string resource.
3459 STATIC_ASSERT(kShortExternalStringTag != 0);
3460 __ testb(r8, Immediate(kShortExternalStringMask));
3461 __ j(not_zero, &call_runtime);
3462 __ movp(rcx, FieldOperand(rax, ExternalString::kResourceDataOffset));
3463 __ jmp(&first_prepared, Label::kNear);
3464 __ bind(&first_is_sequential);
3465 STATIC_ASSERT(SeqOneByteString::kHeaderSize == SeqTwoByteString::kHeaderSize);
3466 __ lea(rcx, FieldOperand(rax, SeqOneByteString::kHeaderSize));
3467 __ bind(&first_prepared);
3468
3469 // Check whether both strings have same encoding.
3470 __ xorl(r8, r9);
3471 __ testb(r8, Immediate(kStringEncodingMask));
3472 __ j(not_zero, &call_runtime);
3473
3474 __ SmiToInteger32(r15, FieldOperand(rdx, SeqString::kLengthOffset));
3475 // r15: length of second string
3476 STATIC_ASSERT(kSeqStringTag == 0);
3477 __ testb(r9, Immediate(kStringRepresentationMask));
3478 __ j(zero, &second_is_sequential, Label::kNear);
3479 // Rule out short external string and load string resource.
3480 STATIC_ASSERT(kShortExternalStringTag != 0);
3481 __ testb(r9, Immediate(kShortExternalStringMask));
3482 __ j(not_zero, &call_runtime);
3483 __ movp(rdx, FieldOperand(rdx, ExternalString::kResourceDataOffset));
3484 __ jmp(&second_prepared, Label::kNear);
3485 __ bind(&second_is_sequential);
3486 STATIC_ASSERT(SeqOneByteString::kHeaderSize == SeqTwoByteString::kHeaderSize);
3487 __ lea(rdx, FieldOperand(rdx, SeqOneByteString::kHeaderSize));
3488 __ bind(&second_prepared);
3489
3490 Label non_ascii_string_add_flat_result;
3491 // r9: instance type of second string
3492 // First string and second string have the same encoding.
3493 STATIC_ASSERT(kTwoByteStringTag == 0);
3494 __ SmiToInteger32(rbx, rbx);
3495 __ testb(r9, Immediate(kStringEncodingMask));
3496 __ j(zero, &non_ascii_string_add_flat_result);
3497
3498 __ bind(&make_flat_ascii_string);
3499 // Both strings are ASCII strings. As they are short they are both flat.
3500 __ AllocateAsciiString(rax, rbx, rdi, r8, r9, &call_runtime);
3501 // rax: result string
3502 // Locate first character of result.
3503 __ lea(rbx, FieldOperand(rax, SeqOneByteString::kHeaderSize));
3504 // rcx: first char of first string
3505 // rbx: first character of result
3506 // r14: length of first string
3507 StringHelper::GenerateCopyCharacters(masm, rbx, rcx, r14, true);
3508 // rbx: next character of result
3509 // rdx: first char of second string
3510 // r15: length of second string
3511 StringHelper::GenerateCopyCharacters(masm, rbx, rdx, r15, true);
3512 __ IncrementCounter(counters->string_add_native(), 1);
3513 __ ret(2 * kPointerSize);
3514
3515 __ bind(&non_ascii_string_add_flat_result);
3516 // Both strings are ASCII strings. As they are short they are both flat.
3517 __ AllocateTwoByteString(rax, rbx, rdi, r8, r9, &call_runtime);
3518 // rax: result string
3519 // Locate first character of result.
3520 __ lea(rbx, FieldOperand(rax, SeqTwoByteString::kHeaderSize));
3521 // rcx: first char of first string
3522 // rbx: first character of result
3523 // r14: length of first string
3524 StringHelper::GenerateCopyCharacters(masm, rbx, rcx, r14, false);
3525 // rbx: next character of result
3526 // rdx: first char of second string
3527 // r15: length of second string
3528 StringHelper::GenerateCopyCharacters(masm, rbx, rdx, r15, false);
3529 __ IncrementCounter(counters->string_add_native(), 1);
3530 __ ret(2 * kPointerSize);
3531
3532 // Just jump to runtime to add the two strings.
3533 __ bind(&call_runtime);
3534 __ TailCallRuntime(Runtime::kStringAdd, 2, 1);
3535
3536 if (call_builtin.is_linked()) {
3537 __ bind(&call_builtin);
3538 __ InvokeBuiltin(builtin_id, JUMP_FUNCTION);
3539 }
3540 }
3541
3542
3543 void StringAddStub::GenerateRegisterArgsPush(MacroAssembler* masm) {
3544 __ push(rax);
3545 __ push(rdx);
3546 }
3547
3548
3549 void StringAddStub::GenerateRegisterArgsPop(MacroAssembler* masm,
3550 Register temp) {
3551 __ PopReturnAddressTo(temp);
3552 __ pop(rdx);
3553 __ pop(rax);
3554 __ PushReturnAddressFrom(temp);
3555 }
3556
3557
3558 void StringAddStub::GenerateConvertArgument(MacroAssembler* masm,
3559 int stack_offset,
3560 Register arg,
3561 Register scratch1,
3562 Register scratch2,
3563 Register scratch3,
3564 Label* slow) {
3565 // First check if the argument is already a string.
3566 Label not_string, done;
3567 __ JumpIfSmi(arg, &not_string);
3568 __ CmpObjectType(arg, FIRST_NONSTRING_TYPE, scratch1);
3569 __ j(below, &done);
3570
3571 // Check the number to string cache.
3572 __ bind(&not_string);
3573 // Puts the cached result into scratch1.
3574 __ LookupNumberStringCache(arg, scratch1, scratch2, scratch3, slow);
3575 __ movp(arg, scratch1);
3576 __ movp(Operand(rsp, stack_offset), arg);
3577 __ bind(&done);
3578 }
3579
3580
3581 void StringHelper::GenerateCopyCharacters(MacroAssembler* masm, 3247 void StringHelper::GenerateCopyCharacters(MacroAssembler* masm,
3582 Register dest, 3248 Register dest,
3583 Register src, 3249 Register src,
3584 Register count, 3250 Register count,
3585 bool ascii) { 3251 bool ascii) {
3586 Label loop; 3252 Label loop;
3587 __ bind(&loop); 3253 __ bind(&loop);
3588 // This loop just copies one character at a time, as it is only used for very 3254 // This loop just copies one character at a time, as it is only used for very
3589 // short strings. 3255 // short strings.
3590 if (ascii) { 3256 if (ascii) {
(...skipping 2133 matching lines...) Expand 10 before | Expand all | Expand 10 after
5724 __ bind(&fast_elements_case); 5390 __ bind(&fast_elements_case);
5725 GenerateCase(masm, FAST_ELEMENTS); 5391 GenerateCase(masm, FAST_ELEMENTS);
5726 } 5392 }
5727 5393
5728 5394
5729 #undef __ 5395 #undef __
5730 5396
5731 } } // namespace v8::internal 5397 } } // namespace v8::internal
5732 5398
5733 #endif // V8_TARGET_ARCH_X64 5399 #endif // V8_TARGET_ARCH_X64
OLDNEW
« src/code-stubs.h ('K') | « src/x64/code-stubs-x64.h ('k') | src/x64/full-codegen-x64.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698