 Chromium Code Reviews
 Chromium Code Reviews Issue 8187:
  Serendipitously arrange the tags so that String.length() becomes a branch-fre...  (Closed) 
  Base URL: http://v8.googlecode.com/svn/branches/bleeding_edge/
    
  
    Issue 8187:
  Serendipitously arrange the tags so that String.length() becomes a branch-fre...  (Closed) 
  Base URL: http://v8.googlecode.com/svn/branches/bleeding_edge/| OLD | NEW | 
|---|---|
| 1 // Copyright 2006-2008 the V8 project authors. All rights reserved. | 1 // Copyright 2006-2008 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 141 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 152 __ movzx_b(scratch, FieldOperand(scratch, Map::kInstanceTypeOffset)); | 152 __ movzx_b(scratch, FieldOperand(scratch, Map::kInstanceTypeOffset)); | 
| 153 __ cmp(scratch, JS_ARRAY_TYPE); | 153 __ cmp(scratch, JS_ARRAY_TYPE); | 
| 154 __ j(not_equal, miss_label, not_taken); | 154 __ j(not_equal, miss_label, not_taken); | 
| 155 | 155 | 
| 156 // Load length directly from the JS array. | 156 // Load length directly from the JS array. | 
| 157 __ mov(eax, FieldOperand(receiver, JSArray::kLengthOffset)); | 157 __ mov(eax, FieldOperand(receiver, JSArray::kLengthOffset)); | 
| 158 __ ret(0); | 158 __ ret(0); | 
| 159 } | 159 } | 
| 160 | 160 | 
| 161 | 161 | 
| 162 void StubCompiler::GenerateLoadShortStringLength(MacroAssembler* masm, | 162 void StubCompiler::GenerateLoadStringLength(MacroAssembler* masm, | 
| 163 Register receiver, | 163 Register receiver, | 
| 164 Register scratch, | 164 Register scratch, | 
| 165 Label* miss_label) { | 165 Label* miss_label) { | 
| 166 // Check that the receiver isn't a smi. | 166 // Check that the receiver isn't a smi. | 
| 167 __ test(receiver, Immediate(kSmiTagMask)); | 167 __ test(receiver, Immediate(kSmiTagMask)); | 
| 168 __ j(zero, miss_label, not_taken); | 168 __ j(zero, miss_label, not_taken); | 
| 169 | 169 | 
| 170 // Check that the object is a short string. | 170 // Check that the object is a string. | 
| 171 __ mov(scratch, FieldOperand(receiver, HeapObject::kMapOffset)); | 171 __ mov(scratch, FieldOperand(receiver, HeapObject::kMapOffset)); | 
| 172 __ movzx_b(scratch, FieldOperand(scratch, Map::kInstanceTypeOffset)); | 172 __ movzx_b(scratch, FieldOperand(scratch, Map::kInstanceTypeOffset)); | 
| 173 __ and_(scratch, kIsNotStringMask | kStringSizeMask); | 173 ASSERT(kNotStringTag != 0); | 
| 174 __ cmp(scratch, kStringTag | kShortStringTag); | 174 __ test(scratch, Immediate(kNotStringTag)); | 
| 175 __ j(not_equal, miss_label, not_taken); | 175 __ j(not_zero, miss_label, not_taken); | 
| 176 | |
| 177 __ and_(scratch, kStringSizeMask); | |
| 176 | 178 | 
| 177 // Load length directly from the string. | 179 // Load length directly from the string. | 
| 178 __ mov(eax, FieldOperand(receiver, String::kLengthOffset)); | 180 __ mov(eax, FieldOperand(receiver, String::kLengthOffset)); | 
| 179 __ shr(eax, String::kShortLengthShift); | 181 | 
| 182 // Ecx is also the receiver. | |
| 
Mads Ager (chromium)
2008/10/27 09:37:00
Ecx -> ecx since it is a register name?
 | |
| 183 __ lea(ecx, Operand(scratch, String::kLongLengthShift)); | |
| 184 __ shr(eax); // Ecx is implicit shift register. | |
| 
Mads Ager (chromium)
2008/10/27 09:37:00
Ditto?
 | |
| 180 __ shl(eax, kSmiTagSize); | 185 __ shl(eax, kSmiTagSize); | 
| 181 __ ret(0); | 186 __ ret(0); | 
| 182 } | 187 } | 
| 183 | |
| 184 void StubCompiler::GenerateLoadMediumStringLength(MacroAssembler* masm, | |
| 185 Register receiver, | |
| 186 Register scratch, | |
| 187 Label* miss_label) { | |
| 188 // Check that the receiver isn't a smi. | |
| 189 __ test(receiver, Immediate(kSmiTagMask)); | |
| 190 __ j(zero, miss_label, not_taken); | |
| 191 | |
| 192 // Check that the object is a short string. | |
| 193 __ mov(scratch, FieldOperand(receiver, HeapObject::kMapOffset)); | |
| 194 __ movzx_b(scratch, FieldOperand(scratch, Map::kInstanceTypeOffset)); | |
| 195 __ and_(scratch, kIsNotStringMask | kStringSizeMask); | |
| 196 __ cmp(scratch, kStringTag | kMediumStringTag); | |
| 197 __ j(not_equal, miss_label, not_taken); | |
| 198 | |
| 199 // Load length directly from the string. | |
| 200 __ mov(eax, FieldOperand(receiver, String::kLengthOffset)); | |
| 201 __ shr(eax, String::kMediumLengthShift); | |
| 202 __ shl(eax, kSmiTagSize); | |
| 203 __ ret(0); | |
| 204 } | |
| 205 | |
| 206 | |
| 207 void StubCompiler::GenerateLoadLongStringLength(MacroAssembler* masm, | |
| 208 Register receiver, | |
| 209 Register scratch, | |
| 210 Label* miss_label) { | |
| 211 // Check that the receiver isn't a smi. | |
| 212 __ test(receiver, Immediate(kSmiTagMask)); | |
| 213 __ j(zero, miss_label, not_taken); | |
| 214 | |
| 215 // Check that the object is a short string. | |
| 216 __ mov(scratch, FieldOperand(receiver, HeapObject::kMapOffset)); | |
| 217 __ movzx_b(scratch, FieldOperand(scratch, Map::kInstanceTypeOffset)); | |
| 218 __ and_(scratch, kIsNotStringMask | kStringSizeMask); | |
| 219 __ cmp(scratch, kStringTag | kLongStringTag); | |
| 220 __ j(not_equal, miss_label, not_taken); | |
| 221 | |
| 222 // Load length directly from the string. | |
| 223 __ mov(eax, FieldOperand(receiver, String::kLengthOffset)); | |
| 224 __ shr(eax, String::kLongLengthShift); | |
| 225 __ shl(eax, kSmiTagSize); | |
| 226 __ ret(0); | |
| 227 } | |
| 228 | 188 | 
| 229 | 189 | 
| 230 void StubCompiler::GenerateLoadFunctionPrototype(MacroAssembler* masm, | 190 void StubCompiler::GenerateLoadFunctionPrototype(MacroAssembler* masm, | 
| 231 Register receiver, | 191 Register receiver, | 
| 232 Register scratch1, | 192 Register scratch1, | 
| 233 Register scratch2, | 193 Register scratch2, | 
| 234 Label* miss_label) { | 194 Label* miss_label) { | 
| 235 __ TryGetFunctionPrototype(receiver, scratch1, scratch2, miss_label); | 195 __ TryGetFunctionPrototype(receiver, scratch1, scratch2, miss_label); | 
| 236 __ mov(eax, Operand(scratch1)); | 196 __ mov(eax, Operand(scratch1)); | 
| 237 __ ret(0); | 197 __ ret(0); | 
| (...skipping 908 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1146 GenerateLoadArrayLength(masm(), ecx, edx, &miss); | 1106 GenerateLoadArrayLength(masm(), ecx, edx, &miss); | 
| 1147 __ bind(&miss); | 1107 __ bind(&miss); | 
| 1148 __ DecrementCounter(&Counters::keyed_load_array_length, 1); | 1108 __ DecrementCounter(&Counters::keyed_load_array_length, 1); | 
| 1149 GenerateLoadMiss(masm(), Code::KEYED_LOAD_IC); | 1109 GenerateLoadMiss(masm(), Code::KEYED_LOAD_IC); | 
| 1150 | 1110 | 
| 1151 // Return the generated code. | 1111 // Return the generated code. | 
| 1152 return GetCode(CALLBACKS); | 1112 return GetCode(CALLBACKS); | 
| 1153 } | 1113 } | 
| 1154 | 1114 | 
| 1155 | 1115 | 
| 1156 Object* KeyedLoadStubCompiler::CompileLoadShortStringLength(String* name) { | 1116 Object* KeyedLoadStubCompiler::CompileLoadStringLength(String* name) { | 
| 1157 // ----------- S t a t e ------------- | 1117 // ----------- S t a t e ------------- | 
| 1158 // -- esp[0] : return address | 1118 // -- esp[0] : return address | 
| 1159 // -- esp[4] : name | 1119 // -- esp[4] : name | 
| 1160 // -- esp[8] : receiver | 1120 // -- esp[8] : receiver | 
| 1161 // ----------------------------------- | 1121 // ----------------------------------- | 
| 1162 HandleScope scope; | 1122 HandleScope scope; | 
| 1163 Label miss; | 1123 Label miss; | 
| 1164 | 1124 | 
| 1165 __ mov(eax, (Operand(esp, kPointerSize))); | 1125 __ mov(eax, (Operand(esp, kPointerSize))); | 
| 1166 __ mov(ecx, (Operand(esp, 2 * kPointerSize))); | 1126 __ mov(ecx, (Operand(esp, 2 * kPointerSize))); | 
| 1167 __ IncrementCounter(&Counters::keyed_load_string_length, 1); | 1127 __ IncrementCounter(&Counters::keyed_load_string_length, 1); | 
| 1168 | 1128 | 
| 1169 // Check that the name has not changed. | 1129 // Check that the name has not changed. | 
| 1170 __ cmp(Operand(eax), Immediate(Handle<String>(name))); | 1130 __ cmp(Operand(eax), Immediate(Handle<String>(name))); | 
| 1171 __ j(not_equal, &miss, not_taken); | 1131 __ j(not_equal, &miss, not_taken); | 
| 1172 | 1132 | 
| 1173 GenerateLoadShortStringLength(masm(), ecx, edx, &miss); | 1133 GenerateLoadStringLength(masm(), ecx, edx, &miss); | 
| 1174 __ bind(&miss); | 1134 __ bind(&miss); | 
| 1175 __ DecrementCounter(&Counters::keyed_load_string_length, 1); | 1135 __ DecrementCounter(&Counters::keyed_load_string_length, 1); | 
| 1176 GenerateLoadMiss(masm(), Code::KEYED_LOAD_IC); | 1136 GenerateLoadMiss(masm(), Code::KEYED_LOAD_IC); | 
| 1177 | 1137 | 
| 1178 // Return the generated code. | 1138 // Return the generated code. | 
| 1179 return GetCode(CALLBACKS); | 1139 return GetCode(CALLBACKS); | 
| 1180 } | 1140 } | 
| 1181 | 1141 | 
| 1182 | 1142 | 
| 1183 Object* KeyedLoadStubCompiler::CompileLoadMediumStringLength(String* name) { | |
| 1184 // ----------- S t a t e ------------- | |
| 1185 // -- esp[0] : return address | |
| 1186 // -- esp[4] : name | |
| 1187 // -- esp[8] : receiver | |
| 1188 // ----------------------------------- | |
| 1189 HandleScope scope; | |
| 1190 Label miss; | |
| 1191 | |
| 1192 __ mov(eax, (Operand(esp, kPointerSize))); | |
| 1193 __ mov(ecx, (Operand(esp, 2 * kPointerSize))); | |
| 1194 __ IncrementCounter(&Counters::keyed_load_string_length, 1); | |
| 1195 | |
| 1196 // Check that the name has not changed. | |
| 1197 __ cmp(Operand(eax), Immediate(Handle<String>(name))); | |
| 1198 __ j(not_equal, &miss, not_taken); | |
| 1199 | |
| 1200 GenerateLoadMediumStringLength(masm(), ecx, edx, &miss); | |
| 1201 __ bind(&miss); | |
| 1202 __ DecrementCounter(&Counters::keyed_load_string_length, 1); | |
| 1203 GenerateLoadMiss(masm(), Code::KEYED_LOAD_IC); | |
| 1204 | |
| 1205 // Return the generated code. | |
| 1206 return GetCode(CALLBACKS); | |
| 1207 } | |
| 1208 | |
| 1209 | |
| 1210 Object* KeyedLoadStubCompiler::CompileLoadLongStringLength(String* name) { | |
| 1211 // ----------- S t a t e ------------- | |
| 1212 // -- esp[0] : return address | |
| 1213 // -- esp[4] : name | |
| 1214 // -- esp[8] : receiver | |
| 1215 // ----------------------------------- | |
| 1216 HandleScope scope; | |
| 1217 Label miss; | |
| 1218 | |
| 1219 __ mov(eax, (Operand(esp, kPointerSize))); | |
| 1220 __ mov(ecx, (Operand(esp, 2 * kPointerSize))); | |
| 1221 __ IncrementCounter(&Counters::keyed_load_string_length, 1); | |
| 1222 | |
| 1223 // Check that the name has not changed. | |
| 1224 __ cmp(Operand(eax), Immediate(Handle<String>(name))); | |
| 1225 __ j(not_equal, &miss, not_taken); | |
| 1226 | |
| 1227 GenerateLoadLongStringLength(masm(), ecx, edx, &miss); | |
| 1228 __ bind(&miss); | |
| 1229 __ DecrementCounter(&Counters::keyed_load_string_length, 1); | |
| 1230 GenerateLoadMiss(masm(), Code::KEYED_LOAD_IC); | |
| 1231 | |
| 1232 // Return the generated code. | |
| 1233 return GetCode(CALLBACKS); | |
| 1234 } | |
| 1235 | |
| 1236 | |
| 1237 Object* KeyedLoadStubCompiler::CompileLoadFunctionPrototype(String* name) { | 1143 Object* KeyedLoadStubCompiler::CompileLoadFunctionPrototype(String* name) { | 
| 1238 // ----------- S t a t e ------------- | 1144 // ----------- S t a t e ------------- | 
| 1239 // -- esp[0] : return address | 1145 // -- esp[0] : return address | 
| 1240 // -- esp[4] : name | 1146 // -- esp[4] : name | 
| 1241 // -- esp[8] : receiver | 1147 // -- esp[8] : receiver | 
| 1242 // ----------------------------------- | 1148 // ----------------------------------- | 
| 1243 HandleScope scope; | 1149 HandleScope scope; | 
| 1244 Label miss; | 1150 Label miss; | 
| 1245 | 1151 | 
| 1246 __ mov(eax, (Operand(esp, kPointerSize))); | 1152 __ mov(eax, (Operand(esp, kPointerSize))); | 
| (...skipping 10 matching lines...) Expand all Loading... | |
| 1257 GenerateLoadMiss(masm(), Code::KEYED_LOAD_IC); | 1163 GenerateLoadMiss(masm(), Code::KEYED_LOAD_IC); | 
| 1258 | 1164 | 
| 1259 // Return the generated code. | 1165 // Return the generated code. | 
| 1260 return GetCode(CALLBACKS); | 1166 return GetCode(CALLBACKS); | 
| 1261 } | 1167 } | 
| 1262 | 1168 | 
| 1263 | 1169 | 
| 1264 #undef __ | 1170 #undef __ | 
| 1265 | 1171 | 
| 1266 } } // namespace v8::internal | 1172 } } // namespace v8::internal | 
| OLD | NEW |