OLD | NEW |
---|---|
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 1335 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
1346 // Test if left operand is a string. | 1346 // Test if left operand is a string. |
1347 __ JumpIfSmi(left, &call_runtime, Label::kNear); | 1347 __ JumpIfSmi(left, &call_runtime, Label::kNear); |
1348 __ CmpObjectType(left, FIRST_NONSTRING_TYPE, ecx); | 1348 __ CmpObjectType(left, FIRST_NONSTRING_TYPE, ecx); |
1349 __ j(above_equal, &call_runtime, Label::kNear); | 1349 __ j(above_equal, &call_runtime, Label::kNear); |
1350 | 1350 |
1351 // Test if right operand is a string. | 1351 // Test if right operand is a string. |
1352 __ JumpIfSmi(right, &call_runtime, Label::kNear); | 1352 __ JumpIfSmi(right, &call_runtime, Label::kNear); |
1353 __ CmpObjectType(right, FIRST_NONSTRING_TYPE, ecx); | 1353 __ CmpObjectType(right, FIRST_NONSTRING_TYPE, ecx); |
1354 __ j(above_equal, &call_runtime, Label::kNear); | 1354 __ j(above_equal, &call_runtime, Label::kNear); |
1355 | 1355 |
1356 StringAddStub string_add_stub((StringAddFlags) | 1356 StringAddStub string_add_stub( |
1357 (ERECT_FRAME | NO_STRING_CHECK_IN_STUB)); | 1357 (StringAddFlags)(STRING_ADD_CHECK_NONE | STRING_ADD_ERECT_FRAME)); |
1358 GenerateRegisterArgsPush(masm); | 1358 GenerateRegisterArgsPush(masm); |
1359 __ TailCallStub(&string_add_stub); | 1359 __ TailCallStub(&string_add_stub); |
1360 | 1360 |
1361 __ bind(&call_runtime); | 1361 __ bind(&call_runtime); |
1362 GenerateTypeTransition(masm); | 1362 GenerateTypeTransition(masm); |
1363 } | 1363 } |
1364 | 1364 |
1365 | 1365 |
1366 static void BinaryOpStub_GenerateHeapResultAllocation(MacroAssembler* masm, | 1366 static void BinaryOpStub_GenerateHeapResultAllocation(MacroAssembler* masm, |
1367 Label* alloc_failure, | 1367 Label* alloc_failure, |
(...skipping 624 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
1992 | 1992 |
1993 // Registers containing left and right operands respectively. | 1993 // Registers containing left and right operands respectively. |
1994 Register left = edx; | 1994 Register left = edx; |
1995 Register right = eax; | 1995 Register right = eax; |
1996 | 1996 |
1997 // Test if left operand is a string. | 1997 // Test if left operand is a string. |
1998 __ JumpIfSmi(left, &left_not_string, Label::kNear); | 1998 __ JumpIfSmi(left, &left_not_string, Label::kNear); |
1999 __ CmpObjectType(left, FIRST_NONSTRING_TYPE, ecx); | 1999 __ CmpObjectType(left, FIRST_NONSTRING_TYPE, ecx); |
2000 __ j(above_equal, &left_not_string, Label::kNear); | 2000 __ j(above_equal, &left_not_string, Label::kNear); |
2001 | 2001 |
2002 StringAddStub string_add_left_stub((StringAddFlags) | 2002 StringAddStub string_add_left_stub( |
2003 (ERECT_FRAME | NO_STRING_CHECK_LEFT_IN_STUB)); | 2003 (StringAddFlags)(STRING_ADD_CHECK_RIGHT | STRING_ADD_ERECT_FRAME)); |
2004 GenerateRegisterArgsPush(masm); | 2004 GenerateRegisterArgsPush(masm); |
2005 __ TailCallStub(&string_add_left_stub); | 2005 __ TailCallStub(&string_add_left_stub); |
2006 | 2006 |
2007 // Left operand is not a string, test right. | 2007 // Left operand is not a string, test right. |
2008 __ bind(&left_not_string); | 2008 __ bind(&left_not_string); |
2009 __ JumpIfSmi(right, &call_runtime, Label::kNear); | 2009 __ JumpIfSmi(right, &call_runtime, Label::kNear); |
2010 __ CmpObjectType(right, FIRST_NONSTRING_TYPE, ecx); | 2010 __ CmpObjectType(right, FIRST_NONSTRING_TYPE, ecx); |
2011 __ j(above_equal, &call_runtime, Label::kNear); | 2011 __ j(above_equal, &call_runtime, Label::kNear); |
2012 | 2012 |
2013 StringAddStub string_add_right_stub((StringAddFlags) | 2013 StringAddStub string_add_right_stub( |
2014 (ERECT_FRAME | NO_STRING_CHECK_RIGHT_IN_STUB)); | 2014 (StringAddFlags)(STRING_ADD_CHECK_LEFT | STRING_ADD_ERECT_FRAME)); |
2015 GenerateRegisterArgsPush(masm); | 2015 GenerateRegisterArgsPush(masm); |
2016 __ TailCallStub(&string_add_right_stub); | 2016 __ TailCallStub(&string_add_right_stub); |
2017 | 2017 |
2018 // Neither argument is a string. | 2018 // Neither argument is a string. |
2019 __ bind(&call_runtime); | 2019 __ bind(&call_runtime); |
2020 } | 2020 } |
2021 | 2021 |
2022 | 2022 |
2023 static void BinaryOpStub_GenerateHeapResultAllocation(MacroAssembler* masm, | 2023 static void BinaryOpStub_GenerateHeapResultAllocation(MacroAssembler* masm, |
2024 Label* alloc_failure, | 2024 Label* alloc_failure, |
(...skipping 3351 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
5376 | 5376 |
5377 void StringAddStub::Generate(MacroAssembler* masm) { | 5377 void StringAddStub::Generate(MacroAssembler* masm) { |
5378 Label call_runtime, call_builtin; | 5378 Label call_runtime, call_builtin; |
5379 Builtins::JavaScript builtin_id = Builtins::ADD; | 5379 Builtins::JavaScript builtin_id = Builtins::ADD; |
5380 | 5380 |
5381 // Load the two arguments. | 5381 // Load the two arguments. |
5382 __ mov(eax, Operand(esp, 2 * kPointerSize)); // First argument. | 5382 __ mov(eax, Operand(esp, 2 * kPointerSize)); // First argument. |
5383 __ mov(edx, Operand(esp, 1 * kPointerSize)); // Second argument. | 5383 __ mov(edx, Operand(esp, 1 * kPointerSize)); // Second argument. |
5384 | 5384 |
5385 // Make sure that both arguments are strings if not known in advance. | 5385 // Make sure that both arguments are strings if not known in advance. |
5386 if ((flags_ & NO_STRING_ADD_FLAGS) != 0) { | 5386 // Otherwise, at least one of the arguments is definitely a string, |
5387 // and we convert the one that is not known to be a string. | |
5388 if ((flags_ & STRING_ADD_CHECK_BOTH) == STRING_ADD_CHECK_BOTH) { | |
mvstanton
2013/07/19 11:44:53
What about an assert in this case that STRING_ADD_
Benedikt Meurer
2013/07/19 11:46:51
You mean both are on?
Benedikt Meurer
2013/07/19 11:52:30
Done.
| |
5387 __ JumpIfSmi(eax, &call_runtime); | 5389 __ JumpIfSmi(eax, &call_runtime); |
5388 __ CmpObjectType(eax, FIRST_NONSTRING_TYPE, ebx); | 5390 __ CmpObjectType(eax, FIRST_NONSTRING_TYPE, ebx); |
5389 __ j(above_equal, &call_runtime); | 5391 __ j(above_equal, &call_runtime); |
5390 | 5392 |
5391 // First argument is a a string, test second. | 5393 // First argument is a a string, test second. |
5392 __ JumpIfSmi(edx, &call_runtime); | 5394 __ JumpIfSmi(edx, &call_runtime); |
5393 __ CmpObjectType(edx, FIRST_NONSTRING_TYPE, ebx); | 5395 __ CmpObjectType(edx, FIRST_NONSTRING_TYPE, ebx); |
5394 __ j(above_equal, &call_runtime); | 5396 __ j(above_equal, &call_runtime); |
5395 } else { | 5397 } else if ((flags_ & STRING_ADD_CHECK_LEFT) == STRING_ADD_CHECK_LEFT) { |
5396 // Here at least one of the arguments is definitely a string. | 5398 ASSERT((flags_ & STRING_ADD_CHECK_RIGHT) == 0); |
5397 // We convert the one that is not known to be a string. | 5399 GenerateConvertArgument(masm, 2 * kPointerSize, eax, ebx, ecx, edi, |
5398 if ((flags_ & NO_STRING_CHECK_LEFT_IN_STUB) == 0) { | 5400 &call_builtin); |
5399 ASSERT((flags_ & NO_STRING_CHECK_RIGHT_IN_STUB) != 0); | 5401 builtin_id = Builtins::STRING_ADD_RIGHT; |
5400 GenerateConvertArgument(masm, 2 * kPointerSize, eax, ebx, ecx, edi, | 5402 } else if ((flags_ & STRING_ADD_CHECK_RIGHT) == STRING_ADD_CHECK_RIGHT) { |
5401 &call_builtin); | 5403 ASSERT((flags_ & STRING_ADD_CHECK_LEFT) == 0); |
5402 builtin_id = Builtins::STRING_ADD_RIGHT; | 5404 GenerateConvertArgument(masm, 1 * kPointerSize, edx, ebx, ecx, edi, |
5403 } else if ((flags_ & NO_STRING_CHECK_RIGHT_IN_STUB) == 0) { | 5405 &call_builtin); |
5404 ASSERT((flags_ & NO_STRING_CHECK_LEFT_IN_STUB) != 0); | 5406 builtin_id = Builtins::STRING_ADD_LEFT; |
5405 GenerateConvertArgument(masm, 1 * kPointerSize, edx, ebx, ecx, edi, | |
5406 &call_builtin); | |
5407 builtin_id = Builtins::STRING_ADD_LEFT; | |
5408 } | |
5409 } | 5407 } |
5410 | 5408 |
5411 // Both arguments are strings. | 5409 // Both arguments are strings. |
5412 // eax: first string | 5410 // eax: first string |
5413 // edx: second string | 5411 // edx: second string |
5414 // Check if either of the strings are empty. In that case return the other. | 5412 // Check if either of the strings are empty. In that case return the other. |
5415 Label second_not_zero_length, both_not_zero_length; | 5413 Label second_not_zero_length, both_not_zero_length; |
5416 __ mov(ecx, FieldOperand(edx, String::kLengthOffset)); | 5414 __ mov(ecx, FieldOperand(edx, String::kLengthOffset)); |
5417 STATIC_ASSERT(kSmiTag == 0); | 5415 STATIC_ASSERT(kSmiTag == 0); |
5418 __ test(ecx, ecx); | 5416 __ test(ecx, ecx); |
(...skipping 265 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
5684 // edi: length of second argument | 5682 // edi: length of second argument |
5685 StringHelper::GenerateCopyCharacters(masm, ecx, edx, edi, ebx, false); | 5683 StringHelper::GenerateCopyCharacters(masm, ecx, edx, edi, ebx, false); |
5686 __ IncrementCounter(counters->string_add_native(), 1); | 5684 __ IncrementCounter(counters->string_add_native(), 1); |
5687 __ ret(2 * kPointerSize); | 5685 __ ret(2 * kPointerSize); |
5688 | 5686 |
5689 // Recover stack pointer before jumping to runtime. | 5687 // Recover stack pointer before jumping to runtime. |
5690 __ bind(&call_runtime_drop_two); | 5688 __ bind(&call_runtime_drop_two); |
5691 __ Drop(2); | 5689 __ Drop(2); |
5692 // Just jump to runtime to add the two strings. | 5690 // Just jump to runtime to add the two strings. |
5693 __ bind(&call_runtime); | 5691 __ bind(&call_runtime); |
5694 if ((flags_ & ERECT_FRAME) != 0) { | 5692 if ((flags_ & STRING_ADD_ERECT_FRAME) != 0) { |
5695 GenerateRegisterArgsPop(masm, ecx); | 5693 GenerateRegisterArgsPop(masm, ecx); |
5696 // Build a frame | 5694 // Build a frame |
5697 { | 5695 { |
5698 FrameScope scope(masm, StackFrame::INTERNAL); | 5696 FrameScope scope(masm, StackFrame::INTERNAL); |
5699 GenerateRegisterArgsPush(masm); | 5697 GenerateRegisterArgsPush(masm); |
5700 __ CallRuntime(Runtime::kStringAdd, 2); | 5698 __ CallRuntime(Runtime::kStringAdd, 2); |
5701 } | 5699 } |
5702 __ ret(0); | 5700 __ ret(0); |
5703 } else { | 5701 } else { |
5704 __ TailCallRuntime(Runtime::kStringAdd, 2, 1); | 5702 __ TailCallRuntime(Runtime::kStringAdd, 2, 1); |
5705 } | 5703 } |
5706 | 5704 |
5707 if (call_builtin.is_linked()) { | 5705 if (call_builtin.is_linked()) { |
5708 __ bind(&call_builtin); | 5706 __ bind(&call_builtin); |
5709 if ((flags_ & ERECT_FRAME) != 0) { | 5707 if ((flags_ & STRING_ADD_ERECT_FRAME) != 0) { |
5710 GenerateRegisterArgsPop(masm, ecx); | 5708 GenerateRegisterArgsPop(masm, ecx); |
5711 // Build a frame | 5709 // Build a frame |
5712 { | 5710 { |
5713 FrameScope scope(masm, StackFrame::INTERNAL); | 5711 FrameScope scope(masm, StackFrame::INTERNAL); |
5714 GenerateRegisterArgsPush(masm); | 5712 GenerateRegisterArgsPush(masm); |
5715 __ InvokeBuiltin(builtin_id, CALL_FUNCTION); | 5713 __ InvokeBuiltin(builtin_id, CALL_FUNCTION); |
5716 } | 5714 } |
5717 __ ret(0); | 5715 __ ret(0); |
5718 } else { | 5716 } else { |
5719 __ InvokeBuiltin(builtin_id, JUMP_FUNCTION); | 5717 __ InvokeBuiltin(builtin_id, JUMP_FUNCTION); |
(...skipping 2061 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
7781 __ bind(&fast_elements_case); | 7779 __ bind(&fast_elements_case); |
7782 GenerateCase(masm, FAST_ELEMENTS); | 7780 GenerateCase(masm, FAST_ELEMENTS); |
7783 } | 7781 } |
7784 | 7782 |
7785 | 7783 |
7786 #undef __ | 7784 #undef __ |
7787 | 7785 |
7788 } } // namespace v8::internal | 7786 } } // namespace v8::internal |
7789 | 7787 |
7790 #endif // V8_TARGET_ARCH_IA32 | 7788 #endif // V8_TARGET_ARCH_IA32 |
OLD | NEW |