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

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

Issue 143633007: A64: Synchronize with r18764. (Closed) Base URL: https://v8.googlecode.com/svn/branches/experimental/a64
Patch Set: Created 6 years, 10 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
« no previous file with comments | « src/ia32/code-stubs-ia32.h ('k') | src/ia32/full-codegen-ia32.cc » ('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 // 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 36 matching lines...) Expand 10 before | Expand all | Expand 10 after
47 Isolate* isolate, 47 Isolate* isolate,
48 CodeStubInterfaceDescriptor* descriptor) { 48 CodeStubInterfaceDescriptor* descriptor) {
49 static Register registers[] = { ebx }; 49 static Register registers[] = { ebx };
50 descriptor->register_param_count_ = 1; 50 descriptor->register_param_count_ = 1;
51 descriptor->register_params_ = registers; 51 descriptor->register_params_ = registers;
52 descriptor->deoptimization_handler_ = 52 descriptor->deoptimization_handler_ =
53 Runtime::FunctionForId(Runtime::kNewClosureFromStubFailure)->entry; 53 Runtime::FunctionForId(Runtime::kNewClosureFromStubFailure)->entry;
54 } 54 }
55 55
56 56
57 void FastNewContextStub::InitializeInterfaceDescriptor(
58 Isolate* isolate,
59 CodeStubInterfaceDescriptor* descriptor) {
60 static Register registers[] = { edi };
61 descriptor->register_param_count_ = 1;
62 descriptor->register_params_ = registers;
63 descriptor->deoptimization_handler_ = NULL;
64 }
65
66
57 void ToNumberStub::InitializeInterfaceDescriptor( 67 void ToNumberStub::InitializeInterfaceDescriptor(
58 Isolate* isolate, 68 Isolate* isolate,
59 CodeStubInterfaceDescriptor* descriptor) { 69 CodeStubInterfaceDescriptor* descriptor) {
60 static Register registers[] = { eax }; 70 static Register registers[] = { eax };
61 descriptor->register_param_count_ = 1; 71 descriptor->register_param_count_ = 1;
62 descriptor->register_params_ = registers; 72 descriptor->register_params_ = registers;
63 descriptor->deoptimization_handler_ = NULL; 73 descriptor->deoptimization_handler_ = NULL;
64 } 74 }
65 75
66 76
(...skipping 117 matching lines...) Expand 10 before | Expand all | Expand 10 after
184 } 194 }
185 195
186 196
187 static void InitializeArrayConstructorDescriptor( 197 static void InitializeArrayConstructorDescriptor(
188 Isolate* isolate, 198 Isolate* isolate,
189 CodeStubInterfaceDescriptor* descriptor, 199 CodeStubInterfaceDescriptor* descriptor,
190 int constant_stack_parameter_count) { 200 int constant_stack_parameter_count) {
191 // register state 201 // register state
192 // eax -- number of arguments 202 // eax -- number of arguments
193 // edi -- function 203 // edi -- function
194 // ebx -- type info cell with elements kind 204 // ebx -- allocation site with elements kind
195 static Register registers_variable_args[] = { edi, ebx, eax }; 205 static Register registers_variable_args[] = { edi, ebx, eax };
196 static Register registers_no_args[] = { edi, ebx }; 206 static Register registers_no_args[] = { edi, ebx };
197 207
198 if (constant_stack_parameter_count == 0) { 208 if (constant_stack_parameter_count == 0) {
199 descriptor->register_param_count_ = 2; 209 descriptor->register_param_count_ = 2;
200 descriptor->register_params_ = registers_no_args; 210 descriptor->register_params_ = registers_no_args;
201 } else { 211 } else {
202 // stack param count needs (constructor pointer, and single argument) 212 // stack param count needs (constructor pointer, and single argument)
203 descriptor->handler_arguments_mode_ = PASS_ARGUMENTS; 213 descriptor->handler_arguments_mode_ = PASS_ARGUMENTS;
204 descriptor->stack_parameter_count_ = eax; 214 descriptor->stack_parameter_count_ = eax;
(...skipping 141 matching lines...) Expand 10 before | Expand all | Expand 10 after
346 Isolate* isolate, 356 Isolate* isolate,
347 CodeStubInterfaceDescriptor* descriptor) { 357 CodeStubInterfaceDescriptor* descriptor) {
348 static Register registers[] = { ecx, edx, eax }; 358 static Register registers[] = { ecx, edx, eax };
349 descriptor->register_param_count_ = 3; 359 descriptor->register_param_count_ = 3;
350 descriptor->register_params_ = registers; 360 descriptor->register_params_ = registers;
351 descriptor->deoptimization_handler_ = 361 descriptor->deoptimization_handler_ =
352 FUNCTION_ADDR(BinaryOpIC_MissWithAllocationSite); 362 FUNCTION_ADDR(BinaryOpIC_MissWithAllocationSite);
353 } 363 }
354 364
355 365
356 void NewStringAddStub::InitializeInterfaceDescriptor( 366 void StringAddStub::InitializeInterfaceDescriptor(
357 Isolate* isolate, 367 Isolate* isolate,
358 CodeStubInterfaceDescriptor* descriptor) { 368 CodeStubInterfaceDescriptor* descriptor) {
359 static Register registers[] = { edx, eax }; 369 static Register registers[] = { edx, eax };
360 descriptor->register_param_count_ = 2; 370 descriptor->register_param_count_ = 2;
361 descriptor->register_params_ = registers; 371 descriptor->register_params_ = registers;
362 descriptor->deoptimization_handler_ = 372 descriptor->deoptimization_handler_ =
363 Runtime::FunctionForId(Runtime::kStringAdd)->entry; 373 Runtime::FunctionForId(Runtime::kStringAdd)->entry;
364 } 374 }
365 375
366 376
(...skipping 67 matching lines...) Expand 10 before | Expand all | Expand 10 after
434 __ push(descriptor->register_params_[i]); 444 __ push(descriptor->register_params_[i]);
435 } 445 }
436 ExternalReference miss = descriptor->miss_handler(); 446 ExternalReference miss = descriptor->miss_handler();
437 __ CallExternalReference(miss, descriptor->register_param_count_); 447 __ CallExternalReference(miss, descriptor->register_param_count_);
438 } 448 }
439 449
440 __ ret(0); 450 __ ret(0);
441 } 451 }
442 452
443 453
444 void FastNewContextStub::Generate(MacroAssembler* masm) {
445 // Try to allocate the context in new space.
446 Label gc;
447 int length = slots_ + Context::MIN_CONTEXT_SLOTS;
448 __ Allocate((length * kPointerSize) + FixedArray::kHeaderSize,
449 eax, ebx, ecx, &gc, TAG_OBJECT);
450
451 // Get the function from the stack.
452 __ mov(ecx, Operand(esp, 1 * kPointerSize));
453
454 // Set up the object header.
455 Factory* factory = masm->isolate()->factory();
456 __ mov(FieldOperand(eax, HeapObject::kMapOffset),
457 factory->function_context_map());
458 __ mov(FieldOperand(eax, Context::kLengthOffset),
459 Immediate(Smi::FromInt(length)));
460
461 // Set up the fixed slots.
462 __ Set(ebx, Immediate(0)); // Set to NULL.
463 __ mov(Operand(eax, Context::SlotOffset(Context::CLOSURE_INDEX)), ecx);
464 __ mov(Operand(eax, Context::SlotOffset(Context::PREVIOUS_INDEX)), esi);
465 __ mov(Operand(eax, Context::SlotOffset(Context::EXTENSION_INDEX)), ebx);
466
467 // Copy the global object from the previous context.
468 __ mov(ebx, Operand(esi, Context::SlotOffset(Context::GLOBAL_OBJECT_INDEX)));
469 __ mov(Operand(eax, Context::SlotOffset(Context::GLOBAL_OBJECT_INDEX)), ebx);
470
471 // Initialize the rest of the slots to undefined.
472 __ mov(ebx, factory->undefined_value());
473 for (int i = Context::MIN_CONTEXT_SLOTS; i < length; i++) {
474 __ mov(Operand(eax, Context::SlotOffset(i)), ebx);
475 }
476
477 // Return and remove the on-stack parameter.
478 __ mov(esi, eax);
479 __ ret(1 * kPointerSize);
480
481 // Need to collect. Call into runtime system.
482 __ bind(&gc);
483 __ TailCallRuntime(Runtime::kNewFunctionContext, 1, 1);
484 }
485
486
487 void FastNewBlockContextStub::Generate(MacroAssembler* masm) { 454 void FastNewBlockContextStub::Generate(MacroAssembler* masm) {
488 // Stack layout on entry: 455 // Stack layout on entry:
489 // 456 //
490 // [esp + (1 * kPointerSize)]: function 457 // [esp + (1 * kPointerSize)]: function
491 // [esp + (2 * kPointerSize)]: serialized scope info 458 // [esp + (2 * kPointerSize)]: serialized scope info
492 459
493 // Try to allocate the context in new space. 460 // Try to allocate the context in new space.
494 Label gc; 461 Label gc;
495 int length = slots_ + Context::MIN_CONTEXT_SLOTS; 462 int length = slots_ + Context::MIN_CONTEXT_SLOTS;
496 __ Allocate(FixedArray::SizeFor(length), eax, ebx, ecx, &gc, TAG_OBJECT); 463 __ Allocate(FixedArray::SizeFor(length), eax, ebx, ecx, &gc, TAG_OBJECT);
(...skipping 2873 matching lines...) Expand 10 before | Expand all | Expand 10 after
3370 if (!result_.is(eax)) { 3337 if (!result_.is(eax)) {
3371 __ mov(result_, eax); 3338 __ mov(result_, eax);
3372 } 3339 }
3373 call_helper.AfterCall(masm); 3340 call_helper.AfterCall(masm);
3374 __ jmp(&exit_); 3341 __ jmp(&exit_);
3375 3342
3376 __ Abort(kUnexpectedFallthroughFromCharFromCodeSlowCase); 3343 __ Abort(kUnexpectedFallthroughFromCharFromCodeSlowCase);
3377 } 3344 }
3378 3345
3379 3346
3380 void StringAddStub::Generate(MacroAssembler* masm) {
3381 Label call_runtime, call_builtin;
3382 Builtins::JavaScript builtin_id = Builtins::ADD;
3383
3384 // Load the two arguments.
3385 __ mov(eax, Operand(esp, 2 * kPointerSize)); // First argument.
3386 __ mov(edx, Operand(esp, 1 * kPointerSize)); // Second argument.
3387
3388 // Make sure that both arguments are strings if not known in advance.
3389 // Otherwise, at least one of the arguments is definitely a string,
3390 // and we convert the one that is not known to be a string.
3391 if ((flags_ & STRING_ADD_CHECK_BOTH) == STRING_ADD_CHECK_BOTH) {
3392 ASSERT((flags_ & STRING_ADD_CHECK_LEFT) == STRING_ADD_CHECK_LEFT);
3393 ASSERT((flags_ & STRING_ADD_CHECK_RIGHT) == STRING_ADD_CHECK_RIGHT);
3394 __ JumpIfSmi(eax, &call_runtime);
3395 __ CmpObjectType(eax, FIRST_NONSTRING_TYPE, ebx);
3396 __ j(above_equal, &call_runtime);
3397
3398 // First argument is a a string, test second.
3399 __ JumpIfSmi(edx, &call_runtime);
3400 __ CmpObjectType(edx, FIRST_NONSTRING_TYPE, ebx);
3401 __ j(above_equal, &call_runtime);
3402 } else if ((flags_ & STRING_ADD_CHECK_LEFT) == STRING_ADD_CHECK_LEFT) {
3403 ASSERT((flags_ & STRING_ADD_CHECK_RIGHT) == 0);
3404 GenerateConvertArgument(masm, 2 * kPointerSize, eax, ebx, ecx, edi,
3405 &call_builtin);
3406 builtin_id = Builtins::STRING_ADD_RIGHT;
3407 } else if ((flags_ & STRING_ADD_CHECK_RIGHT) == STRING_ADD_CHECK_RIGHT) {
3408 ASSERT((flags_ & STRING_ADD_CHECK_LEFT) == 0);
3409 GenerateConvertArgument(masm, 1 * kPointerSize, edx, ebx, ecx, edi,
3410 &call_builtin);
3411 builtin_id = Builtins::STRING_ADD_LEFT;
3412 }
3413
3414 // Both arguments are strings.
3415 // eax: first string
3416 // edx: second string
3417 // Check if either of the strings are empty. In that case return the other.
3418 Label second_not_zero_length, both_not_zero_length;
3419 __ mov(ecx, FieldOperand(edx, String::kLengthOffset));
3420 STATIC_ASSERT(kSmiTag == 0);
3421 __ test(ecx, ecx);
3422 __ j(not_zero, &second_not_zero_length, Label::kNear);
3423 // Second string is empty, result is first string which is already in eax.
3424 Counters* counters = masm->isolate()->counters();
3425 __ IncrementCounter(counters->string_add_native(), 1);
3426 __ ret(2 * kPointerSize);
3427 __ bind(&second_not_zero_length);
3428 __ mov(ebx, FieldOperand(eax, String::kLengthOffset));
3429 STATIC_ASSERT(kSmiTag == 0);
3430 __ test(ebx, ebx);
3431 __ j(not_zero, &both_not_zero_length, Label::kNear);
3432 // First string is empty, result is second string which is in edx.
3433 __ mov(eax, edx);
3434 __ IncrementCounter(counters->string_add_native(), 1);
3435 __ ret(2 * kPointerSize);
3436
3437 // Both strings are non-empty.
3438 // eax: first string
3439 // ebx: length of first string as a smi
3440 // ecx: length of second string as a smi
3441 // edx: second string
3442 // Look at the length of the result of adding the two strings.
3443 Label string_add_flat_result, longer_than_two;
3444 __ bind(&both_not_zero_length);
3445 __ add(ebx, ecx);
3446 STATIC_ASSERT(Smi::kMaxValue == String::kMaxLength);
3447 // Handle exceptionally long strings in the runtime system.
3448 __ j(overflow, &call_runtime);
3449 // Use the string table when adding two one character strings, as it
3450 // helps later optimizations to return an internalized string here.
3451 __ cmp(ebx, Immediate(Smi::FromInt(2)));
3452 __ j(not_equal, &longer_than_two);
3453
3454 // Check that both strings are non-external ASCII strings.
3455 __ JumpIfNotBothSequentialAsciiStrings(eax, edx, ebx, ecx, &call_runtime);
3456
3457 // Get the two characters forming the new string.
3458 __ movzx_b(ebx, FieldOperand(eax, SeqOneByteString::kHeaderSize));
3459 __ movzx_b(ecx, FieldOperand(edx, SeqOneByteString::kHeaderSize));
3460
3461 // Try to lookup two character string in string table. If it is not found
3462 // just allocate a new one.
3463 Label make_two_character_string, make_two_character_string_no_reload;
3464 StringHelper::GenerateTwoCharacterStringTableProbe(
3465 masm, ebx, ecx, eax, edx, edi,
3466 &make_two_character_string_no_reload, &make_two_character_string);
3467 __ IncrementCounter(counters->string_add_native(), 1);
3468 __ ret(2 * kPointerSize);
3469
3470 // Allocate a two character string.
3471 __ bind(&make_two_character_string);
3472 // Reload the arguments.
3473 __ mov(eax, Operand(esp, 2 * kPointerSize)); // First argument.
3474 __ mov(edx, Operand(esp, 1 * kPointerSize)); // Second argument.
3475 // Get the two characters forming the new string.
3476 __ movzx_b(ebx, FieldOperand(eax, SeqOneByteString::kHeaderSize));
3477 __ movzx_b(ecx, FieldOperand(edx, SeqOneByteString::kHeaderSize));
3478 __ bind(&make_two_character_string_no_reload);
3479 __ IncrementCounter(counters->string_add_make_two_char(), 1);
3480 __ AllocateAsciiString(eax, 2, edi, edx, &call_runtime);
3481 // Pack both characters in ebx.
3482 __ shl(ecx, kBitsPerByte);
3483 __ or_(ebx, ecx);
3484 // Set the characters in the new string.
3485 __ mov_w(FieldOperand(eax, SeqOneByteString::kHeaderSize), ebx);
3486 __ IncrementCounter(counters->string_add_native(), 1);
3487 __ ret(2 * kPointerSize);
3488
3489 __ bind(&longer_than_two);
3490 // Check if resulting string will be flat.
3491 __ cmp(ebx, Immediate(Smi::FromInt(ConsString::kMinLength)));
3492 __ j(below, &string_add_flat_result);
3493
3494 // If result is not supposed to be flat allocate a cons string object. If both
3495 // strings are ASCII the result is an ASCII cons string.
3496 Label non_ascii, allocated, ascii_data;
3497 __ mov(edi, FieldOperand(eax, HeapObject::kMapOffset));
3498 __ movzx_b(ecx, FieldOperand(edi, Map::kInstanceTypeOffset));
3499 __ mov(edi, FieldOperand(edx, HeapObject::kMapOffset));
3500 __ movzx_b(edi, FieldOperand(edi, Map::kInstanceTypeOffset));
3501 __ and_(ecx, edi);
3502 STATIC_ASSERT((kStringEncodingMask & kOneByteStringTag) != 0);
3503 STATIC_ASSERT((kStringEncodingMask & kTwoByteStringTag) == 0);
3504 __ test(ecx, Immediate(kStringEncodingMask));
3505 __ j(zero, &non_ascii);
3506 __ bind(&ascii_data);
3507 // Allocate an ASCII cons string.
3508 __ AllocateAsciiConsString(ecx, edi, no_reg, &call_runtime);
3509 __ bind(&allocated);
3510 // Fill the fields of the cons string.
3511 __ AssertSmi(ebx);
3512 __ mov(FieldOperand(ecx, ConsString::kLengthOffset), ebx);
3513 __ mov(FieldOperand(ecx, ConsString::kHashFieldOffset),
3514 Immediate(String::kEmptyHashField));
3515
3516 Label skip_write_barrier, after_writing;
3517 ExternalReference high_promotion_mode = ExternalReference::
3518 new_space_high_promotion_mode_active_address(masm->isolate());
3519 __ test(Operand::StaticVariable(high_promotion_mode), Immediate(1));
3520 __ j(zero, &skip_write_barrier);
3521
3522 __ mov(FieldOperand(ecx, ConsString::kFirstOffset), eax);
3523 __ RecordWriteField(ecx,
3524 ConsString::kFirstOffset,
3525 eax,
3526 ebx,
3527 kDontSaveFPRegs);
3528 __ mov(FieldOperand(ecx, ConsString::kSecondOffset), edx);
3529 __ RecordWriteField(ecx,
3530 ConsString::kSecondOffset,
3531 edx,
3532 ebx,
3533 kDontSaveFPRegs);
3534 __ jmp(&after_writing);
3535
3536 __ bind(&skip_write_barrier);
3537 __ mov(FieldOperand(ecx, ConsString::kFirstOffset), eax);
3538 __ mov(FieldOperand(ecx, ConsString::kSecondOffset), edx);
3539
3540 __ bind(&after_writing);
3541
3542 __ mov(eax, ecx);
3543 __ IncrementCounter(counters->string_add_native(), 1);
3544 __ ret(2 * kPointerSize);
3545 __ bind(&non_ascii);
3546 // At least one of the strings is two-byte. Check whether it happens
3547 // to contain only one byte characters.
3548 // ecx: first instance type AND second instance type.
3549 // edi: second instance type.
3550 __ test(ecx, Immediate(kOneByteDataHintMask));
3551 __ j(not_zero, &ascii_data);
3552 __ mov(ecx, FieldOperand(eax, HeapObject::kMapOffset));
3553 __ movzx_b(ecx, FieldOperand(ecx, Map::kInstanceTypeOffset));
3554 __ xor_(edi, ecx);
3555 STATIC_ASSERT(kOneByteStringTag != 0 && kOneByteDataHintTag != 0);
3556 __ and_(edi, kOneByteStringTag | kOneByteDataHintTag);
3557 __ cmp(edi, kOneByteStringTag | kOneByteDataHintTag);
3558 __ j(equal, &ascii_data);
3559 // Allocate a two byte cons string.
3560 __ AllocateTwoByteConsString(ecx, edi, no_reg, &call_runtime);
3561 __ jmp(&allocated);
3562
3563 // We cannot encounter sliced strings or cons strings here since:
3564 STATIC_ASSERT(SlicedString::kMinLength >= ConsString::kMinLength);
3565 // Handle creating a flat result from either external or sequential strings.
3566 // Locate the first characters' locations.
3567 // eax: first string
3568 // ebx: length of resulting flat string as a smi
3569 // edx: second string
3570 Label first_prepared, second_prepared;
3571 Label first_is_sequential, second_is_sequential;
3572 __ bind(&string_add_flat_result);
3573 __ mov(ecx, FieldOperand(eax, HeapObject::kMapOffset));
3574 __ movzx_b(ecx, FieldOperand(ecx, Map::kInstanceTypeOffset));
3575 // ecx: instance type of first string
3576 STATIC_ASSERT(kSeqStringTag == 0);
3577 __ test_b(ecx, kStringRepresentationMask);
3578 __ j(zero, &first_is_sequential, Label::kNear);
3579 // Rule out short external string and load string resource.
3580 STATIC_ASSERT(kShortExternalStringTag != 0);
3581 __ test_b(ecx, kShortExternalStringMask);
3582 __ j(not_zero, &call_runtime);
3583 __ mov(eax, FieldOperand(eax, ExternalString::kResourceDataOffset));
3584 STATIC_ASSERT(SeqOneByteString::kHeaderSize == SeqTwoByteString::kHeaderSize);
3585 __ jmp(&first_prepared, Label::kNear);
3586 __ bind(&first_is_sequential);
3587 __ add(eax, Immediate(SeqOneByteString::kHeaderSize - kHeapObjectTag));
3588 __ bind(&first_prepared);
3589
3590 __ mov(edi, FieldOperand(edx, HeapObject::kMapOffset));
3591 __ movzx_b(edi, FieldOperand(edi, Map::kInstanceTypeOffset));
3592 // Check whether both strings have same encoding.
3593 // edi: instance type of second string
3594 __ xor_(ecx, edi);
3595 __ test_b(ecx, kStringEncodingMask);
3596 __ j(not_zero, &call_runtime);
3597 STATIC_ASSERT(kSeqStringTag == 0);
3598 __ test_b(edi, kStringRepresentationMask);
3599 __ j(zero, &second_is_sequential, Label::kNear);
3600 // Rule out short external string and load string resource.
3601 STATIC_ASSERT(kShortExternalStringTag != 0);
3602 __ test_b(edi, kShortExternalStringMask);
3603 __ j(not_zero, &call_runtime);
3604 __ mov(edx, FieldOperand(edx, ExternalString::kResourceDataOffset));
3605 STATIC_ASSERT(SeqOneByteString::kHeaderSize == SeqTwoByteString::kHeaderSize);
3606 __ jmp(&second_prepared, Label::kNear);
3607 __ bind(&second_is_sequential);
3608 __ add(edx, Immediate(SeqOneByteString::kHeaderSize - kHeapObjectTag));
3609 __ bind(&second_prepared);
3610
3611 // Push the addresses of both strings' first characters onto the stack.
3612 __ push(edx);
3613 __ push(eax);
3614
3615 Label non_ascii_string_add_flat_result, call_runtime_drop_two;
3616 // edi: instance type of second string
3617 // First string and second string have the same encoding.
3618 STATIC_ASSERT(kTwoByteStringTag == 0);
3619 __ test_b(edi, kStringEncodingMask);
3620 __ j(zero, &non_ascii_string_add_flat_result);
3621
3622 // Both strings are ASCII strings.
3623 // ebx: length of resulting flat string as a smi
3624 __ SmiUntag(ebx);
3625 __ AllocateAsciiString(eax, ebx, ecx, edx, edi, &call_runtime_drop_two);
3626 // eax: result string
3627 __ mov(ecx, eax);
3628 // Locate first character of result.
3629 __ add(ecx, Immediate(SeqOneByteString::kHeaderSize - kHeapObjectTag));
3630 // Load first argument's length and first character location. Account for
3631 // values currently on the stack when fetching arguments from it.
3632 __ mov(edx, Operand(esp, 4 * kPointerSize));
3633 __ mov(edi, FieldOperand(edx, String::kLengthOffset));
3634 __ SmiUntag(edi);
3635 __ pop(edx);
3636 // eax: result string
3637 // ecx: first character of result
3638 // edx: first char of first argument
3639 // edi: length of first argument
3640 StringHelper::GenerateCopyCharacters(masm, ecx, edx, edi, ebx, true);
3641 // Load second argument's length and first character location. Account for
3642 // values currently on the stack when fetching arguments from it.
3643 __ mov(edx, Operand(esp, 2 * kPointerSize));
3644 __ mov(edi, FieldOperand(edx, String::kLengthOffset));
3645 __ SmiUntag(edi);
3646 __ pop(edx);
3647 // eax: result string
3648 // ecx: next character of result
3649 // edx: first char of second argument
3650 // edi: length of second argument
3651 StringHelper::GenerateCopyCharacters(masm, ecx, edx, edi, ebx, true);
3652 __ IncrementCounter(counters->string_add_native(), 1);
3653 __ ret(2 * kPointerSize);
3654
3655 // Handle creating a flat two byte result.
3656 // eax: first string - known to be two byte
3657 // ebx: length of resulting flat string as a smi
3658 // edx: second string
3659 __ bind(&non_ascii_string_add_flat_result);
3660 // Both strings are two byte strings.
3661 __ SmiUntag(ebx);
3662 __ AllocateTwoByteString(eax, ebx, ecx, edx, edi, &call_runtime_drop_two);
3663 // eax: result string
3664 __ mov(ecx, eax);
3665 // Locate first character of result.
3666 __ add(ecx, Immediate(SeqTwoByteString::kHeaderSize - kHeapObjectTag));
3667 // Load second argument's length and first character location. Account for
3668 // values currently on the stack when fetching arguments from it.
3669 __ mov(edx, Operand(esp, 4 * kPointerSize));
3670 __ mov(edi, FieldOperand(edx, String::kLengthOffset));
3671 __ SmiUntag(edi);
3672 __ pop(edx);
3673 // eax: result string
3674 // ecx: first character of result
3675 // edx: first char of first argument
3676 // edi: length of first argument
3677 StringHelper::GenerateCopyCharacters(masm, ecx, edx, edi, ebx, false);
3678 // Load second argument's length and first character location. Account for
3679 // values currently on the stack when fetching arguments from it.
3680 __ mov(edx, Operand(esp, 2 * kPointerSize));
3681 __ mov(edi, FieldOperand(edx, String::kLengthOffset));
3682 __ SmiUntag(edi);
3683 __ pop(edx);
3684 // eax: result string
3685 // ecx: next character of result
3686 // edx: first char of second argument
3687 // edi: length of second argument
3688 StringHelper::GenerateCopyCharacters(masm, ecx, edx, edi, ebx, false);
3689 __ IncrementCounter(counters->string_add_native(), 1);
3690 __ ret(2 * kPointerSize);
3691
3692 // Recover stack pointer before jumping to runtime.
3693 __ bind(&call_runtime_drop_two);
3694 __ Drop(2);
3695 // Just jump to runtime to add the two strings.
3696 __ bind(&call_runtime);
3697 __ TailCallRuntime(Runtime::kStringAdd, 2, 1);
3698
3699 if (call_builtin.is_linked()) {
3700 __ bind(&call_builtin);
3701 __ InvokeBuiltin(builtin_id, JUMP_FUNCTION);
3702 }
3703 }
3704
3705
3706 void StringAddStub::GenerateRegisterArgsPush(MacroAssembler* masm) {
3707 __ push(eax);
3708 __ push(edx);
3709 }
3710
3711
3712 void StringAddStub::GenerateRegisterArgsPop(MacroAssembler* masm,
3713 Register temp) {
3714 __ pop(temp);
3715 __ pop(edx);
3716 __ pop(eax);
3717 __ push(temp);
3718 }
3719
3720
3721 void StringAddStub::GenerateConvertArgument(MacroAssembler* masm,
3722 int stack_offset,
3723 Register arg,
3724 Register scratch1,
3725 Register scratch2,
3726 Register scratch3,
3727 Label* slow) {
3728 // First check if the argument is already a string.
3729 Label not_string, done;
3730 __ JumpIfSmi(arg, &not_string);
3731 __ CmpObjectType(arg, FIRST_NONSTRING_TYPE, scratch1);
3732 __ j(below, &done);
3733
3734 // Check the number to string cache.
3735 __ bind(&not_string);
3736 // Puts the cached result into scratch1.
3737 __ LookupNumberStringCache(arg, scratch1, scratch2, scratch3, slow);
3738 __ mov(arg, scratch1);
3739 __ mov(Operand(esp, stack_offset), arg);
3740 __ bind(&done);
3741 }
3742
3743
3744 void StringHelper::GenerateCopyCharacters(MacroAssembler* masm,
3745 Register dest,
3746 Register src,
3747 Register count,
3748 Register scratch,
3749 bool ascii) {
3750 Label loop;
3751 __ bind(&loop);
3752 // This loop just copies one character at a time, as it is only used for very
3753 // short strings.
3754 if (ascii) {
3755 __ mov_b(scratch, Operand(src, 0));
3756 __ mov_b(Operand(dest, 0), scratch);
3757 __ add(src, Immediate(1));
3758 __ add(dest, Immediate(1));
3759 } else {
3760 __ mov_w(scratch, Operand(src, 0));
3761 __ mov_w(Operand(dest, 0), scratch);
3762 __ add(src, Immediate(2));
3763 __ add(dest, Immediate(2));
3764 }
3765 __ sub(count, Immediate(1));
3766 __ j(not_zero, &loop);
3767 }
3768
3769
3770 void StringHelper::GenerateCopyCharactersREP(MacroAssembler* masm, 3347 void StringHelper::GenerateCopyCharactersREP(MacroAssembler* masm,
3771 Register dest, 3348 Register dest,
3772 Register src, 3349 Register src,
3773 Register count, 3350 Register count,
3774 Register scratch, 3351 Register scratch,
3775 bool ascii) { 3352 bool ascii) {
3776 // Copy characters using rep movs of doublewords. 3353 // Copy characters using rep movs of doublewords.
3777 // The destination is aligned on a 4 byte boundary because we are 3354 // The destination is aligned on a 4 byte boundary because we are
3778 // copying to the beginning of a newly allocated string. 3355 // copying to the beginning of a newly allocated string.
3779 ASSERT(dest.is(edi)); // rep movs destination 3356 ASSERT(dest.is(edi)); // rep movs destination
(...skipping 40 matching lines...) Expand 10 before | Expand all | Expand 10 after
3820 __ mov_b(Operand(dest, 0), scratch); 3397 __ mov_b(Operand(dest, 0), scratch);
3821 __ add(src, Immediate(1)); 3398 __ add(src, Immediate(1));
3822 __ add(dest, Immediate(1)); 3399 __ add(dest, Immediate(1));
3823 __ sub(count, Immediate(1)); 3400 __ sub(count, Immediate(1));
3824 __ j(not_zero, &loop); 3401 __ j(not_zero, &loop);
3825 3402
3826 __ bind(&done); 3403 __ bind(&done);
3827 } 3404 }
3828 3405
3829 3406
3830 void StringHelper::GenerateTwoCharacterStringTableProbe(MacroAssembler* masm,
3831 Register c1,
3832 Register c2,
3833 Register scratch1,
3834 Register scratch2,
3835 Register scratch3,
3836 Label* not_probed,
3837 Label* not_found) {
3838 // Register scratch3 is the general scratch register in this function.
3839 Register scratch = scratch3;
3840
3841 // Make sure that both characters are not digits as such strings has a
3842 // different hash algorithm. Don't try to look for these in the string table.
3843 Label not_array_index;
3844 __ mov(scratch, c1);
3845 __ sub(scratch, Immediate(static_cast<int>('0')));
3846 __ cmp(scratch, Immediate(static_cast<int>('9' - '0')));
3847 __ j(above, &not_array_index, Label::kNear);
3848 __ mov(scratch, c2);
3849 __ sub(scratch, Immediate(static_cast<int>('0')));
3850 __ cmp(scratch, Immediate(static_cast<int>('9' - '0')));
3851 __ j(below_equal, not_probed);
3852
3853 __ bind(&not_array_index);
3854 // Calculate the two character string hash.
3855 Register hash = scratch1;
3856 GenerateHashInit(masm, hash, c1, scratch);
3857 GenerateHashAddCharacter(masm, hash, c2, scratch);
3858 GenerateHashGetHash(masm, hash, scratch);
3859
3860 // Collect the two characters in a register.
3861 Register chars = c1;
3862 __ shl(c2, kBitsPerByte);
3863 __ or_(chars, c2);
3864
3865 // chars: two character string, char 1 in byte 0 and char 2 in byte 1.
3866 // hash: hash of two character string.
3867
3868 // Load the string table.
3869 Register string_table = c2;
3870 __ LoadRoot(string_table, Heap::kStringTableRootIndex);
3871
3872 // Calculate capacity mask from the string table capacity.
3873 Register mask = scratch2;
3874 __ mov(mask, FieldOperand(string_table, StringTable::kCapacityOffset));
3875 __ SmiUntag(mask);
3876 __ sub(mask, Immediate(1));
3877
3878 // Registers
3879 // chars: two character string, char 1 in byte 0 and char 2 in byte 1.
3880 // hash: hash of two character string
3881 // string_table: string table
3882 // mask: capacity mask
3883 // scratch: -
3884
3885 // Perform a number of probes in the string table.
3886 static const int kProbes = 4;
3887 Label found_in_string_table;
3888 Label next_probe[kProbes], next_probe_pop_mask[kProbes];
3889 Register candidate = scratch; // Scratch register contains candidate.
3890 for (int i = 0; i < kProbes; i++) {
3891 // Calculate entry in string table.
3892 __ mov(scratch, hash);
3893 if (i > 0) {
3894 __ add(scratch, Immediate(StringTable::GetProbeOffset(i)));
3895 }
3896 __ and_(scratch, mask);
3897
3898 // Load the entry from the string table.
3899 STATIC_ASSERT(StringTable::kEntrySize == 1);
3900 __ mov(candidate,
3901 FieldOperand(string_table,
3902 scratch,
3903 times_pointer_size,
3904 StringTable::kElementsStartOffset));
3905
3906 // If entry is undefined no string with this hash can be found.
3907 Factory* factory = masm->isolate()->factory();
3908 __ cmp(candidate, factory->undefined_value());
3909 __ j(equal, not_found);
3910 __ cmp(candidate, factory->the_hole_value());
3911 __ j(equal, &next_probe[i]);
3912
3913 // If length is not 2 the string is not a candidate.
3914 __ cmp(FieldOperand(candidate, String::kLengthOffset),
3915 Immediate(Smi::FromInt(2)));
3916 __ j(not_equal, &next_probe[i]);
3917
3918 // As we are out of registers save the mask on the stack and use that
3919 // register as a temporary.
3920 __ push(mask);
3921 Register temp = mask;
3922
3923 // Check that the candidate is a non-external ASCII string.
3924 __ mov(temp, FieldOperand(candidate, HeapObject::kMapOffset));
3925 __ movzx_b(temp, FieldOperand(temp, Map::kInstanceTypeOffset));
3926 __ JumpIfInstanceTypeIsNotSequentialAscii(
3927 temp, temp, &next_probe_pop_mask[i]);
3928
3929 // Check if the two characters match.
3930 __ mov(temp, FieldOperand(candidate, SeqOneByteString::kHeaderSize));
3931 __ and_(temp, 0x0000ffff);
3932 __ cmp(chars, temp);
3933 __ j(equal, &found_in_string_table);
3934 __ bind(&next_probe_pop_mask[i]);
3935 __ pop(mask);
3936 __ bind(&next_probe[i]);
3937 }
3938
3939 // No matching 2 character string found by probing.
3940 __ jmp(not_found);
3941
3942 // Scratch register contains result when we fall through to here.
3943 Register result = candidate;
3944 __ bind(&found_in_string_table);
3945 __ pop(mask); // Pop saved mask from the stack.
3946 if (!result.is(eax)) {
3947 __ mov(eax, result);
3948 }
3949 }
3950
3951
3952 void StringHelper::GenerateHashInit(MacroAssembler* masm, 3407 void StringHelper::GenerateHashInit(MacroAssembler* masm,
3953 Register hash, 3408 Register hash,
3954 Register character, 3409 Register character,
3955 Register scratch) { 3410 Register scratch) {
3956 // hash = (seed + character) + ((seed + character) << 10); 3411 // hash = (seed + character) + ((seed + character) << 10);
3957 if (Serializer::enabled()) { 3412 if (Serializer::enabled()) {
3958 __ LoadRoot(scratch, Heap::kHashSeedRootIndex); 3413 __ LoadRoot(scratch, Heap::kHashSeedRootIndex);
3959 __ SmiUntag(scratch); 3414 __ SmiUntag(scratch);
3960 __ add(scratch, character); 3415 __ add(scratch, character);
3961 __ mov(hash, scratch); 3416 __ mov(hash, scratch);
(...skipping 444 matching lines...) Expand 10 before | Expand all | Expand 10 after
4406 __ push(ecx); 3861 __ push(ecx);
4407 GenerateCompareFlatAsciiStrings(masm, edx, eax, ecx, ebx, edi); 3862 GenerateCompareFlatAsciiStrings(masm, edx, eax, ecx, ebx, edi);
4408 3863
4409 // Call the runtime; it returns -1 (less), 0 (equal), or 1 (greater) 3864 // Call the runtime; it returns -1 (less), 0 (equal), or 1 (greater)
4410 // tagged as a small integer. 3865 // tagged as a small integer.
4411 __ bind(&runtime); 3866 __ bind(&runtime);
4412 __ TailCallRuntime(Runtime::kStringCompare, 2, 1); 3867 __ TailCallRuntime(Runtime::kStringCompare, 2, 1);
4413 } 3868 }
4414 3869
4415 3870
3871 void ArrayPushStub::Generate(MacroAssembler* masm) {
3872 int argc = arguments_count();
3873
3874 if (argc == 0) {
3875 // Noop, return the length.
3876 __ mov(eax, FieldOperand(edx, JSArray::kLengthOffset));
3877 __ ret((argc + 1) * kPointerSize);
3878 return;
3879 }
3880
3881 Isolate* isolate = masm->isolate();
3882
3883 if (argc != 1) {
3884 __ TailCallExternalReference(
3885 ExternalReference(Builtins::c_ArrayPush, isolate), argc + 1, 1);
3886 return;
3887 }
3888
3889 Label call_builtin, attempt_to_grow_elements, with_write_barrier;
3890
3891 // Get the elements array of the object.
3892 __ mov(edi, FieldOperand(edx, JSArray::kElementsOffset));
3893
3894 if (IsFastSmiOrObjectElementsKind(elements_kind())) {
3895 // Check that the elements are in fast mode and writable.
3896 __ cmp(FieldOperand(edi, HeapObject::kMapOffset),
3897 isolate->factory()->fixed_array_map());
3898 __ j(not_equal, &call_builtin);
3899 }
3900
3901 // Get the array's length into eax and calculate new length.
3902 __ mov(eax, FieldOperand(edx, JSArray::kLengthOffset));
3903 STATIC_ASSERT(kSmiTagSize == 1);
3904 STATIC_ASSERT(kSmiTag == 0);
3905 __ add(eax, Immediate(Smi::FromInt(argc)));
3906
3907 // Get the elements' length into ecx.
3908 __ mov(ecx, FieldOperand(edi, FixedArray::kLengthOffset));
3909
3910 // Check if we could survive without allocation.
3911 __ cmp(eax, ecx);
3912
3913 if (IsFastSmiOrObjectElementsKind(elements_kind())) {
3914 __ j(greater, &attempt_to_grow_elements);
3915
3916 // Check if value is a smi.
3917 __ mov(ecx, Operand(esp, argc * kPointerSize));
3918 __ JumpIfNotSmi(ecx, &with_write_barrier);
3919
3920 // Store the value.
3921 __ mov(FieldOperand(edi, eax, times_half_pointer_size,
3922 FixedArray::kHeaderSize - argc * kPointerSize),
3923 ecx);
3924 } else {
3925 __ j(greater, &call_builtin);
3926
3927 __ mov(ecx, Operand(esp, argc * kPointerSize));
3928 __ StoreNumberToDoubleElements(
3929 ecx, edi, eax, ecx, xmm0, &call_builtin, true, argc * kDoubleSize);
3930 }
3931
3932 // Save new length.
3933 __ mov(FieldOperand(edx, JSArray::kLengthOffset), eax);
3934 __ ret((argc + 1) * kPointerSize);
3935
3936 if (IsFastDoubleElementsKind(elements_kind())) {
3937 __ bind(&call_builtin);
3938 __ TailCallExternalReference(
3939 ExternalReference(Builtins::c_ArrayPush, isolate), argc + 1, 1);
3940 return;
3941 }
3942
3943 __ bind(&with_write_barrier);
3944
3945 if (IsFastSmiElementsKind(elements_kind())) {
3946 if (FLAG_trace_elements_transitions) __ jmp(&call_builtin);
3947
3948 __ cmp(FieldOperand(ecx, HeapObject::kMapOffset),
3949 isolate->factory()->heap_number_map());
3950 __ j(equal, &call_builtin);
3951
3952 ElementsKind target_kind = IsHoleyElementsKind(elements_kind())
3953 ? FAST_HOLEY_ELEMENTS : FAST_ELEMENTS;
3954 __ mov(ebx, ContextOperand(esi, Context::GLOBAL_OBJECT_INDEX));
3955 __ mov(ebx, FieldOperand(ebx, GlobalObject::kNativeContextOffset));
3956 __ mov(ebx, ContextOperand(ebx, Context::JS_ARRAY_MAPS_INDEX));
3957 const int header_size = FixedArrayBase::kHeaderSize;
3958 // Verify that the object can be transitioned in place.
3959 const int origin_offset = header_size + elements_kind() * kPointerSize;
3960 __ mov(edi, FieldOperand(ebx, origin_offset));
3961 __ cmp(edi, FieldOperand(edx, HeapObject::kMapOffset));
3962 __ j(not_equal, &call_builtin);
3963
3964 const int target_offset = header_size + target_kind * kPointerSize;
3965 __ mov(ebx, FieldOperand(ebx, target_offset));
3966 ElementsTransitionGenerator::GenerateMapChangeElementsTransition(
3967 masm, DONT_TRACK_ALLOCATION_SITE, NULL);
3968 // Restore edi used as a scratch register for the write barrier used while
3969 // setting the map.
3970 __ mov(edi, FieldOperand(edx, JSArray::kElementsOffset));
3971 }
3972
3973 // Save new length.
3974 __ mov(FieldOperand(edx, JSArray::kLengthOffset), eax);
3975
3976 // Store the value.
3977 __ lea(edx, FieldOperand(edi, eax, times_half_pointer_size,
3978 FixedArray::kHeaderSize - argc * kPointerSize));
3979 __ mov(Operand(edx, 0), ecx);
3980
3981 __ RecordWrite(edi, edx, ecx, kDontSaveFPRegs, EMIT_REMEMBERED_SET,
3982 OMIT_SMI_CHECK);
3983
3984 __ ret((argc + 1) * kPointerSize);
3985
3986 __ bind(&attempt_to_grow_elements);
3987 if (!FLAG_inline_new) {
3988 __ bind(&call_builtin);
3989 __ TailCallExternalReference(
3990 ExternalReference(Builtins::c_ArrayPush, isolate), argc + 1, 1);
3991 return;
3992 }
3993
3994 __ mov(ebx, Operand(esp, argc * kPointerSize));
3995 // Growing elements that are SMI-only requires special handling in case the
3996 // new element is non-Smi. For now, delegate to the builtin.
3997 if (IsFastSmiElementsKind(elements_kind())) {
3998 __ JumpIfNotSmi(ebx, &call_builtin);
3999 }
4000
4001 // We could be lucky and the elements array could be at the top of new-space.
4002 // In this case we can just grow it in place by moving the allocation pointer
4003 // up.
4004 ExternalReference new_space_allocation_top =
4005 ExternalReference::new_space_allocation_top_address(isolate);
4006 ExternalReference new_space_allocation_limit =
4007 ExternalReference::new_space_allocation_limit_address(isolate);
4008
4009 const int kAllocationDelta = 4;
4010 ASSERT(kAllocationDelta >= argc);
4011 // Load top.
4012 __ mov(ecx, Operand::StaticVariable(new_space_allocation_top));
4013
4014 // Check if it's the end of elements.
4015 __ lea(edx, FieldOperand(edi, eax, times_half_pointer_size,
4016 FixedArray::kHeaderSize - argc * kPointerSize));
4017 __ cmp(edx, ecx);
4018 __ j(not_equal, &call_builtin);
4019 __ add(ecx, Immediate(kAllocationDelta * kPointerSize));
4020 __ cmp(ecx, Operand::StaticVariable(new_space_allocation_limit));
4021 __ j(above, &call_builtin);
4022
4023 // We fit and could grow elements.
4024 __ mov(Operand::StaticVariable(new_space_allocation_top), ecx);
4025
4026 // Push the argument...
4027 __ mov(Operand(edx, 0), ebx);
4028 // ... and fill the rest with holes.
4029 for (int i = 1; i < kAllocationDelta; i++) {
4030 __ mov(Operand(edx, i * kPointerSize),
4031 isolate->factory()->the_hole_value());
4032 }
4033
4034 if (IsFastObjectElementsKind(elements_kind())) {
4035 // We know the elements array is in new space so we don't need the
4036 // remembered set, but we just pushed a value onto it so we may have to tell
4037 // the incremental marker to rescan the object that we just grew. We don't
4038 // need to worry about the holes because they are in old space and already
4039 // marked black.
4040 __ RecordWrite(edi, edx, ebx, kDontSaveFPRegs, OMIT_REMEMBERED_SET);
4041 }
4042
4043 // Restore receiver to edx as finish sequence assumes it's here.
4044 __ mov(edx, Operand(esp, (argc + 1) * kPointerSize));
4045
4046 // Increment element's and array's sizes.
4047 __ add(FieldOperand(edi, FixedArray::kLengthOffset),
4048 Immediate(Smi::FromInt(kAllocationDelta)));
4049
4050 // NOTE: This only happen in new-space, where we don't care about the
4051 // black-byte-count on pages. Otherwise we should update that too if the
4052 // object is black.
4053
4054 __ mov(FieldOperand(edx, JSArray::kLengthOffset), eax);
4055 __ ret((argc + 1) * kPointerSize);
4056
4057 __ bind(&call_builtin);
4058 __ TailCallExternalReference(
4059 ExternalReference(Builtins::c_ArrayPush, isolate), argc + 1, 1);
4060 }
4061
4062
4416 void BinaryOpICWithAllocationSiteStub::Generate(MacroAssembler* masm) { 4063 void BinaryOpICWithAllocationSiteStub::Generate(MacroAssembler* masm) {
4417 // ----------- S t a t e ------------- 4064 // ----------- S t a t e -------------
4418 // -- edx : left 4065 // -- edx : left
4419 // -- eax : right 4066 // -- eax : right
4420 // -- esp[0] : return address 4067 // -- esp[0] : return address
4421 // ----------------------------------- 4068 // -----------------------------------
4422 Isolate* isolate = masm->isolate(); 4069 Isolate* isolate = masm->isolate();
4423 4070
4424 // Load ecx with the allocation site. We stick an undefined dummy value here 4071 // Load ecx with the allocation site. We stick an undefined dummy value here
4425 // and replace it with the real allocation site later when we instantiate this 4072 // and replace it with the real allocation site later when we instantiate this
(...skipping 998 matching lines...) Expand 10 before | Expand all | Expand 10 after
5424 // If we reached this point there is a problem. 5071 // If we reached this point there is a problem.
5425 __ Abort(kUnexpectedElementsKindInArrayConstructor); 5072 __ Abort(kUnexpectedElementsKindInArrayConstructor);
5426 } else { 5073 } else {
5427 UNREACHABLE(); 5074 UNREACHABLE();
5428 } 5075 }
5429 } 5076 }
5430 5077
5431 5078
5432 static void CreateArrayDispatchOneArgument(MacroAssembler* masm, 5079 static void CreateArrayDispatchOneArgument(MacroAssembler* masm,
5433 AllocationSiteOverrideMode mode) { 5080 AllocationSiteOverrideMode mode) {
5434 // ebx - type info cell (if mode != DISABLE_ALLOCATION_SITES) 5081 // ebx - allocation site (if mode != DISABLE_ALLOCATION_SITES)
5435 // edx - kind (if mode != DISABLE_ALLOCATION_SITES) 5082 // edx - kind (if mode != DISABLE_ALLOCATION_SITES)
5436 // eax - number of arguments 5083 // eax - number of arguments
5437 // edi - constructor? 5084 // edi - constructor?
5438 // esp[0] - return address 5085 // esp[0] - return address
5439 // esp[4] - last argument 5086 // esp[4] - last argument
5440 Label normal_sequence; 5087 Label normal_sequence;
5441 if (mode == DONT_OVERRIDE) { 5088 if (mode == DONT_OVERRIDE) {
5442 ASSERT(FAST_SMI_ELEMENTS == 0); 5089 ASSERT(FAST_SMI_ELEMENTS == 0);
5443 ASSERT(FAST_HOLEY_SMI_ELEMENTS == 1); 5090 ASSERT(FAST_HOLEY_SMI_ELEMENTS == 1);
5444 ASSERT(FAST_ELEMENTS == 2); 5091 ASSERT(FAST_ELEMENTS == 2);
(...skipping 20 matching lines...) Expand all
5465 __ TailCallStub(&stub_holey); 5112 __ TailCallStub(&stub_holey);
5466 5113
5467 __ bind(&normal_sequence); 5114 __ bind(&normal_sequence);
5468 ArraySingleArgumentConstructorStub stub(initial, 5115 ArraySingleArgumentConstructorStub stub(initial,
5469 DISABLE_ALLOCATION_SITES); 5116 DISABLE_ALLOCATION_SITES);
5470 __ TailCallStub(&stub); 5117 __ TailCallStub(&stub);
5471 } else if (mode == DONT_OVERRIDE) { 5118 } else if (mode == DONT_OVERRIDE) {
5472 // We are going to create a holey array, but our kind is non-holey. 5119 // We are going to create a holey array, but our kind is non-holey.
5473 // Fix kind and retry. 5120 // Fix kind and retry.
5474 __ inc(edx); 5121 __ inc(edx);
5475 __ mov(ecx, FieldOperand(ebx, Cell::kValueOffset)); 5122
5476 if (FLAG_debug_code) { 5123 if (FLAG_debug_code) {
5477 Handle<Map> allocation_site_map = 5124 Handle<Map> allocation_site_map =
5478 masm->isolate()->factory()->allocation_site_map(); 5125 masm->isolate()->factory()->allocation_site_map();
5479 __ cmp(FieldOperand(ecx, 0), Immediate(allocation_site_map)); 5126 __ cmp(FieldOperand(ebx, 0), Immediate(allocation_site_map));
5480 __ Assert(equal, kExpectedAllocationSiteInCell); 5127 __ Assert(equal, kExpectedAllocationSite);
5481 } 5128 }
5482 5129
5483 // Save the resulting elements kind in type info. We can't just store r3 5130 // Save the resulting elements kind in type info. We can't just store r3
5484 // in the AllocationSite::transition_info field because elements kind is 5131 // in the AllocationSite::transition_info field because elements kind is
5485 // restricted to a portion of the field...upper bits need to be left alone. 5132 // restricted to a portion of the field...upper bits need to be left alone.
5486 STATIC_ASSERT(AllocationSite::ElementsKindBits::kShift == 0); 5133 STATIC_ASSERT(AllocationSite::ElementsKindBits::kShift == 0);
5487 __ add(FieldOperand(ecx, AllocationSite::kTransitionInfoOffset), 5134 __ add(FieldOperand(ebx, AllocationSite::kTransitionInfoOffset),
5488 Immediate(Smi::FromInt(kFastElementsKindPackedToHoley))); 5135 Immediate(Smi::FromInt(kFastElementsKindPackedToHoley)));
5489 5136
5490 __ bind(&normal_sequence); 5137 __ bind(&normal_sequence);
5491 int last_index = GetSequenceIndexFromFastElementsKind( 5138 int last_index = GetSequenceIndexFromFastElementsKind(
5492 TERMINAL_FAST_ELEMENTS_KIND); 5139 TERMINAL_FAST_ELEMENTS_KIND);
5493 for (int i = 0; i <= last_index; ++i) { 5140 for (int i = 0; i <= last_index; ++i) {
5494 Label next; 5141 Label next;
5495 ElementsKind kind = GetFastElementsKindFromSequenceIndex(i); 5142 ElementsKind kind = GetFastElementsKindFromSequenceIndex(i);
5496 __ cmp(edx, kind); 5143 __ cmp(edx, kind);
5497 __ j(not_equal, &next); 5144 __ j(not_equal, &next);
(...skipping 111 matching lines...) Expand 10 before | Expand all | Expand 10 after
5609 __ cmp(FieldOperand(ebx, 0), Immediate(cell_map)); 5256 __ cmp(FieldOperand(ebx, 0), Immediate(cell_map));
5610 __ Assert(equal, kExpectedPropertyCellInRegisterEbx); 5257 __ Assert(equal, kExpectedPropertyCellInRegisterEbx);
5611 __ bind(&okay_here); 5258 __ bind(&okay_here);
5612 } 5259 }
5613 5260
5614 Label no_info; 5261 Label no_info;
5615 // If the type cell is undefined, or contains anything other than an 5262 // If the type cell is undefined, or contains anything other than an
5616 // AllocationSite, call an array constructor that doesn't use AllocationSites. 5263 // AllocationSite, call an array constructor that doesn't use AllocationSites.
5617 __ cmp(ebx, Immediate(undefined_sentinel)); 5264 __ cmp(ebx, Immediate(undefined_sentinel));
5618 __ j(equal, &no_info); 5265 __ j(equal, &no_info);
5619 __ mov(edx, FieldOperand(ebx, Cell::kValueOffset)); 5266 __ mov(ebx, FieldOperand(ebx, Cell::kValueOffset));
5620 __ cmp(FieldOperand(edx, 0), Immediate( 5267 __ cmp(FieldOperand(ebx, 0), Immediate(
5621 masm->isolate()->factory()->allocation_site_map())); 5268 masm->isolate()->factory()->allocation_site_map()));
5622 __ j(not_equal, &no_info); 5269 __ j(not_equal, &no_info);
5623 5270
5624 // Only look at the lower 16 bits of the transition info. 5271 // Only look at the lower 16 bits of the transition info.
5625 __ mov(edx, FieldOperand(edx, AllocationSite::kTransitionInfoOffset)); 5272 __ mov(edx, FieldOperand(ebx, AllocationSite::kTransitionInfoOffset));
5626 __ SmiUntag(edx); 5273 __ SmiUntag(edx);
5627 STATIC_ASSERT(AllocationSite::ElementsKindBits::kShift == 0); 5274 STATIC_ASSERT(AllocationSite::ElementsKindBits::kShift == 0);
5628 __ and_(edx, Immediate(AllocationSite::ElementsKindBits::kMask)); 5275 __ and_(edx, Immediate(AllocationSite::ElementsKindBits::kMask));
5629 GenerateDispatchToArrayStub(masm, DONT_OVERRIDE); 5276 GenerateDispatchToArrayStub(masm, DONT_OVERRIDE);
5630 5277
5631 __ bind(&no_info); 5278 __ bind(&no_info);
5632 GenerateDispatchToArrayStub(masm, DISABLE_ALLOCATION_SITES); 5279 GenerateDispatchToArrayStub(masm, DISABLE_ALLOCATION_SITES);
5633 } 5280 }
5634 5281
5635 5282
(...skipping 83 matching lines...) Expand 10 before | Expand all | Expand 10 after
5719 __ bind(&fast_elements_case); 5366 __ bind(&fast_elements_case);
5720 GenerateCase(masm, FAST_ELEMENTS); 5367 GenerateCase(masm, FAST_ELEMENTS);
5721 } 5368 }
5722 5369
5723 5370
5724 #undef __ 5371 #undef __
5725 5372
5726 } } // namespace v8::internal 5373 } } // namespace v8::internal
5727 5374
5728 #endif // V8_TARGET_ARCH_IA32 5375 #endif // V8_TARGET_ARCH_IA32
OLDNEW
« no previous file with comments | « src/ia32/code-stubs-ia32.h ('k') | src/ia32/full-codegen-ia32.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698