OLD | NEW |
1 // Copyright 2010 the V8 project authors. All rights reserved. | 1 // Copyright 2010 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 6023 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
6034 ASSERT(value.is_valid()); | 6034 ASSERT(value.is_valid()); |
6035 Condition is_smi = masm_->CheckSmi(value.reg()); | 6035 Condition is_smi = masm_->CheckSmi(value.reg()); |
6036 destination()->false_target()->Branch(is_smi); | 6036 destination()->false_target()->Branch(is_smi); |
6037 // Check that this is an object. | 6037 // Check that this is an object. |
6038 __ CmpObjectType(value.reg(), FIRST_JS_OBJECT_TYPE, kScratchRegister); | 6038 __ CmpObjectType(value.reg(), FIRST_JS_OBJECT_TYPE, kScratchRegister); |
6039 value.Unuse(); | 6039 value.Unuse(); |
6040 destination()->Split(above_equal); | 6040 destination()->Split(above_equal); |
6041 } | 6041 } |
6042 | 6042 |
6043 | 6043 |
| 6044 // Deferred code to check whether the String JavaScript object is safe for using |
| 6045 // default value of. This code is called after the bit caching this information |
| 6046 // in the map has been checked with the map for the object in the map_result_ |
| 6047 // register. On return the register map_result_ contains 1 for true and 0 for |
| 6048 // false. |
| 6049 class DeferredIsStringWrapperSafeForDefaultValueOf : public DeferredCode { |
| 6050 public: |
| 6051 DeferredIsStringWrapperSafeForDefaultValueOf(Register object, |
| 6052 Register map_result, |
| 6053 Register scratch1, |
| 6054 Register scratch2) |
| 6055 : object_(object), |
| 6056 map_result_(map_result), |
| 6057 scratch1_(scratch1), |
| 6058 scratch2_(scratch2) { } |
| 6059 |
| 6060 virtual void Generate() { |
| 6061 Label false_result; |
| 6062 |
| 6063 // Check that map is loaded as expected. |
| 6064 if (FLAG_debug_code) { |
| 6065 __ cmpq(map_result_, FieldOperand(object_, HeapObject::kMapOffset)); |
| 6066 __ Assert(equal, "Map not in expected register"); |
| 6067 } |
| 6068 |
| 6069 // Check for fast case object. Generate false result for slow case object. |
| 6070 __ movq(scratch1_, FieldOperand(object_, JSObject::kPropertiesOffset)); |
| 6071 __ movq(scratch1_, FieldOperand(scratch1_, HeapObject::kMapOffset)); |
| 6072 __ CompareRoot(scratch1_, Heap::kHashTableMapRootIndex); |
| 6073 __ j(equal, &false_result); |
| 6074 |
| 6075 // Look for valueOf symbol in the descriptor array, and indicate false if |
| 6076 // found. The type is not checked, so if it is a transition it is a false |
| 6077 // negative. |
| 6078 __ movq(map_result_, |
| 6079 FieldOperand(map_result_, Map::kInstanceDescriptorsOffset)); |
| 6080 __ movq(scratch1_, FieldOperand(map_result_, FixedArray::kLengthOffset)); |
| 6081 // map_result_: descriptor array |
| 6082 // scratch1_: length of descriptor array |
| 6083 // Calculate the end of the descriptor array. |
| 6084 SmiIndex index = masm_->SmiToIndex(scratch2_, scratch1_, kPointerSizeLog2); |
| 6085 __ lea(scratch1_, |
| 6086 Operand( |
| 6087 map_result_, index.reg, index.scale, FixedArray::kHeaderSize)); |
| 6088 // Calculate location of the first key name. |
| 6089 __ addq(map_result_, |
| 6090 Immediate(FixedArray::kHeaderSize + |
| 6091 DescriptorArray::kFirstIndex * kPointerSize)); |
| 6092 // Loop through all the keys in the descriptor array. If one of these is the |
| 6093 // symbol valueOf the result is false. |
| 6094 Label entry, loop; |
| 6095 __ jmp(&entry); |
| 6096 __ bind(&loop); |
| 6097 __ movq(scratch2_, FieldOperand(map_result_, 0)); |
| 6098 __ Cmp(scratch2_, Factory::value_of_symbol()); |
| 6099 __ j(equal, &false_result); |
| 6100 __ addq(map_result_, Immediate(kPointerSize)); |
| 6101 __ bind(&entry); |
| 6102 __ cmpq(map_result_, scratch1_); |
| 6103 __ j(not_equal, &loop); |
| 6104 |
| 6105 // Reload map as register map_result_ was used as temporary above. |
| 6106 __ movq(map_result_, FieldOperand(object_, HeapObject::kMapOffset)); |
| 6107 |
| 6108 // If a valueOf property is not found on the object check that it's |
| 6109 // prototype is the un-modified String prototype. If not result is false. |
| 6110 __ movq(scratch1_, FieldOperand(map_result_, Map::kPrototypeOffset)); |
| 6111 __ testq(scratch1_, Immediate(kSmiTagMask)); |
| 6112 __ j(zero, &false_result); |
| 6113 __ movq(scratch1_, FieldOperand(scratch1_, HeapObject::kMapOffset)); |
| 6114 __ movq(scratch2_, |
| 6115 Operand(rsi, Context::SlotOffset(Context::GLOBAL_INDEX))); |
| 6116 __ movq(scratch2_, |
| 6117 FieldOperand(scratch2_, GlobalObject::kGlobalContextOffset)); |
| 6118 __ cmpq(scratch1_, |
| 6119 CodeGenerator::ContextOperand( |
| 6120 scratch2_, Context::STRING_FUNCTION_PROTOTYPE_MAP_INDEX)); |
| 6121 __ j(not_equal, &false_result); |
| 6122 // Set the bit in the map to indicate that it has been checked safe for |
| 6123 // default valueOf and set true result. |
| 6124 __ or_(FieldOperand(map_result_, Map::kBitField2Offset), |
| 6125 Immediate(1 << Map::kStringWrapperSafeForDefaultValueOf)); |
| 6126 __ Set(map_result_, 1); |
| 6127 __ jmp(exit_label()); |
| 6128 __ bind(&false_result); |
| 6129 // Set false result. |
| 6130 __ Set(map_result_, 0); |
| 6131 } |
| 6132 |
| 6133 private: |
| 6134 Register object_; |
| 6135 Register map_result_; |
| 6136 Register scratch1_; |
| 6137 Register scratch2_; |
| 6138 }; |
| 6139 |
| 6140 |
| 6141 void CodeGenerator::GenerateIsStringWrapperSafeForDefaultValueOf( |
| 6142 ZoneList<Expression*>* args) { |
| 6143 ASSERT(args->length() == 1); |
| 6144 Load(args->at(0)); |
| 6145 Result obj = frame_->Pop(); // Pop the string wrapper. |
| 6146 obj.ToRegister(); |
| 6147 ASSERT(obj.is_valid()); |
| 6148 if (FLAG_debug_code) { |
| 6149 __ AbortIfSmi(obj.reg()); |
| 6150 } |
| 6151 |
| 6152 // Check whether this map has already been checked to be safe for default |
| 6153 // valueOf. |
| 6154 Result map_result = allocator()->Allocate(); |
| 6155 ASSERT(map_result.is_valid()); |
| 6156 __ movq(map_result.reg(), FieldOperand(obj.reg(), HeapObject::kMapOffset)); |
| 6157 __ testb(FieldOperand(map_result.reg(), Map::kBitField2Offset), |
| 6158 Immediate(1 << Map::kStringWrapperSafeForDefaultValueOf)); |
| 6159 destination()->true_target()->Branch(not_zero); |
| 6160 |
| 6161 // We need an additional two scratch registers for the deferred code. |
| 6162 Result temp1 = allocator()->Allocate(); |
| 6163 ASSERT(temp1.is_valid()); |
| 6164 Result temp2 = allocator()->Allocate(); |
| 6165 ASSERT(temp2.is_valid()); |
| 6166 |
| 6167 DeferredIsStringWrapperSafeForDefaultValueOf* deferred = |
| 6168 new DeferredIsStringWrapperSafeForDefaultValueOf( |
| 6169 obj.reg(), map_result.reg(), temp1.reg(), temp2.reg()); |
| 6170 deferred->Branch(zero); |
| 6171 deferred->BindExit(); |
| 6172 __ testq(map_result.reg(), map_result.reg()); |
| 6173 obj.Unuse(); |
| 6174 map_result.Unuse(); |
| 6175 temp1.Unuse(); |
| 6176 temp2.Unuse(); |
| 6177 destination()->Split(not_equal); |
| 6178 } |
| 6179 |
| 6180 |
6044 void CodeGenerator::GenerateIsFunction(ZoneList<Expression*>* args) { | 6181 void CodeGenerator::GenerateIsFunction(ZoneList<Expression*>* args) { |
6045 // This generates a fast version of: | 6182 // This generates a fast version of: |
6046 // (%_ClassOf(arg) === 'Function') | 6183 // (%_ClassOf(arg) === 'Function') |
6047 ASSERT(args->length() == 1); | 6184 ASSERT(args->length() == 1); |
6048 Load(args->at(0)); | 6185 Load(args->at(0)); |
6049 Result obj = frame_->Pop(); | 6186 Result obj = frame_->Pop(); |
6050 obj.ToRegister(); | 6187 obj.ToRegister(); |
6051 Condition is_smi = masm_->CheckSmi(obj.reg()); | 6188 Condition is_smi = masm_->CheckSmi(obj.reg()); |
6052 destination()->false_target()->Branch(is_smi); | 6189 destination()->false_target()->Branch(is_smi); |
6053 __ CmpObjectType(obj.reg(), JS_FUNCTION_TYPE, kScratchRegister); | 6190 __ CmpObjectType(obj.reg(), JS_FUNCTION_TYPE, kScratchRegister); |
(...skipping 6562 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
12616 #undef __ | 12753 #undef __ |
12617 | 12754 |
12618 void RecordWriteStub::Generate(MacroAssembler* masm) { | 12755 void RecordWriteStub::Generate(MacroAssembler* masm) { |
12619 masm->RecordWriteHelper(object_, addr_, scratch_); | 12756 masm->RecordWriteHelper(object_, addr_, scratch_); |
12620 masm->ret(0); | 12757 masm->ret(0); |
12621 } | 12758 } |
12622 | 12759 |
12623 } } // namespace v8::internal | 12760 } } // namespace v8::internal |
12624 | 12761 |
12625 #endif // V8_TARGET_ARCH_X64 | 12762 #endif // V8_TARGET_ARCH_X64 |
OLD | NEW |