| 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 |