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