| 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 1582 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1593 __ push(rax); // Save result on the stack | 1593 __ push(rax); // Save result on the stack |
| 1594 result_saved = true; | 1594 result_saved = true; |
| 1595 } | 1595 } |
| 1596 switch (property->kind()) { | 1596 switch (property->kind()) { |
| 1597 case ObjectLiteral::Property::CONSTANT: | 1597 case ObjectLiteral::Property::CONSTANT: |
| 1598 UNREACHABLE(); | 1598 UNREACHABLE(); |
| 1599 case ObjectLiteral::Property::MATERIALIZED_LITERAL: | 1599 case ObjectLiteral::Property::MATERIALIZED_LITERAL: |
| 1600 ASSERT(!CompileTimeValue::IsCompileTimeValue(value)); | 1600 ASSERT(!CompileTimeValue::IsCompileTimeValue(value)); |
| 1601 // Fall through. | 1601 // Fall through. |
| 1602 case ObjectLiteral::Property::COMPUTED: | 1602 case ObjectLiteral::Property::COMPUTED: |
| 1603 if (key->handle()->IsSymbol()) { | 1603 if (key->handle()->IsInternalizedString()) { |
| 1604 if (property->emit_store()) { | 1604 if (property->emit_store()) { |
| 1605 VisitForAccumulatorValue(value); | 1605 VisitForAccumulatorValue(value); |
| 1606 __ Move(rcx, key->handle()); | 1606 __ Move(rcx, key->handle()); |
| 1607 __ movq(rdx, Operand(rsp, 0)); | 1607 __ movq(rdx, Operand(rsp, 0)); |
| 1608 Handle<Code> ic = is_classic_mode() | 1608 Handle<Code> ic = is_classic_mode() |
| 1609 ? isolate()->builtins()->StoreIC_Initialize() | 1609 ? isolate()->builtins()->StoreIC_Initialize() |
| 1610 : isolate()->builtins()->StoreIC_Initialize_Strict(); | 1610 : isolate()->builtins()->StoreIC_Initialize_Strict(); |
| 1611 CallIC(ic, RelocInfo::CODE_TARGET, key->LiteralFeedbackId()); | 1611 CallIC(ic, RelocInfo::CODE_TARGET, key->LiteralFeedbackId()); |
| 1612 PrepareForBailoutForId(key->id(), NO_REGISTERS); | 1612 PrepareForBailoutForId(key->id(), NO_REGISTERS); |
| 1613 } else { | 1613 } else { |
| (...skipping 980 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2594 __ testb(FieldOperand(rbx, Map::kBitField2Offset), | 2594 __ testb(FieldOperand(rbx, Map::kBitField2Offset), |
| 2595 Immediate(1 << Map::kStringWrapperSafeForDefaultValueOf)); | 2595 Immediate(1 << Map::kStringWrapperSafeForDefaultValueOf)); |
| 2596 __ j(not_zero, if_true); | 2596 __ j(not_zero, if_true); |
| 2597 | 2597 |
| 2598 // Check for fast case object. Generate false result for slow case object. | 2598 // Check for fast case object. Generate false result for slow case object. |
| 2599 __ movq(rcx, FieldOperand(rax, JSObject::kPropertiesOffset)); | 2599 __ movq(rcx, FieldOperand(rax, JSObject::kPropertiesOffset)); |
| 2600 __ movq(rcx, FieldOperand(rcx, HeapObject::kMapOffset)); | 2600 __ movq(rcx, FieldOperand(rcx, HeapObject::kMapOffset)); |
| 2601 __ CompareRoot(rcx, Heap::kHashTableMapRootIndex); | 2601 __ CompareRoot(rcx, Heap::kHashTableMapRootIndex); |
| 2602 __ j(equal, if_false); | 2602 __ j(equal, if_false); |
| 2603 | 2603 |
| 2604 // Look for valueOf symbol in the descriptor array, and indicate false if | 2604 // Look for valueOf string in the descriptor array, and indicate false if |
| 2605 // found. Since we omit an enumeration index check, if it is added via a | 2605 // found. Since we omit an enumeration index check, if it is added via a |
| 2606 // transition that shares its descriptor array, this is a false positive. | 2606 // transition that shares its descriptor array, this is a false positive. |
| 2607 Label entry, loop, done; | 2607 Label entry, loop, done; |
| 2608 | 2608 |
| 2609 // Skip loop if no descriptors are valid. | 2609 // Skip loop if no descriptors are valid. |
| 2610 __ NumberOfOwnDescriptors(rcx, rbx); | 2610 __ NumberOfOwnDescriptors(rcx, rbx); |
| 2611 __ cmpq(rcx, Immediate(0)); | 2611 __ cmpq(rcx, Immediate(0)); |
| 2612 __ j(equal, &done); | 2612 __ j(equal, &done); |
| 2613 | 2613 |
| 2614 __ LoadInstanceDescriptors(rbx, rbx); | 2614 __ LoadInstanceDescriptors(rbx, rbx); |
| 2615 // rbx: descriptor array. | 2615 // rbx: descriptor array. |
| 2616 // rcx: valid entries in the descriptor array. | 2616 // rcx: valid entries in the descriptor array. |
| 2617 // Calculate the end of the descriptor array. | 2617 // Calculate the end of the descriptor array. |
| 2618 __ imul(rcx, rcx, Immediate(DescriptorArray::kDescriptorSize)); | 2618 __ imul(rcx, rcx, Immediate(DescriptorArray::kDescriptorSize)); |
| 2619 SmiIndex index = masm_->SmiToIndex(rdx, rcx, kPointerSizeLog2); | 2619 SmiIndex index = masm_->SmiToIndex(rdx, rcx, kPointerSizeLog2); |
| 2620 __ lea(rcx, | 2620 __ lea(rcx, |
| 2621 Operand( | 2621 Operand( |
| 2622 rbx, index.reg, index.scale, DescriptorArray::kFirstOffset)); | 2622 rbx, index.reg, index.scale, DescriptorArray::kFirstOffset)); |
| 2623 // Calculate location of the first key name. | 2623 // Calculate location of the first key name. |
| 2624 __ addq(rbx, Immediate(DescriptorArray::kFirstOffset)); | 2624 __ addq(rbx, Immediate(DescriptorArray::kFirstOffset)); |
| 2625 // Loop through all the keys in the descriptor array. If one of these is the | 2625 // Loop through all the keys in the descriptor array. If one of these is the |
| 2626 // symbol valueOf the result is false. | 2626 // internalized string "valueOf" the result is false. |
| 2627 __ jmp(&entry); | 2627 __ jmp(&entry); |
| 2628 __ bind(&loop); | 2628 __ bind(&loop); |
| 2629 __ movq(rdx, FieldOperand(rbx, 0)); | 2629 __ movq(rdx, FieldOperand(rbx, 0)); |
| 2630 __ Cmp(rdx, FACTORY->value_of_symbol()); | 2630 __ Cmp(rdx, FACTORY->value_of_string()); |
| 2631 __ j(equal, if_false); | 2631 __ j(equal, if_false); |
| 2632 __ addq(rbx, Immediate(DescriptorArray::kDescriptorSize * kPointerSize)); | 2632 __ addq(rbx, Immediate(DescriptorArray::kDescriptorSize * kPointerSize)); |
| 2633 __ bind(&entry); | 2633 __ bind(&entry); |
| 2634 __ cmpq(rbx, rcx); | 2634 __ cmpq(rbx, rcx); |
| 2635 __ j(not_equal, &loop); | 2635 __ j(not_equal, &loop); |
| 2636 | 2636 |
| 2637 __ bind(&done); | 2637 __ bind(&done); |
| 2638 // Reload map as register rbx was used as temporary above. | 2638 // Reload map as register rbx was used as temporary above. |
| 2639 __ movq(rbx, FieldOperand(rax, HeapObject::kMapOffset)); | 2639 __ movq(rbx, FieldOperand(rax, HeapObject::kMapOffset)); |
| 2640 | 2640 |
| (...skipping 214 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2855 __ j(not_equal, &non_function_constructor); | 2855 __ j(not_equal, &non_function_constructor); |
| 2856 | 2856 |
| 2857 // rax now contains the constructor function. Grab the | 2857 // rax now contains the constructor function. Grab the |
| 2858 // instance class name from there. | 2858 // instance class name from there. |
| 2859 __ movq(rax, FieldOperand(rax, JSFunction::kSharedFunctionInfoOffset)); | 2859 __ movq(rax, FieldOperand(rax, JSFunction::kSharedFunctionInfoOffset)); |
| 2860 __ movq(rax, FieldOperand(rax, SharedFunctionInfo::kInstanceClassNameOffset)); | 2860 __ movq(rax, FieldOperand(rax, SharedFunctionInfo::kInstanceClassNameOffset)); |
| 2861 __ jmp(&done); | 2861 __ jmp(&done); |
| 2862 | 2862 |
| 2863 // Functions have class 'Function'. | 2863 // Functions have class 'Function'. |
| 2864 __ bind(&function); | 2864 __ bind(&function); |
| 2865 __ Move(rax, isolate()->factory()->function_class_symbol()); | 2865 __ Move(rax, isolate()->factory()->function_class_string()); |
| 2866 __ jmp(&done); | 2866 __ jmp(&done); |
| 2867 | 2867 |
| 2868 // Objects with a non-function constructor have class 'Object'. | 2868 // Objects with a non-function constructor have class 'Object'. |
| 2869 __ bind(&non_function_constructor); | 2869 __ bind(&non_function_constructor); |
| 2870 __ Move(rax, isolate()->factory()->Object_symbol()); | 2870 __ Move(rax, isolate()->factory()->Object_string()); |
| 2871 __ jmp(&done); | 2871 __ jmp(&done); |
| 2872 | 2872 |
| 2873 // Non-JS objects have class null. | 2873 // Non-JS objects have class null. |
| 2874 __ bind(&null); | 2874 __ bind(&null); |
| 2875 __ LoadRoot(rax, Heap::kNullValueRootIndex); | 2875 __ LoadRoot(rax, Heap::kNullValueRootIndex); |
| 2876 | 2876 |
| 2877 // All done. | 2877 // All done. |
| 2878 __ bind(&done); | 2878 __ bind(&done); |
| 2879 | 2879 |
| 2880 context()->Plug(rax); | 2880 context()->Plug(rax); |
| (...skipping 339 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 3220 &need_conversion, | 3220 &need_conversion, |
| 3221 &need_conversion, | 3221 &need_conversion, |
| 3222 &index_out_of_range, | 3222 &index_out_of_range, |
| 3223 STRING_INDEX_IS_NUMBER); | 3223 STRING_INDEX_IS_NUMBER); |
| 3224 generator.GenerateFast(masm_); | 3224 generator.GenerateFast(masm_); |
| 3225 __ jmp(&done); | 3225 __ jmp(&done); |
| 3226 | 3226 |
| 3227 __ bind(&index_out_of_range); | 3227 __ bind(&index_out_of_range); |
| 3228 // When the index is out of range, the spec requires us to return | 3228 // When the index is out of range, the spec requires us to return |
| 3229 // the empty string. | 3229 // the empty string. |
| 3230 __ LoadRoot(result, Heap::kEmptyStringRootIndex); | 3230 __ LoadRoot(result, Heap::kempty_stringRootIndex); |
| 3231 __ jmp(&done); | 3231 __ jmp(&done); |
| 3232 | 3232 |
| 3233 __ bind(&need_conversion); | 3233 __ bind(&need_conversion); |
| 3234 // Move smi zero into the result register, which will trigger | 3234 // Move smi zero into the result register, which will trigger |
| 3235 // conversion. | 3235 // conversion. |
| 3236 __ Move(result, Smi::FromInt(0)); | 3236 __ Move(result, Smi::FromInt(0)); |
| 3237 __ jmp(&done); | 3237 __ jmp(&done); |
| 3238 | 3238 |
| 3239 NopRuntimeCallHelper call_helper; | 3239 NopRuntimeCallHelper call_helper; |
| 3240 generator.GenerateSlow(masm_, call_helper); | 3240 generator.GenerateSlow(masm_, call_helper); |
| (...skipping 305 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 3546 __ j(not_equal, &bailout); | 3546 __ j(not_equal, &bailout); |
| 3547 | 3547 |
| 3548 // Check that the array has fast elements. | 3548 // Check that the array has fast elements. |
| 3549 __ CheckFastElements(scratch, &bailout); | 3549 __ CheckFastElements(scratch, &bailout); |
| 3550 | 3550 |
| 3551 // Array has fast elements, so its length must be a smi. | 3551 // Array has fast elements, so its length must be a smi. |
| 3552 // If the array has length zero, return the empty string. | 3552 // If the array has length zero, return the empty string. |
| 3553 __ movq(array_length, FieldOperand(array, JSArray::kLengthOffset)); | 3553 __ movq(array_length, FieldOperand(array, JSArray::kLengthOffset)); |
| 3554 __ SmiCompare(array_length, Smi::FromInt(0)); | 3554 __ SmiCompare(array_length, Smi::FromInt(0)); |
| 3555 __ j(not_zero, &non_trivial_array); | 3555 __ j(not_zero, &non_trivial_array); |
| 3556 __ LoadRoot(rax, Heap::kEmptyStringRootIndex); | 3556 __ LoadRoot(rax, Heap::kempty_stringRootIndex); |
| 3557 __ jmp(&return_result); | 3557 __ jmp(&return_result); |
| 3558 | 3558 |
| 3559 // Save the array length on the stack. | 3559 // Save the array length on the stack. |
| 3560 __ bind(&non_trivial_array); | 3560 __ bind(&non_trivial_array); |
| 3561 __ SmiToInteger32(array_length, array_length); | 3561 __ SmiToInteger32(array_length, array_length); |
| 3562 __ movl(array_length_operand, array_length); | 3562 __ movl(array_length_operand, array_length); |
| 3563 | 3563 |
| 3564 // Save the FixedArray containing array's elements. | 3564 // Save the FixedArray containing array's elements. |
| 3565 // End of array's live range. | 3565 // End of array's live range. |
| 3566 elements = array; | 3566 elements = array; |
| (...skipping 641 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 4208 Label* if_false = NULL; | 4208 Label* if_false = NULL; |
| 4209 Label* fall_through = NULL; | 4209 Label* fall_through = NULL; |
| 4210 context()->PrepareTest(&materialize_true, &materialize_false, | 4210 context()->PrepareTest(&materialize_true, &materialize_false, |
| 4211 &if_true, &if_false, &fall_through); | 4211 &if_true, &if_false, &fall_through); |
| 4212 | 4212 |
| 4213 { AccumulatorValueContext context(this); | 4213 { AccumulatorValueContext context(this); |
| 4214 VisitForTypeofValue(sub_expr); | 4214 VisitForTypeofValue(sub_expr); |
| 4215 } | 4215 } |
| 4216 PrepareForBailoutBeforeSplit(expr, true, if_true, if_false); | 4216 PrepareForBailoutBeforeSplit(expr, true, if_true, if_false); |
| 4217 | 4217 |
| 4218 if (check->Equals(isolate()->heap()->number_symbol())) { | 4218 if (check->Equals(isolate()->heap()->number_string())) { |
| 4219 __ JumpIfSmi(rax, if_true); | 4219 __ JumpIfSmi(rax, if_true); |
| 4220 __ movq(rax, FieldOperand(rax, HeapObject::kMapOffset)); | 4220 __ movq(rax, FieldOperand(rax, HeapObject::kMapOffset)); |
| 4221 __ CompareRoot(rax, Heap::kHeapNumberMapRootIndex); | 4221 __ CompareRoot(rax, Heap::kHeapNumberMapRootIndex); |
| 4222 Split(equal, if_true, if_false, fall_through); | 4222 Split(equal, if_true, if_false, fall_through); |
| 4223 } else if (check->Equals(isolate()->heap()->string_symbol())) { | 4223 } else if (check->Equals(isolate()->heap()->string_string())) { |
| 4224 __ JumpIfSmi(rax, if_false); | 4224 __ JumpIfSmi(rax, if_false); |
| 4225 // Check for undetectable objects => false. | 4225 // Check for undetectable objects => false. |
| 4226 __ CmpObjectType(rax, FIRST_NONSTRING_TYPE, rdx); | 4226 __ CmpObjectType(rax, FIRST_NONSTRING_TYPE, rdx); |
| 4227 __ j(above_equal, if_false); | 4227 __ j(above_equal, if_false); |
| 4228 __ testb(FieldOperand(rdx, Map::kBitFieldOffset), | 4228 __ testb(FieldOperand(rdx, Map::kBitFieldOffset), |
| 4229 Immediate(1 << Map::kIsUndetectable)); | 4229 Immediate(1 << Map::kIsUndetectable)); |
| 4230 Split(zero, if_true, if_false, fall_through); | 4230 Split(zero, if_true, if_false, fall_through); |
| 4231 } else if (check->Equals(isolate()->heap()->boolean_symbol())) { | 4231 } else if (check->Equals(isolate()->heap()->boolean_string())) { |
| 4232 __ CompareRoot(rax, Heap::kTrueValueRootIndex); | 4232 __ CompareRoot(rax, Heap::kTrueValueRootIndex); |
| 4233 __ j(equal, if_true); | 4233 __ j(equal, if_true); |
| 4234 __ CompareRoot(rax, Heap::kFalseValueRootIndex); | 4234 __ CompareRoot(rax, Heap::kFalseValueRootIndex); |
| 4235 Split(equal, if_true, if_false, fall_through); | 4235 Split(equal, if_true, if_false, fall_through); |
| 4236 } else if (FLAG_harmony_typeof && | 4236 } else if (FLAG_harmony_typeof && |
| 4237 check->Equals(isolate()->heap()->null_symbol())) { | 4237 check->Equals(isolate()->heap()->null_string())) { |
| 4238 __ CompareRoot(rax, Heap::kNullValueRootIndex); | 4238 __ CompareRoot(rax, Heap::kNullValueRootIndex); |
| 4239 Split(equal, if_true, if_false, fall_through); | 4239 Split(equal, if_true, if_false, fall_through); |
| 4240 } else if (check->Equals(isolate()->heap()->undefined_symbol())) { | 4240 } else if (check->Equals(isolate()->heap()->undefined_string())) { |
| 4241 __ CompareRoot(rax, Heap::kUndefinedValueRootIndex); | 4241 __ CompareRoot(rax, Heap::kUndefinedValueRootIndex); |
| 4242 __ j(equal, if_true); | 4242 __ j(equal, if_true); |
| 4243 __ JumpIfSmi(rax, if_false); | 4243 __ JumpIfSmi(rax, if_false); |
| 4244 // Check for undetectable objects => true. | 4244 // Check for undetectable objects => true. |
| 4245 __ movq(rdx, FieldOperand(rax, HeapObject::kMapOffset)); | 4245 __ movq(rdx, FieldOperand(rax, HeapObject::kMapOffset)); |
| 4246 __ testb(FieldOperand(rdx, Map::kBitFieldOffset), | 4246 __ testb(FieldOperand(rdx, Map::kBitFieldOffset), |
| 4247 Immediate(1 << Map::kIsUndetectable)); | 4247 Immediate(1 << Map::kIsUndetectable)); |
| 4248 Split(not_zero, if_true, if_false, fall_through); | 4248 Split(not_zero, if_true, if_false, fall_through); |
| 4249 } else if (check->Equals(isolate()->heap()->function_symbol())) { | 4249 } else if (check->Equals(isolate()->heap()->function_string())) { |
| 4250 __ JumpIfSmi(rax, if_false); | 4250 __ JumpIfSmi(rax, if_false); |
| 4251 STATIC_ASSERT(NUM_OF_CALLABLE_SPEC_OBJECT_TYPES == 2); | 4251 STATIC_ASSERT(NUM_OF_CALLABLE_SPEC_OBJECT_TYPES == 2); |
| 4252 __ CmpObjectType(rax, JS_FUNCTION_TYPE, rdx); | 4252 __ CmpObjectType(rax, JS_FUNCTION_TYPE, rdx); |
| 4253 __ j(equal, if_true); | 4253 __ j(equal, if_true); |
| 4254 __ CmpInstanceType(rdx, JS_FUNCTION_PROXY_TYPE); | 4254 __ CmpInstanceType(rdx, JS_FUNCTION_PROXY_TYPE); |
| 4255 Split(equal, if_true, if_false, fall_through); | 4255 Split(equal, if_true, if_false, fall_through); |
| 4256 } else if (check->Equals(isolate()->heap()->object_symbol())) { | 4256 } else if (check->Equals(isolate()->heap()->object_string())) { |
| 4257 __ JumpIfSmi(rax, if_false); | 4257 __ JumpIfSmi(rax, if_false); |
| 4258 if (!FLAG_harmony_typeof) { | 4258 if (!FLAG_harmony_typeof) { |
| 4259 __ CompareRoot(rax, Heap::kNullValueRootIndex); | 4259 __ CompareRoot(rax, Heap::kNullValueRootIndex); |
| 4260 __ j(equal, if_true); | 4260 __ j(equal, if_true); |
| 4261 } | 4261 } |
| 4262 __ CmpObjectType(rax, FIRST_NONCALLABLE_SPEC_OBJECT_TYPE, rdx); | 4262 __ CmpObjectType(rax, FIRST_NONCALLABLE_SPEC_OBJECT_TYPE, rdx); |
| 4263 __ j(below, if_false); | 4263 __ j(below, if_false); |
| 4264 __ CmpInstanceType(rdx, LAST_NONCALLABLE_SPEC_OBJECT_TYPE); | 4264 __ CmpInstanceType(rdx, LAST_NONCALLABLE_SPEC_OBJECT_TYPE); |
| 4265 __ j(above, if_false); | 4265 __ j(above, if_false); |
| 4266 // Check for undetectable objects => false. | 4266 // Check for undetectable objects => false. |
| (...skipping 259 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 4526 *context_length = 0; | 4526 *context_length = 0; |
| 4527 return previous_; | 4527 return previous_; |
| 4528 } | 4528 } |
| 4529 | 4529 |
| 4530 | 4530 |
| 4531 #undef __ | 4531 #undef __ |
| 4532 | 4532 |
| 4533 } } // namespace v8::internal | 4533 } } // namespace v8::internal |
| 4534 | 4534 |
| 4535 #endif // V8_TARGET_ARCH_X64 | 4535 #endif // V8_TARGET_ARCH_X64 |
| OLD | NEW |