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 493 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
504 __ mov(FieldOperand(eax, Context::kLengthOffset), | 504 __ mov(FieldOperand(eax, Context::kLengthOffset), |
505 Immediate(Smi::FromInt(length))); | 505 Immediate(Smi::FromInt(length))); |
506 | 506 |
507 // If this block context is nested in the native context we get a smi | 507 // If this block context is nested in the native context we get a smi |
508 // sentinel instead of a function. The block context should get the | 508 // sentinel instead of a function. The block context should get the |
509 // canonical empty function of the native context as its closure which | 509 // canonical empty function of the native context as its closure which |
510 // we still have to look up. | 510 // we still have to look up. |
511 Label after_sentinel; | 511 Label after_sentinel; |
512 __ JumpIfNotSmi(ecx, &after_sentinel, Label::kNear); | 512 __ JumpIfNotSmi(ecx, &after_sentinel, Label::kNear); |
513 if (FLAG_debug_code) { | 513 if (FLAG_debug_code) { |
514 const char* message = "Expected 0 as a Smi sentinel"; | |
515 __ cmp(ecx, 0); | 514 __ cmp(ecx, 0); |
516 __ Assert(equal, message); | 515 __ Assert(equal, kExpected0AsASmiSentinel); |
517 } | 516 } |
518 __ mov(ecx, GlobalObjectOperand()); | 517 __ mov(ecx, GlobalObjectOperand()); |
519 __ mov(ecx, FieldOperand(ecx, GlobalObject::kNativeContextOffset)); | 518 __ mov(ecx, FieldOperand(ecx, GlobalObject::kNativeContextOffset)); |
520 __ mov(ecx, ContextOperand(ecx, Context::CLOSURE_INDEX)); | 519 __ mov(ecx, ContextOperand(ecx, Context::CLOSURE_INDEX)); |
521 __ bind(&after_sentinel); | 520 __ bind(&after_sentinel); |
522 | 521 |
523 // Set up the fixed slots. | 522 // Set up the fixed slots. |
524 __ mov(ContextOperand(eax, Context::CLOSURE_INDEX), ecx); | 523 __ mov(ContextOperand(eax, Context::CLOSURE_INDEX), ecx); |
525 __ mov(ContextOperand(eax, Context::PREVIOUS_INDEX), esi); | 524 __ mov(ContextOperand(eax, Context::PREVIOUS_INDEX), esi); |
526 __ mov(ContextOperand(eax, Context::EXTENSION_INDEX), ebx); | 525 __ mov(ContextOperand(eax, Context::EXTENSION_INDEX), ebx); |
(...skipping 2935 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
3462 __ mov(eax, Operand(esp, kJSRegExpOffset)); | 3461 __ mov(eax, Operand(esp, kJSRegExpOffset)); |
3463 STATIC_ASSERT(kSmiTag == 0); | 3462 STATIC_ASSERT(kSmiTag == 0); |
3464 __ JumpIfSmi(eax, &runtime); | 3463 __ JumpIfSmi(eax, &runtime); |
3465 __ CmpObjectType(eax, JS_REGEXP_TYPE, ecx); | 3464 __ CmpObjectType(eax, JS_REGEXP_TYPE, ecx); |
3466 __ j(not_equal, &runtime); | 3465 __ j(not_equal, &runtime); |
3467 | 3466 |
3468 // Check that the RegExp has been compiled (data contains a fixed array). | 3467 // Check that the RegExp has been compiled (data contains a fixed array). |
3469 __ mov(ecx, FieldOperand(eax, JSRegExp::kDataOffset)); | 3468 __ mov(ecx, FieldOperand(eax, JSRegExp::kDataOffset)); |
3470 if (FLAG_debug_code) { | 3469 if (FLAG_debug_code) { |
3471 __ test(ecx, Immediate(kSmiTagMask)); | 3470 __ test(ecx, Immediate(kSmiTagMask)); |
3472 __ Check(not_zero, "Unexpected type for RegExp data, FixedArray expected"); | 3471 __ Check(not_zero, kUnexpectedTypeForRegExpDataFixedArrayExpected); |
3473 __ CmpObjectType(ecx, FIXED_ARRAY_TYPE, ebx); | 3472 __ CmpObjectType(ecx, FIXED_ARRAY_TYPE, ebx); |
3474 __ Check(equal, "Unexpected type for RegExp data, FixedArray expected"); | 3473 __ Check(equal, kUnexpectedTypeForRegExpDataFixedArrayExpected); |
3475 } | 3474 } |
3476 | 3475 |
3477 // ecx: RegExp data (FixedArray) | 3476 // ecx: RegExp data (FixedArray) |
3478 // Check the type of the RegExp. Only continue if type is JSRegExp::IRREGEXP. | 3477 // Check the type of the RegExp. Only continue if type is JSRegExp::IRREGEXP. |
3479 __ mov(ebx, FieldOperand(ecx, JSRegExp::kDataTagOffset)); | 3478 __ mov(ebx, FieldOperand(ecx, JSRegExp::kDataTagOffset)); |
3480 __ cmp(ebx, Immediate(Smi::FromInt(JSRegExp::IRREGEXP))); | 3479 __ cmp(ebx, Immediate(Smi::FromInt(JSRegExp::IRREGEXP))); |
3481 __ j(not_equal, &runtime); | 3480 __ j(not_equal, &runtime); |
3482 | 3481 |
3483 // ecx: RegExp data (FixedArray) | 3482 // ecx: RegExp data (FixedArray) |
3484 // Check that the number of captures fit in the static offsets vector buffer. | 3483 // Check that the number of captures fit in the static offsets vector buffer. |
(...skipping 339 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
3824 | 3823 |
3825 // (8) External string. Short external strings have been ruled out. | 3824 // (8) External string. Short external strings have been ruled out. |
3826 __ bind(&external_string); | 3825 __ bind(&external_string); |
3827 // Reload instance type. | 3826 // Reload instance type. |
3828 __ mov(ebx, FieldOperand(eax, HeapObject::kMapOffset)); | 3827 __ mov(ebx, FieldOperand(eax, HeapObject::kMapOffset)); |
3829 __ movzx_b(ebx, FieldOperand(ebx, Map::kInstanceTypeOffset)); | 3828 __ movzx_b(ebx, FieldOperand(ebx, Map::kInstanceTypeOffset)); |
3830 if (FLAG_debug_code) { | 3829 if (FLAG_debug_code) { |
3831 // Assert that we do not have a cons or slice (indirect strings) here. | 3830 // Assert that we do not have a cons or slice (indirect strings) here. |
3832 // Sequential strings have already been ruled out. | 3831 // Sequential strings have already been ruled out. |
3833 __ test_b(ebx, kIsIndirectStringMask); | 3832 __ test_b(ebx, kIsIndirectStringMask); |
3834 __ Assert(zero, "external string expected, but not found"); | 3833 __ Assert(zero, kExternalStringExpectedButNotFound); |
3835 } | 3834 } |
3836 __ mov(eax, FieldOperand(eax, ExternalString::kResourceDataOffset)); | 3835 __ mov(eax, FieldOperand(eax, ExternalString::kResourceDataOffset)); |
3837 // Move the pointer so that offset-wise, it looks like a sequential string. | 3836 // Move the pointer so that offset-wise, it looks like a sequential string. |
3838 STATIC_ASSERT(SeqTwoByteString::kHeaderSize == SeqOneByteString::kHeaderSize); | 3837 STATIC_ASSERT(SeqTwoByteString::kHeaderSize == SeqOneByteString::kHeaderSize); |
3839 __ sub(eax, Immediate(SeqTwoByteString::kHeaderSize - kHeapObjectTag)); | 3838 __ sub(eax, Immediate(SeqTwoByteString::kHeaderSize - kHeapObjectTag)); |
3840 STATIC_ASSERT(kTwoByteStringTag == 0); | 3839 STATIC_ASSERT(kTwoByteStringTag == 0); |
3841 // (8a) Is the external string one byte? If yes, go to (6). | 3840 // (8a) Is the external string one byte? If yes, go to (6). |
3842 __ test_b(ebx, kStringEncodingMask); | 3841 __ test_b(ebx, kStringEncodingMask); |
3843 __ j(not_zero, &seq_one_byte_string); // Goto (6). | 3842 __ j(not_zero, &seq_one_byte_string); // Goto (6). |
3844 | 3843 |
(...skipping 474 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
4319 ebx); | 4318 ebx); |
4320 } else { | 4319 } else { |
4321 StringCompareStub::GenerateCompareFlatAsciiStrings(masm, | 4320 StringCompareStub::GenerateCompareFlatAsciiStrings(masm, |
4322 edx, | 4321 edx, |
4323 eax, | 4322 eax, |
4324 ecx, | 4323 ecx, |
4325 ebx, | 4324 ebx, |
4326 edi); | 4325 edi); |
4327 } | 4326 } |
4328 #ifdef DEBUG | 4327 #ifdef DEBUG |
4329 __ Abort("Unexpected fall-through from string comparison"); | 4328 __ Abort(kUnexpectedFallThroughFromStringComparison); |
4330 #endif | 4329 #endif |
4331 | 4330 |
4332 __ bind(&check_unequal_objects); | 4331 __ bind(&check_unequal_objects); |
4333 if (cc == equal && !strict()) { | 4332 if (cc == equal && !strict()) { |
4334 // Non-strict equality. Objects are unequal if | 4333 // Non-strict equality. Objects are unequal if |
4335 // they are both JSObjects and not undetectable, | 4334 // they are both JSObjects and not undetectable, |
4336 // and their pointers are different. | 4335 // and their pointers are different. |
4337 Label not_both_objects; | 4336 Label not_both_objects; |
4338 Label return_unequal; | 4337 Label return_unequal; |
4339 // At most one is a smi, so we can test for smi by adding the two. | 4338 // At most one is a smi, so we can test for smi by adding the two. |
(...skipping 738 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
5078 function); | 5077 function); |
5079 } else { | 5078 } else { |
5080 // The constants for the code patching are based on no push instructions | 5079 // The constants for the code patching are based on no push instructions |
5081 // at the call site. | 5080 // at the call site. |
5082 ASSERT(HasArgsInRegisters()); | 5081 ASSERT(HasArgsInRegisters()); |
5083 // Get return address and delta to inlined map check. | 5082 // Get return address and delta to inlined map check. |
5084 __ mov(scratch, Operand(esp, 0 * kPointerSize)); | 5083 __ mov(scratch, Operand(esp, 0 * kPointerSize)); |
5085 __ sub(scratch, Operand(esp, 1 * kPointerSize)); | 5084 __ sub(scratch, Operand(esp, 1 * kPointerSize)); |
5086 if (FLAG_debug_code) { | 5085 if (FLAG_debug_code) { |
5087 __ cmpb(Operand(scratch, 0), kCmpEdiOperandByte1); | 5086 __ cmpb(Operand(scratch, 0), kCmpEdiOperandByte1); |
5088 __ Assert(equal, "InstanceofStub unexpected call site cache (cmp 1)"); | 5087 __ Assert(equal, kInstanceofStubUnexpectedCallSiteCacheCmp1); |
5089 __ cmpb(Operand(scratch, 1), kCmpEdiOperandByte2); | 5088 __ cmpb(Operand(scratch, 1), kCmpEdiOperandByte2); |
5090 __ Assert(equal, "InstanceofStub unexpected call site cache (cmp 2)"); | 5089 __ Assert(equal, kInstanceofStubUnexpectedCallSiteCacheCmp2); |
5091 } | 5090 } |
5092 __ mov(scratch, Operand(scratch, kDeltaToCmpImmediate)); | 5091 __ mov(scratch, Operand(scratch, kDeltaToCmpImmediate)); |
5093 __ mov(Operand(scratch, 0), map); | 5092 __ mov(Operand(scratch, 0), map); |
5094 } | 5093 } |
5095 | 5094 |
5096 // Loop through the prototype chain of the object looking for the function | 5095 // Loop through the prototype chain of the object looking for the function |
5097 // prototype. | 5096 // prototype. |
5098 __ mov(scratch, FieldOperand(map, Map::kPrototypeOffset)); | 5097 __ mov(scratch, FieldOperand(map, Map::kPrototypeOffset)); |
5099 Label loop, is_instance, is_not_instance; | 5098 Label loop, is_instance, is_not_instance; |
5100 __ bind(&loop); | 5099 __ bind(&loop); |
(...skipping 12 matching lines...) Expand all Loading... |
5113 __ mov(scratch, Immediate(Heap::kInstanceofCacheAnswerRootIndex)); | 5112 __ mov(scratch, Immediate(Heap::kInstanceofCacheAnswerRootIndex)); |
5114 __ mov(Operand::StaticArray(scratch, | 5113 __ mov(Operand::StaticArray(scratch, |
5115 times_pointer_size, roots_array_start), eax); | 5114 times_pointer_size, roots_array_start), eax); |
5116 } else { | 5115 } else { |
5117 // Get return address and delta to inlined map check. | 5116 // Get return address and delta to inlined map check. |
5118 __ mov(eax, factory->true_value()); | 5117 __ mov(eax, factory->true_value()); |
5119 __ mov(scratch, Operand(esp, 0 * kPointerSize)); | 5118 __ mov(scratch, Operand(esp, 0 * kPointerSize)); |
5120 __ sub(scratch, Operand(esp, 1 * kPointerSize)); | 5119 __ sub(scratch, Operand(esp, 1 * kPointerSize)); |
5121 if (FLAG_debug_code) { | 5120 if (FLAG_debug_code) { |
5122 __ cmpb(Operand(scratch, kDeltaToMov), kMovEaxImmediateByte); | 5121 __ cmpb(Operand(scratch, kDeltaToMov), kMovEaxImmediateByte); |
5123 __ Assert(equal, "InstanceofStub unexpected call site cache (mov)"); | 5122 __ Assert(equal, kInstanceofStubUnexpectedCallSiteCacheMov); |
5124 } | 5123 } |
5125 __ mov(Operand(scratch, kDeltaToMovImmediate), eax); | 5124 __ mov(Operand(scratch, kDeltaToMovImmediate), eax); |
5126 if (!ReturnTrueFalseObject()) { | 5125 if (!ReturnTrueFalseObject()) { |
5127 __ Set(eax, Immediate(0)); | 5126 __ Set(eax, Immediate(0)); |
5128 } | 5127 } |
5129 } | 5128 } |
5130 __ ret((HasArgsInRegisters() ? 0 : 2) * kPointerSize); | 5129 __ ret((HasArgsInRegisters() ? 0 : 2) * kPointerSize); |
5131 | 5130 |
5132 __ bind(&is_not_instance); | 5131 __ bind(&is_not_instance); |
5133 if (!HasCallSiteInlineCheck()) { | 5132 if (!HasCallSiteInlineCheck()) { |
5134 __ Set(eax, Immediate(Smi::FromInt(1))); | 5133 __ Set(eax, Immediate(Smi::FromInt(1))); |
5135 __ mov(scratch, Immediate(Heap::kInstanceofCacheAnswerRootIndex)); | 5134 __ mov(scratch, Immediate(Heap::kInstanceofCacheAnswerRootIndex)); |
5136 __ mov(Operand::StaticArray( | 5135 __ mov(Operand::StaticArray( |
5137 scratch, times_pointer_size, roots_array_start), eax); | 5136 scratch, times_pointer_size, roots_array_start), eax); |
5138 } else { | 5137 } else { |
5139 // Get return address and delta to inlined map check. | 5138 // Get return address and delta to inlined map check. |
5140 __ mov(eax, factory->false_value()); | 5139 __ mov(eax, factory->false_value()); |
5141 __ mov(scratch, Operand(esp, 0 * kPointerSize)); | 5140 __ mov(scratch, Operand(esp, 0 * kPointerSize)); |
5142 __ sub(scratch, Operand(esp, 1 * kPointerSize)); | 5141 __ sub(scratch, Operand(esp, 1 * kPointerSize)); |
5143 if (FLAG_debug_code) { | 5142 if (FLAG_debug_code) { |
5144 __ cmpb(Operand(scratch, kDeltaToMov), kMovEaxImmediateByte); | 5143 __ cmpb(Operand(scratch, kDeltaToMov), kMovEaxImmediateByte); |
5145 __ Assert(equal, "InstanceofStub unexpected call site cache (mov)"); | 5144 __ Assert(equal, kInstanceofStubUnexpectedCallSiteCacheMov); |
5146 } | 5145 } |
5147 __ mov(Operand(scratch, kDeltaToMovImmediate), eax); | 5146 __ mov(Operand(scratch, kDeltaToMovImmediate), eax); |
5148 if (!ReturnTrueFalseObject()) { | 5147 if (!ReturnTrueFalseObject()) { |
5149 __ Set(eax, Immediate(Smi::FromInt(1))); | 5148 __ Set(eax, Immediate(Smi::FromInt(1))); |
5150 } | 5149 } |
5151 } | 5150 } |
5152 __ ret((HasArgsInRegisters() ? 0 : 2) * kPointerSize); | 5151 __ ret((HasArgsInRegisters() ? 0 : 2) * kPointerSize); |
5153 | 5152 |
5154 Label object_not_null, object_not_null_or_smi; | 5153 Label object_not_null, object_not_null_or_smi; |
5155 __ bind(¬_js_object); | 5154 __ bind(¬_js_object); |
(...skipping 92 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
5248 masm, factory, object_, index_, result_, &call_runtime_); | 5247 masm, factory, object_, index_, result_, &call_runtime_); |
5249 | 5248 |
5250 __ SmiTag(result_); | 5249 __ SmiTag(result_); |
5251 __ bind(&exit_); | 5250 __ bind(&exit_); |
5252 } | 5251 } |
5253 | 5252 |
5254 | 5253 |
5255 void StringCharCodeAtGenerator::GenerateSlow( | 5254 void StringCharCodeAtGenerator::GenerateSlow( |
5256 MacroAssembler* masm, | 5255 MacroAssembler* masm, |
5257 const RuntimeCallHelper& call_helper) { | 5256 const RuntimeCallHelper& call_helper) { |
5258 __ Abort("Unexpected fallthrough to CharCodeAt slow case"); | 5257 __ Abort(kUnexpectedFallthroughToCharCodeAtSlowCase); |
5259 | 5258 |
5260 // Index is not a smi. | 5259 // Index is not a smi. |
5261 __ bind(&index_not_smi_); | 5260 __ bind(&index_not_smi_); |
5262 // If index is a heap number, try converting it to an integer. | 5261 // If index is a heap number, try converting it to an integer. |
5263 __ CheckMap(index_, | 5262 __ CheckMap(index_, |
5264 masm->isolate()->factory()->heap_number_map(), | 5263 masm->isolate()->factory()->heap_number_map(), |
5265 index_not_number_, | 5264 index_not_number_, |
5266 DONT_DO_SMI_CHECK); | 5265 DONT_DO_SMI_CHECK); |
5267 call_helper.BeforeCall(masm); | 5266 call_helper.BeforeCall(masm); |
5268 __ push(object_); | 5267 __ push(object_); |
(...skipping 29 matching lines...) Expand all Loading... |
5298 __ push(object_); | 5297 __ push(object_); |
5299 __ SmiTag(index_); | 5298 __ SmiTag(index_); |
5300 __ push(index_); | 5299 __ push(index_); |
5301 __ CallRuntime(Runtime::kStringCharCodeAt, 2); | 5300 __ CallRuntime(Runtime::kStringCharCodeAt, 2); |
5302 if (!result_.is(eax)) { | 5301 if (!result_.is(eax)) { |
5303 __ mov(result_, eax); | 5302 __ mov(result_, eax); |
5304 } | 5303 } |
5305 call_helper.AfterCall(masm); | 5304 call_helper.AfterCall(masm); |
5306 __ jmp(&exit_); | 5305 __ jmp(&exit_); |
5307 | 5306 |
5308 __ Abort("Unexpected fallthrough from CharCodeAt slow case"); | 5307 __ Abort(kUnexpectedFallthroughFromCharCodeAtSlowCase); |
5309 } | 5308 } |
5310 | 5309 |
5311 | 5310 |
5312 // ------------------------------------------------------------------------- | 5311 // ------------------------------------------------------------------------- |
5313 // StringCharFromCodeGenerator | 5312 // StringCharFromCodeGenerator |
5314 | 5313 |
5315 void StringCharFromCodeGenerator::GenerateFast(MacroAssembler* masm) { | 5314 void StringCharFromCodeGenerator::GenerateFast(MacroAssembler* masm) { |
5316 // Fast case of Heap::LookupSingleCharacterStringFromCode. | 5315 // Fast case of Heap::LookupSingleCharacterStringFromCode. |
5317 STATIC_ASSERT(kSmiTag == 0); | 5316 STATIC_ASSERT(kSmiTag == 0); |
5318 STATIC_ASSERT(kSmiShiftSize == 0); | 5317 STATIC_ASSERT(kSmiShiftSize == 0); |
(...skipping 14 matching lines...) Expand all Loading... |
5333 FixedArray::kHeaderSize)); | 5332 FixedArray::kHeaderSize)); |
5334 __ cmp(result_, factory->undefined_value()); | 5333 __ cmp(result_, factory->undefined_value()); |
5335 __ j(equal, &slow_case_); | 5334 __ j(equal, &slow_case_); |
5336 __ bind(&exit_); | 5335 __ bind(&exit_); |
5337 } | 5336 } |
5338 | 5337 |
5339 | 5338 |
5340 void StringCharFromCodeGenerator::GenerateSlow( | 5339 void StringCharFromCodeGenerator::GenerateSlow( |
5341 MacroAssembler* masm, | 5340 MacroAssembler* masm, |
5342 const RuntimeCallHelper& call_helper) { | 5341 const RuntimeCallHelper& call_helper) { |
5343 __ Abort("Unexpected fallthrough to CharFromCode slow case"); | 5342 __ Abort(kUnexpectedFallthroughToCharFromCodeSlowCase); |
5344 | 5343 |
5345 __ bind(&slow_case_); | 5344 __ bind(&slow_case_); |
5346 call_helper.BeforeCall(masm); | 5345 call_helper.BeforeCall(masm); |
5347 __ push(code_); | 5346 __ push(code_); |
5348 __ CallRuntime(Runtime::kCharFromCode, 1); | 5347 __ CallRuntime(Runtime::kCharFromCode, 1); |
5349 if (!result_.is(eax)) { | 5348 if (!result_.is(eax)) { |
5350 __ mov(result_, eax); | 5349 __ mov(result_, eax); |
5351 } | 5350 } |
5352 call_helper.AfterCall(masm); | 5351 call_helper.AfterCall(masm); |
5353 __ jmp(&exit_); | 5352 __ jmp(&exit_); |
5354 | 5353 |
5355 __ Abort("Unexpected fallthrough from CharFromCode slow case"); | 5354 __ Abort(kUnexpectedFallthroughFromCharFromCodeSlowCase); |
5356 } | 5355 } |
5357 | 5356 |
5358 | 5357 |
5359 void StringAddStub::Generate(MacroAssembler* masm) { | 5358 void StringAddStub::Generate(MacroAssembler* masm) { |
5360 Label call_runtime, call_builtin; | 5359 Label call_runtime, call_builtin; |
5361 Builtins::JavaScript builtin_id = Builtins::ADD; | 5360 Builtins::JavaScript builtin_id = Builtins::ADD; |
5362 | 5361 |
5363 // Load the two arguments. | 5362 // Load the two arguments. |
5364 __ mov(eax, Operand(esp, 2 * kPointerSize)); // First argument. | 5363 __ mov(eax, Operand(esp, 2 * kPointerSize)); // First argument. |
5365 __ mov(edx, Operand(esp, 1 * kPointerSize)); // Second argument. | 5364 __ mov(edx, Operand(esp, 1 * kPointerSize)); // Second argument. |
(...skipping 2109 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
7475 Label next; | 7474 Label next; |
7476 ElementsKind kind = GetFastElementsKindFromSequenceIndex(i); | 7475 ElementsKind kind = GetFastElementsKindFromSequenceIndex(i); |
7477 __ cmp(edx, kind); | 7476 __ cmp(edx, kind); |
7478 __ j(not_equal, &next); | 7477 __ j(not_equal, &next); |
7479 T stub(kind); | 7478 T stub(kind); |
7480 __ TailCallStub(&stub); | 7479 __ TailCallStub(&stub); |
7481 __ bind(&next); | 7480 __ bind(&next); |
7482 } | 7481 } |
7483 | 7482 |
7484 // If we reached this point there is a problem. | 7483 // If we reached this point there is a problem. |
7485 __ Abort("Unexpected ElementsKind in array constructor"); | 7484 __ Abort(kUnexpectedElementsKindInArrayConstructor); |
7486 } | 7485 } |
7487 | 7486 |
7488 | 7487 |
7489 static void CreateArrayDispatchOneArgument(MacroAssembler* masm) { | 7488 static void CreateArrayDispatchOneArgument(MacroAssembler* masm) { |
7490 // ebx - type info cell | 7489 // ebx - type info cell |
7491 // edx - kind | 7490 // edx - kind |
7492 // eax - number of arguments | 7491 // eax - number of arguments |
7493 // edi - constructor? | 7492 // edi - constructor? |
7494 // esp[0] - return address | 7493 // esp[0] - return address |
7495 // esp[4] - last argument | 7494 // esp[4] - last argument |
(...skipping 42 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
7538 Label next; | 7537 Label next; |
7539 ElementsKind kind = GetFastElementsKindFromSequenceIndex(i); | 7538 ElementsKind kind = GetFastElementsKindFromSequenceIndex(i); |
7540 __ cmp(edx, kind); | 7539 __ cmp(edx, kind); |
7541 __ j(not_equal, &next); | 7540 __ j(not_equal, &next); |
7542 ArraySingleArgumentConstructorStub stub(kind); | 7541 ArraySingleArgumentConstructorStub stub(kind); |
7543 __ TailCallStub(&stub); | 7542 __ TailCallStub(&stub); |
7544 __ bind(&next); | 7543 __ bind(&next); |
7545 } | 7544 } |
7546 | 7545 |
7547 // If we reached this point there is a problem. | 7546 // If we reached this point there is a problem. |
7548 __ Abort("Unexpected ElementsKind in array constructor"); | 7547 __ Abort(kUnexpectedElementsKindInArrayConstructor); |
7549 } | 7548 } |
7550 | 7549 |
7551 | 7550 |
7552 template<class T> | 7551 template<class T> |
7553 static void ArrayConstructorStubAheadOfTimeHelper(Isolate* isolate) { | 7552 static void ArrayConstructorStubAheadOfTimeHelper(Isolate* isolate) { |
7554 int to_index = GetSequenceIndexFromFastElementsKind( | 7553 int to_index = GetSequenceIndexFromFastElementsKind( |
7555 TERMINAL_FAST_ELEMENTS_KIND); | 7554 TERMINAL_FAST_ELEMENTS_KIND); |
7556 for (int i = 0; i <= to_index; ++i) { | 7555 for (int i = 0; i <= to_index; ++i) { |
7557 ElementsKind kind = GetFastElementsKindFromSequenceIndex(i); | 7556 ElementsKind kind = GetFastElementsKindFromSequenceIndex(i); |
7558 T stub(kind); | 7557 T stub(kind); |
(...skipping 44 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
7603 masm->isolate()); | 7602 masm->isolate()); |
7604 | 7603 |
7605 if (FLAG_debug_code) { | 7604 if (FLAG_debug_code) { |
7606 // The array construct code is only set for the global and natives | 7605 // The array construct code is only set for the global and natives |
7607 // builtin Array functions which always have maps. | 7606 // builtin Array functions which always have maps. |
7608 | 7607 |
7609 // Initial map for the builtin Array function should be a map. | 7608 // Initial map for the builtin Array function should be a map. |
7610 __ mov(ecx, FieldOperand(edi, JSFunction::kPrototypeOrInitialMapOffset)); | 7609 __ mov(ecx, FieldOperand(edi, JSFunction::kPrototypeOrInitialMapOffset)); |
7611 // Will both indicate a NULL and a Smi. | 7610 // Will both indicate a NULL and a Smi. |
7612 __ test(ecx, Immediate(kSmiTagMask)); | 7611 __ test(ecx, Immediate(kSmiTagMask)); |
7613 __ Assert(not_zero, "Unexpected initial map for Array function"); | 7612 __ Assert(not_zero, kUnexpectedInitialMapForArrayFunction); |
7614 __ CmpObjectType(ecx, MAP_TYPE, ecx); | 7613 __ CmpObjectType(ecx, MAP_TYPE, ecx); |
7615 __ Assert(equal, "Unexpected initial map for Array function"); | 7614 __ Assert(equal, kUnexpectedInitialMapForArrayFunction); |
7616 | 7615 |
7617 // We should either have undefined in ebx or a valid cell | 7616 // We should either have undefined in ebx or a valid cell |
7618 Label okay_here; | 7617 Label okay_here; |
7619 Handle<Map> cell_map = masm->isolate()->factory()->cell_map(); | 7618 Handle<Map> cell_map = masm->isolate()->factory()->cell_map(); |
7620 __ cmp(ebx, Immediate(undefined_sentinel)); | 7619 __ cmp(ebx, Immediate(undefined_sentinel)); |
7621 __ j(equal, &okay_here); | 7620 __ j(equal, &okay_here); |
7622 __ cmp(FieldOperand(ebx, 0), Immediate(cell_map)); | 7621 __ cmp(FieldOperand(ebx, 0), Immediate(cell_map)); |
7623 __ Assert(equal, "Expected property cell in register ebx"); | 7622 __ Assert(equal, kExpectedPropertyCellInRegisterEbx); |
7624 __ bind(&okay_here); | 7623 __ bind(&okay_here); |
7625 } | 7624 } |
7626 | 7625 |
7627 Label no_info, switch_ready; | 7626 Label no_info, switch_ready; |
7628 // Get the elements kind and case on that. | 7627 // Get the elements kind and case on that. |
7629 __ cmp(ebx, Immediate(undefined_sentinel)); | 7628 __ cmp(ebx, Immediate(undefined_sentinel)); |
7630 __ j(equal, &no_info); | 7629 __ j(equal, &no_info); |
7631 __ mov(edx, FieldOperand(ebx, Cell::kValueOffset)); | 7630 __ mov(edx, FieldOperand(ebx, Cell::kValueOffset)); |
7632 | 7631 |
7633 // The type cell may have undefined in its value. | 7632 // The type cell may have undefined in its value. |
(...skipping 83 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
7717 // ----------------------------------- | 7716 // ----------------------------------- |
7718 | 7717 |
7719 if (FLAG_debug_code) { | 7718 if (FLAG_debug_code) { |
7720 // The array construct code is only set for the global and natives | 7719 // The array construct code is only set for the global and natives |
7721 // builtin Array functions which always have maps. | 7720 // builtin Array functions which always have maps. |
7722 | 7721 |
7723 // Initial map for the builtin Array function should be a map. | 7722 // Initial map for the builtin Array function should be a map. |
7724 __ mov(ecx, FieldOperand(edi, JSFunction::kPrototypeOrInitialMapOffset)); | 7723 __ mov(ecx, FieldOperand(edi, JSFunction::kPrototypeOrInitialMapOffset)); |
7725 // Will both indicate a NULL and a Smi. | 7724 // Will both indicate a NULL and a Smi. |
7726 __ test(ecx, Immediate(kSmiTagMask)); | 7725 __ test(ecx, Immediate(kSmiTagMask)); |
7727 __ Assert(not_zero, "Unexpected initial map for Array function"); | 7726 __ Assert(not_zero, kUnexpectedInitialMapForArrayFunction); |
7728 __ CmpObjectType(ecx, MAP_TYPE, ecx); | 7727 __ CmpObjectType(ecx, MAP_TYPE, ecx); |
7729 __ Assert(equal, "Unexpected initial map for Array function"); | 7728 __ Assert(equal, kUnexpectedInitialMapForArrayFunction); |
7730 } | 7729 } |
7731 | 7730 |
7732 // Figure out the right elements kind | 7731 // Figure out the right elements kind |
7733 __ mov(ecx, FieldOperand(edi, JSFunction::kPrototypeOrInitialMapOffset)); | 7732 __ mov(ecx, FieldOperand(edi, JSFunction::kPrototypeOrInitialMapOffset)); |
7734 | 7733 |
7735 // Load the map's "bit field 2" into |result|. We only need the first byte, | 7734 // Load the map's "bit field 2" into |result|. We only need the first byte, |
7736 // but the following masking takes care of that anyway. | 7735 // but the following masking takes care of that anyway. |
7737 __ mov(ecx, FieldOperand(ecx, Map::kBitField2Offset)); | 7736 __ mov(ecx, FieldOperand(ecx, Map::kBitField2Offset)); |
7738 // Retrieve elements_kind from bit field 2. | 7737 // Retrieve elements_kind from bit field 2. |
7739 __ and_(ecx, Map::kElementsKindMask); | 7738 __ and_(ecx, Map::kElementsKindMask); |
7740 __ shr(ecx, Map::kElementsKindShift); | 7739 __ shr(ecx, Map::kElementsKindShift); |
7741 | 7740 |
7742 if (FLAG_debug_code) { | 7741 if (FLAG_debug_code) { |
7743 Label done; | 7742 Label done; |
7744 __ cmp(ecx, Immediate(FAST_ELEMENTS)); | 7743 __ cmp(ecx, Immediate(FAST_ELEMENTS)); |
7745 __ j(equal, &done); | 7744 __ j(equal, &done); |
7746 __ cmp(ecx, Immediate(FAST_HOLEY_ELEMENTS)); | 7745 __ cmp(ecx, Immediate(FAST_HOLEY_ELEMENTS)); |
7747 __ Assert(equal, | 7746 __ Assert(equal, |
7748 "Invalid ElementsKind for InternalArray or InternalPackedArray"); | 7747 kInvalidElementsKindForInternalArrayOrInternalPackedArray); |
7749 __ bind(&done); | 7748 __ bind(&done); |
7750 } | 7749 } |
7751 | 7750 |
7752 Label fast_elements_case; | 7751 Label fast_elements_case; |
7753 __ cmp(ecx, Immediate(FAST_ELEMENTS)); | 7752 __ cmp(ecx, Immediate(FAST_ELEMENTS)); |
7754 __ j(equal, &fast_elements_case); | 7753 __ j(equal, &fast_elements_case); |
7755 GenerateCase(masm, FAST_HOLEY_ELEMENTS); | 7754 GenerateCase(masm, FAST_HOLEY_ELEMENTS); |
7756 | 7755 |
7757 __ bind(&fast_elements_case); | 7756 __ bind(&fast_elements_case); |
7758 GenerateCase(masm, FAST_ELEMENTS); | 7757 GenerateCase(masm, FAST_ELEMENTS); |
7759 } | 7758 } |
7760 | 7759 |
7761 | 7760 |
7762 #undef __ | 7761 #undef __ |
7763 | 7762 |
7764 } } // namespace v8::internal | 7763 } } // namespace v8::internal |
7765 | 7764 |
7766 #endif // V8_TARGET_ARCH_IA32 | 7765 #endif // V8_TARGET_ARCH_IA32 |
OLD | NEW |