OLD | NEW |
1 // Copyright 2011 the V8 project authors. All rights reserved. | 1 // Copyright 2011 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 170 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
181 ASSERT(!scratch.is(name)); | 181 ASSERT(!scratch.is(name)); |
182 ASSERT(!extra.is(receiver)); | 182 ASSERT(!extra.is(receiver)); |
183 ASSERT(!extra.is(name)); | 183 ASSERT(!extra.is(name)); |
184 ASSERT(!extra.is(scratch)); | 184 ASSERT(!extra.is(scratch)); |
185 | 185 |
186 // Check scratch and extra registers are valid, and extra2 is unused. | 186 // Check scratch and extra registers are valid, and extra2 is unused. |
187 ASSERT(!scratch.is(no_reg)); | 187 ASSERT(!scratch.is(no_reg)); |
188 ASSERT(extra2.is(no_reg)); | 188 ASSERT(extra2.is(no_reg)); |
189 | 189 |
190 // Check that the receiver isn't a smi. | 190 // Check that the receiver isn't a smi. |
191 __ test(receiver, Immediate(kSmiTagMask)); | 191 __ JumpIfSmi(receiver, &miss); |
192 __ j(zero, &miss); | |
193 | 192 |
194 // Get the map of the receiver and compute the hash. | 193 // Get the map of the receiver and compute the hash. |
195 __ mov(scratch, FieldOperand(name, String::kHashFieldOffset)); | 194 __ mov(scratch, FieldOperand(name, String::kHashFieldOffset)); |
196 __ add(scratch, FieldOperand(receiver, HeapObject::kMapOffset)); | 195 __ add(scratch, FieldOperand(receiver, HeapObject::kMapOffset)); |
197 __ xor_(scratch, flags); | 196 __ xor_(scratch, flags); |
198 __ and_(scratch, (kPrimaryTableSize - 1) << kHeapObjectTagSize); | 197 __ and_(scratch, (kPrimaryTableSize - 1) << kHeapObjectTagSize); |
199 | 198 |
200 // Probe the primary table. | 199 // Probe the primary table. |
201 ProbeTable(isolate, masm, flags, kPrimary, name, scratch, extra); | 200 ProbeTable(isolate, masm, flags, kPrimary, name, scratch, extra); |
202 | 201 |
(...skipping 39 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
242 // Load the prototype from the initial map. | 241 // Load the prototype from the initial map. |
243 __ mov(prototype, FieldOperand(prototype, Map::kPrototypeOffset)); | 242 __ mov(prototype, FieldOperand(prototype, Map::kPrototypeOffset)); |
244 } | 243 } |
245 | 244 |
246 | 245 |
247 void StubCompiler::GenerateLoadArrayLength(MacroAssembler* masm, | 246 void StubCompiler::GenerateLoadArrayLength(MacroAssembler* masm, |
248 Register receiver, | 247 Register receiver, |
249 Register scratch, | 248 Register scratch, |
250 Label* miss_label) { | 249 Label* miss_label) { |
251 // Check that the receiver isn't a smi. | 250 // Check that the receiver isn't a smi. |
252 __ test(receiver, Immediate(kSmiTagMask)); | 251 __ JumpIfSmi(receiver, miss_label); |
253 __ j(zero, miss_label); | |
254 | 252 |
255 // Check that the object is a JS array. | 253 // Check that the object is a JS array. |
256 __ CmpObjectType(receiver, JS_ARRAY_TYPE, scratch); | 254 __ CmpObjectType(receiver, JS_ARRAY_TYPE, scratch); |
257 __ j(not_equal, miss_label); | 255 __ j(not_equal, miss_label); |
258 | 256 |
259 // Load length directly from the JS array. | 257 // Load length directly from the JS array. |
260 __ mov(eax, FieldOperand(receiver, JSArray::kLengthOffset)); | 258 __ mov(eax, FieldOperand(receiver, JSArray::kLengthOffset)); |
261 __ ret(0); | 259 __ ret(0); |
262 } | 260 } |
263 | 261 |
264 | 262 |
265 // Generate code to check if an object is a string. If the object is | 263 // Generate code to check if an object is a string. If the object is |
266 // a string, the map's instance type is left in the scratch register. | 264 // a string, the map's instance type is left in the scratch register. |
267 static void GenerateStringCheck(MacroAssembler* masm, | 265 static void GenerateStringCheck(MacroAssembler* masm, |
268 Register receiver, | 266 Register receiver, |
269 Register scratch, | 267 Register scratch, |
270 Label* smi, | 268 Label* smi, |
271 Label* non_string_object) { | 269 Label* non_string_object) { |
272 // Check that the object isn't a smi. | 270 // Check that the object isn't a smi. |
273 __ test(receiver, Immediate(kSmiTagMask)); | 271 __ JumpIfSmi(receiver, smi); |
274 __ j(zero, smi); | |
275 | 272 |
276 // Check that the object is a string. | 273 // Check that the object is a string. |
277 __ mov(scratch, FieldOperand(receiver, HeapObject::kMapOffset)); | 274 __ mov(scratch, FieldOperand(receiver, HeapObject::kMapOffset)); |
278 __ movzx_b(scratch, FieldOperand(scratch, Map::kInstanceTypeOffset)); | 275 __ movzx_b(scratch, FieldOperand(scratch, Map::kInstanceTypeOffset)); |
279 ASSERT(kNotStringTag != 0); | 276 ASSERT(kNotStringTag != 0); |
280 __ test(scratch, Immediate(kNotStringTag)); | 277 __ test(scratch, Immediate(kNotStringTag)); |
281 __ j(not_zero, non_string_object); | 278 __ j(not_zero, non_string_object); |
282 } | 279 } |
283 | 280 |
284 | 281 |
(...skipping 217 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
502 LookupResult* lookup, | 499 LookupResult* lookup, |
503 Register receiver, | 500 Register receiver, |
504 Register scratch1, | 501 Register scratch1, |
505 Register scratch2, | 502 Register scratch2, |
506 Register scratch3, | 503 Register scratch3, |
507 Label* miss) { | 504 Label* miss) { |
508 ASSERT(holder->HasNamedInterceptor()); | 505 ASSERT(holder->HasNamedInterceptor()); |
509 ASSERT(!holder->GetNamedInterceptor()->getter()->IsUndefined()); | 506 ASSERT(!holder->GetNamedInterceptor()->getter()->IsUndefined()); |
510 | 507 |
511 // Check that the receiver isn't a smi. | 508 // Check that the receiver isn't a smi. |
512 __ test(receiver, Immediate(kSmiTagMask)); | 509 __ JumpIfSmi(receiver, miss); |
513 __ j(zero, miss); | |
514 | 510 |
515 CallOptimization optimization(lookup); | 511 CallOptimization optimization(lookup); |
516 | 512 |
517 if (optimization.is_constant_call()) { | 513 if (optimization.is_constant_call()) { |
518 return CompileCacheable(masm, | 514 return CompileCacheable(masm, |
519 object, | 515 object, |
520 receiver, | 516 receiver, |
521 scratch1, | 517 scratch1, |
522 scratch2, | 518 scratch2, |
523 scratch3, | 519 scratch3, |
(...skipping 207 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
731 // but may be destroyed if store is successful. | 727 // but may be destroyed if store is successful. |
732 void StubCompiler::GenerateStoreField(MacroAssembler* masm, | 728 void StubCompiler::GenerateStoreField(MacroAssembler* masm, |
733 JSObject* object, | 729 JSObject* object, |
734 int index, | 730 int index, |
735 Map* transition, | 731 Map* transition, |
736 Register receiver_reg, | 732 Register receiver_reg, |
737 Register name_reg, | 733 Register name_reg, |
738 Register scratch, | 734 Register scratch, |
739 Label* miss_label) { | 735 Label* miss_label) { |
740 // Check that the object isn't a smi. | 736 // Check that the object isn't a smi. |
741 __ test(receiver_reg, Immediate(kSmiTagMask)); | 737 __ JumpIfSmi(receiver_reg, miss_label); |
742 __ j(zero, miss_label); | |
743 | 738 |
744 // Check that the map of the object hasn't changed. | 739 // Check that the map of the object hasn't changed. |
745 __ cmp(FieldOperand(receiver_reg, HeapObject::kMapOffset), | 740 __ cmp(FieldOperand(receiver_reg, HeapObject::kMapOffset), |
746 Immediate(Handle<Map>(object->map()))); | 741 Immediate(Handle<Map>(object->map()))); |
747 __ j(not_equal, miss_label); | 742 __ j(not_equal, miss_label); |
748 | 743 |
749 // Perform global security token check if needed. | 744 // Perform global security token check if needed. |
750 if (object->IsJSGlobalProxy()) { | 745 if (object->IsJSGlobalProxy()) { |
751 __ CheckAccessGlobalProxy(receiver_reg, scratch, miss_label); | 746 __ CheckAccessGlobalProxy(receiver_reg, scratch, miss_label); |
752 } | 747 } |
(...skipping 260 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1013 void StubCompiler::GenerateLoadField(JSObject* object, | 1008 void StubCompiler::GenerateLoadField(JSObject* object, |
1014 JSObject* holder, | 1009 JSObject* holder, |
1015 Register receiver, | 1010 Register receiver, |
1016 Register scratch1, | 1011 Register scratch1, |
1017 Register scratch2, | 1012 Register scratch2, |
1018 Register scratch3, | 1013 Register scratch3, |
1019 int index, | 1014 int index, |
1020 String* name, | 1015 String* name, |
1021 Label* miss) { | 1016 Label* miss) { |
1022 // Check that the receiver isn't a smi. | 1017 // Check that the receiver isn't a smi. |
1023 __ test(receiver, Immediate(kSmiTagMask)); | 1018 __ JumpIfSmi(receiver, miss); |
1024 __ j(zero, miss); | |
1025 | 1019 |
1026 // Check the prototype chain. | 1020 // Check the prototype chain. |
1027 Register reg = | 1021 Register reg = |
1028 CheckPrototypes(object, receiver, holder, | 1022 CheckPrototypes(object, receiver, holder, |
1029 scratch1, scratch2, scratch3, name, miss); | 1023 scratch1, scratch2, scratch3, name, miss); |
1030 | 1024 |
1031 // Get the value from the properties. | 1025 // Get the value from the properties. |
1032 GenerateFastPropertyLoad(masm(), eax, reg, holder, index); | 1026 GenerateFastPropertyLoad(masm(), eax, reg, holder, index); |
1033 __ ret(0); | 1027 __ ret(0); |
1034 } | 1028 } |
1035 | 1029 |
1036 | 1030 |
1037 MaybeObject* StubCompiler::GenerateLoadCallback(JSObject* object, | 1031 MaybeObject* StubCompiler::GenerateLoadCallback(JSObject* object, |
1038 JSObject* holder, | 1032 JSObject* holder, |
1039 Register receiver, | 1033 Register receiver, |
1040 Register name_reg, | 1034 Register name_reg, |
1041 Register scratch1, | 1035 Register scratch1, |
1042 Register scratch2, | 1036 Register scratch2, |
1043 Register scratch3, | 1037 Register scratch3, |
1044 AccessorInfo* callback, | 1038 AccessorInfo* callback, |
1045 String* name, | 1039 String* name, |
1046 Label* miss) { | 1040 Label* miss) { |
1047 // Check that the receiver isn't a smi. | 1041 // Check that the receiver isn't a smi. |
1048 __ test(receiver, Immediate(kSmiTagMask)); | 1042 __ JumpIfSmi(receiver, miss); |
1049 __ j(zero, miss); | |
1050 | 1043 |
1051 // Check that the maps haven't changed. | 1044 // Check that the maps haven't changed. |
1052 Register reg = | 1045 Register reg = |
1053 CheckPrototypes(object, receiver, holder, scratch1, | 1046 CheckPrototypes(object, receiver, holder, scratch1, |
1054 scratch2, scratch3, name, miss); | 1047 scratch2, scratch3, name, miss); |
1055 | 1048 |
1056 Handle<AccessorInfo> callback_handle(callback); | 1049 Handle<AccessorInfo> callback_handle(callback); |
1057 | 1050 |
1058 // Insert additional parameters into the stack frame above return address. | 1051 // Insert additional parameters into the stack frame above return address. |
1059 ASSERT(!scratch3.is(reg)); | 1052 ASSERT(!scratch3.is(reg)); |
(...skipping 45 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1105 void StubCompiler::GenerateLoadConstant(JSObject* object, | 1098 void StubCompiler::GenerateLoadConstant(JSObject* object, |
1106 JSObject* holder, | 1099 JSObject* holder, |
1107 Register receiver, | 1100 Register receiver, |
1108 Register scratch1, | 1101 Register scratch1, |
1109 Register scratch2, | 1102 Register scratch2, |
1110 Register scratch3, | 1103 Register scratch3, |
1111 Object* value, | 1104 Object* value, |
1112 String* name, | 1105 String* name, |
1113 Label* miss) { | 1106 Label* miss) { |
1114 // Check that the receiver isn't a smi. | 1107 // Check that the receiver isn't a smi. |
1115 __ test(receiver, Immediate(kSmiTagMask)); | 1108 __ JumpIfSmi(receiver, miss); |
1116 __ j(zero, miss); | |
1117 | 1109 |
1118 // Check that the maps haven't changed. | 1110 // Check that the maps haven't changed. |
1119 CheckPrototypes(object, receiver, holder, | 1111 CheckPrototypes(object, receiver, holder, |
1120 scratch1, scratch2, scratch3, name, miss); | 1112 scratch1, scratch2, scratch3, name, miss); |
1121 | 1113 |
1122 // Return the constant value. | 1114 // Return the constant value. |
1123 __ mov(eax, Handle<Object>(value)); | 1115 __ mov(eax, Handle<Object>(value)); |
1124 __ ret(0); | 1116 __ ret(0); |
1125 } | 1117 } |
1126 | 1118 |
1127 | 1119 |
1128 void StubCompiler::GenerateLoadInterceptor(JSObject* object, | 1120 void StubCompiler::GenerateLoadInterceptor(JSObject* object, |
1129 JSObject* interceptor_holder, | 1121 JSObject* interceptor_holder, |
1130 LookupResult* lookup, | 1122 LookupResult* lookup, |
1131 Register receiver, | 1123 Register receiver, |
1132 Register name_reg, | 1124 Register name_reg, |
1133 Register scratch1, | 1125 Register scratch1, |
1134 Register scratch2, | 1126 Register scratch2, |
1135 Register scratch3, | 1127 Register scratch3, |
1136 String* name, | 1128 String* name, |
1137 Label* miss) { | 1129 Label* miss) { |
1138 ASSERT(interceptor_holder->HasNamedInterceptor()); | 1130 ASSERT(interceptor_holder->HasNamedInterceptor()); |
1139 ASSERT(!interceptor_holder->GetNamedInterceptor()->getter()->IsUndefined()); | 1131 ASSERT(!interceptor_holder->GetNamedInterceptor()->getter()->IsUndefined()); |
1140 | 1132 |
1141 // Check that the receiver isn't a smi. | 1133 // Check that the receiver isn't a smi. |
1142 __ test(receiver, Immediate(kSmiTagMask)); | 1134 __ JumpIfSmi(receiver, miss); |
1143 __ j(zero, miss); | |
1144 | 1135 |
1145 // So far the most popular follow ups for interceptor loads are FIELD | 1136 // So far the most popular follow ups for interceptor loads are FIELD |
1146 // and CALLBACKS, so inline only them, other cases may be added | 1137 // and CALLBACKS, so inline only them, other cases may be added |
1147 // later. | 1138 // later. |
1148 bool compile_followup_inline = false; | 1139 bool compile_followup_inline = false; |
1149 if (lookup->IsProperty() && lookup->IsCacheable()) { | 1140 if (lookup->IsProperty() && lookup->IsCacheable()) { |
1150 if (lookup->type() == FIELD) { | 1141 if (lookup->type() == FIELD) { |
1151 compile_followup_inline = true; | 1142 compile_followup_inline = true; |
1152 } else if (lookup->type() == CALLBACKS && | 1143 } else if (lookup->type() == CALLBACKS && |
1153 lookup->GetCallbackObject()->IsAccessorInfo() && | 1144 lookup->GetCallbackObject()->IsAccessorInfo() && |
(...skipping 129 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1283 // Get the number of arguments. | 1274 // Get the number of arguments. |
1284 const int argc = arguments().immediate(); | 1275 const int argc = arguments().immediate(); |
1285 | 1276 |
1286 // Get the receiver from the stack. | 1277 // Get the receiver from the stack. |
1287 __ mov(edx, Operand(esp, (argc + 1) * kPointerSize)); | 1278 __ mov(edx, Operand(esp, (argc + 1) * kPointerSize)); |
1288 | 1279 |
1289 // If the object is the holder then we know that it's a global | 1280 // If the object is the holder then we know that it's a global |
1290 // object which can only happen for contextual calls. In this case, | 1281 // object which can only happen for contextual calls. In this case, |
1291 // the receiver cannot be a smi. | 1282 // the receiver cannot be a smi. |
1292 if (object != holder) { | 1283 if (object != holder) { |
1293 __ test(edx, Immediate(kSmiTagMask)); | 1284 __ JumpIfSmi(edx, miss); |
1294 __ j(zero, miss); | |
1295 } | 1285 } |
1296 | 1286 |
1297 // Check that the maps haven't changed. | 1287 // Check that the maps haven't changed. |
1298 CheckPrototypes(object, edx, holder, ebx, eax, edi, name, miss); | 1288 CheckPrototypes(object, edx, holder, ebx, eax, edi, name, miss); |
1299 } | 1289 } |
1300 | 1290 |
1301 | 1291 |
1302 void CallStubCompiler::GenerateLoadFunctionFromCell(JSGlobalPropertyCell* cell, | 1292 void CallStubCompiler::GenerateLoadFunctionFromCell(JSGlobalPropertyCell* cell, |
1303 JSFunction* function, | 1293 JSFunction* function, |
1304 Label* miss) { | 1294 Label* miss) { |
1305 // Get the value from the cell. | 1295 // Get the value from the cell. |
1306 if (Serializer::enabled()) { | 1296 if (Serializer::enabled()) { |
1307 __ mov(edi, Immediate(Handle<JSGlobalPropertyCell>(cell))); | 1297 __ mov(edi, Immediate(Handle<JSGlobalPropertyCell>(cell))); |
1308 __ mov(edi, FieldOperand(edi, JSGlobalPropertyCell::kValueOffset)); | 1298 __ mov(edi, FieldOperand(edi, JSGlobalPropertyCell::kValueOffset)); |
1309 } else { | 1299 } else { |
1310 __ mov(edi, Operand::Cell(Handle<JSGlobalPropertyCell>(cell))); | 1300 __ mov(edi, Operand::Cell(Handle<JSGlobalPropertyCell>(cell))); |
1311 } | 1301 } |
1312 | 1302 |
1313 // Check that the cell contains the same function. | 1303 // Check that the cell contains the same function. |
1314 if (isolate()->heap()->InNewSpace(function)) { | 1304 if (isolate()->heap()->InNewSpace(function)) { |
1315 // We can't embed a pointer to a function in new space so we have | 1305 // We can't embed a pointer to a function in new space so we have |
1316 // to verify that the shared function info is unchanged. This has | 1306 // to verify that the shared function info is unchanged. This has |
1317 // the nice side effect that multiple closures based on the same | 1307 // the nice side effect that multiple closures based on the same |
1318 // function can all use this call IC. Before we load through the | 1308 // function can all use this call IC. Before we load through the |
1319 // function, we have to verify that it still is a function. | 1309 // function, we have to verify that it still is a function. |
1320 __ test(edi, Immediate(kSmiTagMask)); | 1310 __ JumpIfSmi(edi, miss); |
1321 __ j(zero, miss); | |
1322 __ CmpObjectType(edi, JS_FUNCTION_TYPE, ebx); | 1311 __ CmpObjectType(edi, JS_FUNCTION_TYPE, ebx); |
1323 __ j(not_equal, miss); | 1312 __ j(not_equal, miss); |
1324 | 1313 |
1325 // Check the shared function info. Make sure it hasn't changed. | 1314 // Check the shared function info. Make sure it hasn't changed. |
1326 __ cmp(FieldOperand(edi, JSFunction::kSharedFunctionInfoOffset), | 1315 __ cmp(FieldOperand(edi, JSFunction::kSharedFunctionInfoOffset), |
1327 Immediate(Handle<SharedFunctionInfo>(function->shared()))); | 1316 Immediate(Handle<SharedFunctionInfo>(function->shared()))); |
1328 __ j(not_equal, miss); | 1317 __ j(not_equal, miss); |
1329 } else { | 1318 } else { |
1330 __ cmp(Operand(edi), Immediate(Handle<JSFunction>(function))); | 1319 __ cmp(Operand(edi), Immediate(Handle<JSFunction>(function))); |
1331 __ j(not_equal, miss); | 1320 __ j(not_equal, miss); |
(...skipping 27 matching lines...) Expand all Loading... |
1359 // ----------------------------------- | 1348 // ----------------------------------- |
1360 Label miss; | 1349 Label miss; |
1361 | 1350 |
1362 GenerateNameCheck(name, &miss); | 1351 GenerateNameCheck(name, &miss); |
1363 | 1352 |
1364 // Get the receiver from the stack. | 1353 // Get the receiver from the stack. |
1365 const int argc = arguments().immediate(); | 1354 const int argc = arguments().immediate(); |
1366 __ mov(edx, Operand(esp, (argc + 1) * kPointerSize)); | 1355 __ mov(edx, Operand(esp, (argc + 1) * kPointerSize)); |
1367 | 1356 |
1368 // Check that the receiver isn't a smi. | 1357 // Check that the receiver isn't a smi. |
1369 __ test(edx, Immediate(kSmiTagMask)); | 1358 __ JumpIfSmi(edx, &miss); |
1370 __ j(zero, &miss); | |
1371 | 1359 |
1372 // Do the right check and compute the holder register. | 1360 // Do the right check and compute the holder register. |
1373 Register reg = CheckPrototypes(object, edx, holder, ebx, eax, edi, | 1361 Register reg = CheckPrototypes(object, edx, holder, ebx, eax, edi, |
1374 name, &miss); | 1362 name, &miss); |
1375 | 1363 |
1376 GenerateFastPropertyLoad(masm(), edi, reg, holder, index); | 1364 GenerateFastPropertyLoad(masm(), edi, reg, holder, index); |
1377 | 1365 |
1378 // Check that the function really is a function. | 1366 // Check that the function really is a function. |
1379 __ test(edi, Immediate(kSmiTagMask)); | 1367 __ JumpIfSmi(edi, &miss); |
1380 __ j(zero, &miss); | |
1381 __ CmpObjectType(edi, JS_FUNCTION_TYPE, ebx); | 1368 __ CmpObjectType(edi, JS_FUNCTION_TYPE, ebx); |
1382 __ j(not_equal, &miss); | 1369 __ j(not_equal, &miss); |
1383 | 1370 |
1384 // Patch the receiver on the stack with the global proxy if | 1371 // Patch the receiver on the stack with the global proxy if |
1385 // necessary. | 1372 // necessary. |
1386 if (object->IsGlobalObject()) { | 1373 if (object->IsGlobalObject()) { |
1387 __ mov(edx, FieldOperand(edx, GlobalObject::kGlobalReceiverOffset)); | 1374 __ mov(edx, FieldOperand(edx, GlobalObject::kGlobalReceiverOffset)); |
1388 __ mov(Operand(esp, (argc + 1) * kPointerSize), edx); | 1375 __ mov(Operand(esp, (argc + 1) * kPointerSize), edx); |
1389 } | 1376 } |
1390 | 1377 |
(...skipping 34 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1425 | 1412 |
1426 Label miss; | 1413 Label miss; |
1427 | 1414 |
1428 GenerateNameCheck(name, &miss); | 1415 GenerateNameCheck(name, &miss); |
1429 | 1416 |
1430 // Get the receiver from the stack. | 1417 // Get the receiver from the stack. |
1431 const int argc = arguments().immediate(); | 1418 const int argc = arguments().immediate(); |
1432 __ mov(edx, Operand(esp, (argc + 1) * kPointerSize)); | 1419 __ mov(edx, Operand(esp, (argc + 1) * kPointerSize)); |
1433 | 1420 |
1434 // Check that the receiver isn't a smi. | 1421 // Check that the receiver isn't a smi. |
1435 __ test(edx, Immediate(kSmiTagMask)); | 1422 __ JumpIfSmi(edx, &miss); |
1436 __ j(zero, &miss); | |
1437 | 1423 |
1438 CheckPrototypes(JSObject::cast(object), edx, | 1424 CheckPrototypes(JSObject::cast(object), edx, |
1439 holder, ebx, | 1425 holder, ebx, |
1440 eax, edi, name, &miss); | 1426 eax, edi, name, &miss); |
1441 | 1427 |
1442 if (argc == 0) { | 1428 if (argc == 0) { |
1443 // Noop, return the length. | 1429 // Noop, return the length. |
1444 __ mov(eax, FieldOperand(edx, JSArray::kLengthOffset)); | 1430 __ mov(eax, FieldOperand(edx, JSArray::kLengthOffset)); |
1445 __ ret((argc + 1) * kPointerSize); | 1431 __ ret((argc + 1) * kPointerSize); |
1446 } else { | 1432 } else { |
(...skipping 27 matching lines...) Expand all Loading... |
1474 __ mov(FieldOperand(edx, JSArray::kLengthOffset), eax); | 1460 __ mov(FieldOperand(edx, JSArray::kLengthOffset), eax); |
1475 | 1461 |
1476 // Push the element. | 1462 // Push the element. |
1477 __ lea(edx, FieldOperand(ebx, | 1463 __ lea(edx, FieldOperand(ebx, |
1478 eax, times_half_pointer_size, | 1464 eax, times_half_pointer_size, |
1479 FixedArray::kHeaderSize - argc * kPointerSize)); | 1465 FixedArray::kHeaderSize - argc * kPointerSize)); |
1480 __ mov(ecx, Operand(esp, argc * kPointerSize)); | 1466 __ mov(ecx, Operand(esp, argc * kPointerSize)); |
1481 __ mov(Operand(edx, 0), ecx); | 1467 __ mov(Operand(edx, 0), ecx); |
1482 | 1468 |
1483 // Check if value is a smi. | 1469 // Check if value is a smi. |
1484 __ test(ecx, Immediate(kSmiTagMask)); | 1470 __ JumpIfNotSmi(ecx, &with_write_barrier); |
1485 __ j(not_zero, &with_write_barrier); | |
1486 | 1471 |
1487 __ bind(&exit); | 1472 __ bind(&exit); |
1488 __ ret((argc + 1) * kPointerSize); | 1473 __ ret((argc + 1) * kPointerSize); |
1489 | 1474 |
1490 __ bind(&with_write_barrier); | 1475 __ bind(&with_write_barrier); |
1491 | 1476 |
1492 __ InNewSpace(ebx, ecx, equal, &exit); | 1477 __ InNewSpace(ebx, ecx, equal, &exit); |
1493 | 1478 |
1494 __ RecordWriteHelper(ebx, edx, ecx); | 1479 __ RecordWriteHelper(ebx, edx, ecx); |
1495 __ ret((argc + 1) * kPointerSize); | 1480 __ ret((argc + 1) * kPointerSize); |
(...skipping 82 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1578 | 1563 |
1579 Label miss, return_undefined, call_builtin; | 1564 Label miss, return_undefined, call_builtin; |
1580 | 1565 |
1581 GenerateNameCheck(name, &miss); | 1566 GenerateNameCheck(name, &miss); |
1582 | 1567 |
1583 // Get the receiver from the stack. | 1568 // Get the receiver from the stack. |
1584 const int argc = arguments().immediate(); | 1569 const int argc = arguments().immediate(); |
1585 __ mov(edx, Operand(esp, (argc + 1) * kPointerSize)); | 1570 __ mov(edx, Operand(esp, (argc + 1) * kPointerSize)); |
1586 | 1571 |
1587 // Check that the receiver isn't a smi. | 1572 // Check that the receiver isn't a smi. |
1588 __ test(edx, Immediate(kSmiTagMask)); | 1573 __ JumpIfSmi(edx, &miss); |
1589 __ j(zero, &miss); | |
1590 CheckPrototypes(JSObject::cast(object), edx, | 1574 CheckPrototypes(JSObject::cast(object), edx, |
1591 holder, ebx, | 1575 holder, ebx, |
1592 eax, edi, name, &miss); | 1576 eax, edi, name, &miss); |
1593 | 1577 |
1594 // Get the elements array of the object. | 1578 // Get the elements array of the object. |
1595 __ mov(ebx, FieldOperand(edx, JSArray::kElementsOffset)); | 1579 __ mov(ebx, FieldOperand(edx, JSArray::kElementsOffset)); |
1596 | 1580 |
1597 // Check that the elements are in fast mode and writable. | 1581 // Check that the elements are in fast mode and writable. |
1598 __ cmp(FieldOperand(ebx, HeapObject::kMapOffset), | 1582 __ cmp(FieldOperand(ebx, HeapObject::kMapOffset), |
1599 Immediate(factory()->fixed_array_map())); | 1583 Immediate(factory()->fixed_array_map())); |
(...skipping 238 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1838 return isolate()->heap()->undefined_value(); | 1822 return isolate()->heap()->undefined_value(); |
1839 } | 1823 } |
1840 | 1824 |
1841 Label miss; | 1825 Label miss; |
1842 GenerateNameCheck(name, &miss); | 1826 GenerateNameCheck(name, &miss); |
1843 | 1827 |
1844 if (cell == NULL) { | 1828 if (cell == NULL) { |
1845 __ mov(edx, Operand(esp, 2 * kPointerSize)); | 1829 __ mov(edx, Operand(esp, 2 * kPointerSize)); |
1846 | 1830 |
1847 STATIC_ASSERT(kSmiTag == 0); | 1831 STATIC_ASSERT(kSmiTag == 0); |
1848 __ test(edx, Immediate(kSmiTagMask)); | 1832 __ JumpIfSmi(edx, &miss); |
1849 __ j(zero, &miss); | |
1850 | 1833 |
1851 CheckPrototypes(JSObject::cast(object), edx, holder, ebx, eax, edi, name, | 1834 CheckPrototypes(JSObject::cast(object), edx, holder, ebx, eax, edi, name, |
1852 &miss); | 1835 &miss); |
1853 } else { | 1836 } else { |
1854 ASSERT(cell->value() == function); | 1837 ASSERT(cell->value() == function); |
1855 GenerateGlobalReceiverCheck(JSObject::cast(object), holder, name, &miss); | 1838 GenerateGlobalReceiverCheck(JSObject::cast(object), holder, name, &miss); |
1856 GenerateLoadFunctionFromCell(cell, function, &miss); | 1839 GenerateLoadFunctionFromCell(cell, function, &miss); |
1857 } | 1840 } |
1858 | 1841 |
1859 // Load the char code argument. | 1842 // Load the char code argument. |
1860 Register code = ebx; | 1843 Register code = ebx; |
1861 __ mov(code, Operand(esp, 1 * kPointerSize)); | 1844 __ mov(code, Operand(esp, 1 * kPointerSize)); |
1862 | 1845 |
1863 // Check the code is a smi. | 1846 // Check the code is a smi. |
1864 Label slow; | 1847 Label slow; |
1865 STATIC_ASSERT(kSmiTag == 0); | 1848 STATIC_ASSERT(kSmiTag == 0); |
1866 __ test(code, Immediate(kSmiTagMask)); | 1849 __ JumpIfNotSmi(code, &slow); |
1867 __ j(not_zero, &slow); | |
1868 | 1850 |
1869 // Convert the smi code to uint16. | 1851 // Convert the smi code to uint16. |
1870 __ and_(code, Immediate(Smi::FromInt(0xffff))); | 1852 __ and_(code, Immediate(Smi::FromInt(0xffff))); |
1871 | 1853 |
1872 StringCharFromCodeGenerator char_from_code_generator(code, eax); | 1854 StringCharFromCodeGenerator char_from_code_generator(code, eax); |
1873 char_from_code_generator.GenerateFast(masm()); | 1855 char_from_code_generator.GenerateFast(masm()); |
1874 __ ret(2 * kPointerSize); | 1856 __ ret(2 * kPointerSize); |
1875 | 1857 |
1876 StubRuntimeCallHelper call_helper; | 1858 StubRuntimeCallHelper call_helper; |
1877 char_from_code_generator.GenerateSlow(masm(), call_helper); | 1859 char_from_code_generator.GenerateSlow(masm(), call_helper); |
(...skipping 44 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1922 return isolate()->heap()->undefined_value(); | 1904 return isolate()->heap()->undefined_value(); |
1923 } | 1905 } |
1924 | 1906 |
1925 Label miss; | 1907 Label miss; |
1926 GenerateNameCheck(name, &miss); | 1908 GenerateNameCheck(name, &miss); |
1927 | 1909 |
1928 if (cell == NULL) { | 1910 if (cell == NULL) { |
1929 __ mov(edx, Operand(esp, 2 * kPointerSize)); | 1911 __ mov(edx, Operand(esp, 2 * kPointerSize)); |
1930 | 1912 |
1931 STATIC_ASSERT(kSmiTag == 0); | 1913 STATIC_ASSERT(kSmiTag == 0); |
1932 __ test(edx, Immediate(kSmiTagMask)); | 1914 __ JumpIfSmi(edx, &miss); |
1933 __ j(zero, &miss); | |
1934 | 1915 |
1935 CheckPrototypes(JSObject::cast(object), edx, holder, ebx, eax, edi, name, | 1916 CheckPrototypes(JSObject::cast(object), edx, holder, ebx, eax, edi, name, |
1936 &miss); | 1917 &miss); |
1937 } else { | 1918 } else { |
1938 ASSERT(cell->value() == function); | 1919 ASSERT(cell->value() == function); |
1939 GenerateGlobalReceiverCheck(JSObject::cast(object), holder, name, &miss); | 1920 GenerateGlobalReceiverCheck(JSObject::cast(object), holder, name, &miss); |
1940 GenerateLoadFunctionFromCell(cell, function, &miss); | 1921 GenerateLoadFunctionFromCell(cell, function, &miss); |
1941 } | 1922 } |
1942 | 1923 |
1943 // Load the (only) argument into eax. | 1924 // Load the (only) argument into eax. |
1944 __ mov(eax, Operand(esp, 1 * kPointerSize)); | 1925 __ mov(eax, Operand(esp, 1 * kPointerSize)); |
1945 | 1926 |
1946 // Check if the argument is a smi. | 1927 // Check if the argument is a smi. |
1947 Label smi; | 1928 Label smi; |
1948 STATIC_ASSERT(kSmiTag == 0); | 1929 STATIC_ASSERT(kSmiTag == 0); |
1949 __ test(eax, Immediate(kSmiTagMask)); | 1930 __ JumpIfSmi(eax, &smi); |
1950 __ j(zero, &smi); | |
1951 | 1931 |
1952 // Check if the argument is a heap number and load its value into xmm0. | 1932 // Check if the argument is a heap number and load its value into xmm0. |
1953 Label slow; | 1933 Label slow; |
1954 __ CheckMap(eax, factory()->heap_number_map(), &slow, DONT_DO_SMI_CHECK); | 1934 __ CheckMap(eax, factory()->heap_number_map(), &slow, DONT_DO_SMI_CHECK); |
1955 __ movdbl(xmm0, FieldOperand(eax, HeapNumber::kValueOffset)); | 1935 __ movdbl(xmm0, FieldOperand(eax, HeapNumber::kValueOffset)); |
1956 | 1936 |
1957 // Check if the argument is strictly positive. Note this also | 1937 // Check if the argument is strictly positive. Note this also |
1958 // discards NaN. | 1938 // discards NaN. |
1959 __ xorpd(xmm1, xmm1); | 1939 __ xorpd(xmm1, xmm1); |
1960 __ ucomisd(xmm0, xmm1); | 1940 __ ucomisd(xmm0, xmm1); |
(...skipping 86 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2047 return isolate()->heap()->undefined_value(); | 2027 return isolate()->heap()->undefined_value(); |
2048 } | 2028 } |
2049 | 2029 |
2050 Label miss; | 2030 Label miss; |
2051 GenerateNameCheck(name, &miss); | 2031 GenerateNameCheck(name, &miss); |
2052 | 2032 |
2053 if (cell == NULL) { | 2033 if (cell == NULL) { |
2054 __ mov(edx, Operand(esp, 2 * kPointerSize)); | 2034 __ mov(edx, Operand(esp, 2 * kPointerSize)); |
2055 | 2035 |
2056 STATIC_ASSERT(kSmiTag == 0); | 2036 STATIC_ASSERT(kSmiTag == 0); |
2057 __ test(edx, Immediate(kSmiTagMask)); | 2037 __ JumpIfSmi(edx, &miss); |
2058 __ j(zero, &miss); | |
2059 | 2038 |
2060 CheckPrototypes(JSObject::cast(object), edx, holder, ebx, eax, edi, name, | 2039 CheckPrototypes(JSObject::cast(object), edx, holder, ebx, eax, edi, name, |
2061 &miss); | 2040 &miss); |
2062 } else { | 2041 } else { |
2063 ASSERT(cell->value() == function); | 2042 ASSERT(cell->value() == function); |
2064 GenerateGlobalReceiverCheck(JSObject::cast(object), holder, name, &miss); | 2043 GenerateGlobalReceiverCheck(JSObject::cast(object), holder, name, &miss); |
2065 GenerateLoadFunctionFromCell(cell, function, &miss); | 2044 GenerateLoadFunctionFromCell(cell, function, &miss); |
2066 } | 2045 } |
2067 | 2046 |
2068 // Load the (only) argument into eax. | 2047 // Load the (only) argument into eax. |
2069 __ mov(eax, Operand(esp, 1 * kPointerSize)); | 2048 __ mov(eax, Operand(esp, 1 * kPointerSize)); |
2070 | 2049 |
2071 // Check if the argument is a smi. | 2050 // Check if the argument is a smi. |
2072 Label not_smi; | 2051 Label not_smi; |
2073 STATIC_ASSERT(kSmiTag == 0); | 2052 STATIC_ASSERT(kSmiTag == 0); |
2074 __ test(eax, Immediate(kSmiTagMask)); | 2053 __ JumpIfNotSmi(eax, ¬_smi); |
2075 __ j(not_zero, ¬_smi); | |
2076 | 2054 |
2077 // Set ebx to 1...1 (== -1) if the argument is negative, or to 0...0 | 2055 // Set ebx to 1...1 (== -1) if the argument is negative, or to 0...0 |
2078 // otherwise. | 2056 // otherwise. |
2079 __ mov(ebx, eax); | 2057 __ mov(ebx, eax); |
2080 __ sar(ebx, kBitsPerInt - 1); | 2058 __ sar(ebx, kBitsPerInt - 1); |
2081 | 2059 |
2082 // Do bitwise not or do nothing depending on ebx. | 2060 // Do bitwise not or do nothing depending on ebx. |
2083 __ xor_(eax, Operand(ebx)); | 2061 __ xor_(eax, Operand(ebx)); |
2084 | 2062 |
2085 // Add 1 or do nothing depending on ebx. | 2063 // Add 1 or do nothing depending on ebx. |
(...skipping 65 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2151 | 2129 |
2152 Label miss, miss_before_stack_reserved; | 2130 Label miss, miss_before_stack_reserved; |
2153 | 2131 |
2154 GenerateNameCheck(name, &miss_before_stack_reserved); | 2132 GenerateNameCheck(name, &miss_before_stack_reserved); |
2155 | 2133 |
2156 // Get the receiver from the stack. | 2134 // Get the receiver from the stack. |
2157 const int argc = arguments().immediate(); | 2135 const int argc = arguments().immediate(); |
2158 __ mov(edx, Operand(esp, (argc + 1) * kPointerSize)); | 2136 __ mov(edx, Operand(esp, (argc + 1) * kPointerSize)); |
2159 | 2137 |
2160 // Check that the receiver isn't a smi. | 2138 // Check that the receiver isn't a smi. |
2161 __ test(edx, Immediate(kSmiTagMask)); | 2139 __ JumpIfSmi(edx, &miss_before_stack_reserved); |
2162 __ j(zero, &miss_before_stack_reserved); | |
2163 | 2140 |
2164 Counters* counters = isolate()->counters(); | 2141 Counters* counters = isolate()->counters(); |
2165 __ IncrementCounter(counters->call_const(), 1); | 2142 __ IncrementCounter(counters->call_const(), 1); |
2166 __ IncrementCounter(counters->call_const_fast_api(), 1); | 2143 __ IncrementCounter(counters->call_const_fast_api(), 1); |
2167 | 2144 |
2168 // Allocate space for v8::Arguments implicit values. Must be initialized | 2145 // Allocate space for v8::Arguments implicit values. Must be initialized |
2169 // before calling any runtime function. | 2146 // before calling any runtime function. |
2170 __ sub(Operand(esp), Immediate(kFastApiCallArguments * kPointerSize)); | 2147 __ sub(Operand(esp), Immediate(kFastApiCallArguments * kPointerSize)); |
2171 | 2148 |
2172 // Check that the maps haven't changed and find a Holder as a side effect. | 2149 // Check that the maps haven't changed and find a Holder as a side effect. |
(...skipping 47 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2220 Label miss; | 2197 Label miss; |
2221 | 2198 |
2222 GenerateNameCheck(name, &miss); | 2199 GenerateNameCheck(name, &miss); |
2223 | 2200 |
2224 // Get the receiver from the stack. | 2201 // Get the receiver from the stack. |
2225 const int argc = arguments().immediate(); | 2202 const int argc = arguments().immediate(); |
2226 __ mov(edx, Operand(esp, (argc + 1) * kPointerSize)); | 2203 __ mov(edx, Operand(esp, (argc + 1) * kPointerSize)); |
2227 | 2204 |
2228 // Check that the receiver isn't a smi. | 2205 // Check that the receiver isn't a smi. |
2229 if (check != NUMBER_CHECK) { | 2206 if (check != NUMBER_CHECK) { |
2230 __ test(edx, Immediate(kSmiTagMask)); | 2207 __ JumpIfSmi(edx, &miss); |
2231 __ j(zero, &miss); | |
2232 } | 2208 } |
2233 | 2209 |
2234 // Make sure that it's okay not to patch the on stack receiver | 2210 // Make sure that it's okay not to patch the on stack receiver |
2235 // unless we're doing a receiver map check. | 2211 // unless we're doing a receiver map check. |
2236 ASSERT(!object->IsGlobalObject() || check == RECEIVER_MAP_CHECK); | 2212 ASSERT(!object->IsGlobalObject() || check == RECEIVER_MAP_CHECK); |
2237 | 2213 |
2238 SharedFunctionInfo* function_info = function->shared(); | 2214 SharedFunctionInfo* function_info = function->shared(); |
2239 switch (check) { | 2215 switch (check) { |
2240 case RECEIVER_MAP_CHECK: | 2216 case RECEIVER_MAP_CHECK: |
2241 __ IncrementCounter(isolate()->counters()->call_const(), 1); | 2217 __ IncrementCounter(isolate()->counters()->call_const(), 1); |
(...skipping 28 matching lines...) Expand all Loading... |
2270 break; | 2246 break; |
2271 | 2247 |
2272 case NUMBER_CHECK: { | 2248 case NUMBER_CHECK: { |
2273 if (!function->IsBuiltin() && !function_info->strict_mode()) { | 2249 if (!function->IsBuiltin() && !function_info->strict_mode()) { |
2274 // Calling non-strict non-builtins with a value as the receiver | 2250 // Calling non-strict non-builtins with a value as the receiver |
2275 // requires boxing. | 2251 // requires boxing. |
2276 __ jmp(&miss); | 2252 __ jmp(&miss); |
2277 } else { | 2253 } else { |
2278 Label fast; | 2254 Label fast; |
2279 // Check that the object is a smi or a heap number. | 2255 // Check that the object is a smi or a heap number. |
2280 __ test(edx, Immediate(kSmiTagMask)); | 2256 __ JumpIfSmi(edx, &fast); |
2281 __ j(zero, &fast); | |
2282 __ CmpObjectType(edx, HEAP_NUMBER_TYPE, eax); | 2257 __ CmpObjectType(edx, HEAP_NUMBER_TYPE, eax); |
2283 __ j(not_equal, &miss); | 2258 __ j(not_equal, &miss); |
2284 __ bind(&fast); | 2259 __ bind(&fast); |
2285 // Check that the maps starting from the prototype haven't changed. | 2260 // Check that the maps starting from the prototype haven't changed. |
2286 GenerateDirectLoadGlobalFunctionPrototype( | 2261 GenerateDirectLoadGlobalFunctionPrototype( |
2287 masm(), Context::NUMBER_FUNCTION_INDEX, eax, &miss); | 2262 masm(), Context::NUMBER_FUNCTION_INDEX, eax, &miss); |
2288 CheckPrototypes(JSObject::cast(object->GetPrototype()), eax, holder, | 2263 CheckPrototypes(JSObject::cast(object->GetPrototype()), eax, holder, |
2289 ebx, edx, edi, name, &miss); | 2264 ebx, edx, edi, name, &miss); |
2290 } | 2265 } |
2291 break; | 2266 break; |
(...skipping 74 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2366 ebx, | 2341 ebx, |
2367 edi, | 2342 edi, |
2368 eax, | 2343 eax, |
2369 &miss); | 2344 &miss); |
2370 if (result->IsFailure()) return result; | 2345 if (result->IsFailure()) return result; |
2371 | 2346 |
2372 // Restore receiver. | 2347 // Restore receiver. |
2373 __ mov(edx, Operand(esp, (argc + 1) * kPointerSize)); | 2348 __ mov(edx, Operand(esp, (argc + 1) * kPointerSize)); |
2374 | 2349 |
2375 // Check that the function really is a function. | 2350 // Check that the function really is a function. |
2376 __ test(eax, Immediate(kSmiTagMask)); | 2351 __ JumpIfSmi(eax, &miss); |
2377 __ j(zero, &miss); | |
2378 __ CmpObjectType(eax, JS_FUNCTION_TYPE, ebx); | 2352 __ CmpObjectType(eax, JS_FUNCTION_TYPE, ebx); |
2379 __ j(not_equal, &miss); | 2353 __ j(not_equal, &miss); |
2380 | 2354 |
2381 // Patch the receiver on the stack with the global proxy if | 2355 // Patch the receiver on the stack with the global proxy if |
2382 // necessary. | 2356 // necessary. |
2383 if (object->IsGlobalObject()) { | 2357 if (object->IsGlobalObject()) { |
2384 __ mov(edx, FieldOperand(edx, GlobalObject::kGlobalReceiverOffset)); | 2358 __ mov(edx, FieldOperand(edx, GlobalObject::kGlobalReceiverOffset)); |
2385 __ mov(Operand(esp, (argc + 1) * kPointerSize), edx); | 2359 __ mov(Operand(esp, (argc + 1) * kPointerSize), edx); |
2386 } | 2360 } |
2387 | 2361 |
(...skipping 127 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2515 String* name) { | 2489 String* name) { |
2516 // ----------- S t a t e ------------- | 2490 // ----------- S t a t e ------------- |
2517 // -- eax : value | 2491 // -- eax : value |
2518 // -- ecx : name | 2492 // -- ecx : name |
2519 // -- edx : receiver | 2493 // -- edx : receiver |
2520 // -- esp[0] : return address | 2494 // -- esp[0] : return address |
2521 // ----------------------------------- | 2495 // ----------------------------------- |
2522 Label miss; | 2496 Label miss; |
2523 | 2497 |
2524 // Check that the object isn't a smi. | 2498 // Check that the object isn't a smi. |
2525 __ test(edx, Immediate(kSmiTagMask)); | 2499 __ JumpIfSmi(edx, &miss); |
2526 __ j(zero, &miss); | |
2527 | 2500 |
2528 // Check that the map of the object hasn't changed. | 2501 // Check that the map of the object hasn't changed. |
2529 __ cmp(FieldOperand(edx, HeapObject::kMapOffset), | 2502 __ cmp(FieldOperand(edx, HeapObject::kMapOffset), |
2530 Immediate(Handle<Map>(object->map()))); | 2503 Immediate(Handle<Map>(object->map()))); |
2531 __ j(not_equal, &miss); | 2504 __ j(not_equal, &miss); |
2532 | 2505 |
2533 // Perform global security token check if needed. | 2506 // Perform global security token check if needed. |
2534 if (object->IsJSGlobalProxy()) { | 2507 if (object->IsJSGlobalProxy()) { |
2535 __ CheckAccessGlobalProxy(edx, ebx, &miss); | 2508 __ CheckAccessGlobalProxy(edx, ebx, &miss); |
2536 } | 2509 } |
(...skipping 28 matching lines...) Expand all Loading... |
2565 String* name) { | 2538 String* name) { |
2566 // ----------- S t a t e ------------- | 2539 // ----------- S t a t e ------------- |
2567 // -- eax : value | 2540 // -- eax : value |
2568 // -- ecx : name | 2541 // -- ecx : name |
2569 // -- edx : receiver | 2542 // -- edx : receiver |
2570 // -- esp[0] : return address | 2543 // -- esp[0] : return address |
2571 // ----------------------------------- | 2544 // ----------------------------------- |
2572 Label miss; | 2545 Label miss; |
2573 | 2546 |
2574 // Check that the object isn't a smi. | 2547 // Check that the object isn't a smi. |
2575 __ test(edx, Immediate(kSmiTagMask)); | 2548 __ JumpIfSmi(edx, &miss); |
2576 __ j(zero, &miss); | |
2577 | 2549 |
2578 // Check that the map of the object hasn't changed. | 2550 // Check that the map of the object hasn't changed. |
2579 __ cmp(FieldOperand(edx, HeapObject::kMapOffset), | 2551 __ cmp(FieldOperand(edx, HeapObject::kMapOffset), |
2580 Immediate(Handle<Map>(receiver->map()))); | 2552 Immediate(Handle<Map>(receiver->map()))); |
2581 __ j(not_equal, &miss); | 2553 __ j(not_equal, &miss); |
2582 | 2554 |
2583 // Perform global security token check if needed. | 2555 // Perform global security token check if needed. |
2584 if (receiver->IsJSGlobalProxy()) { | 2556 if (receiver->IsJSGlobalProxy()) { |
2585 __ CheckAccessGlobalProxy(edx, ebx, &miss); | 2557 __ CheckAccessGlobalProxy(edx, ebx, &miss); |
2586 } | 2558 } |
(...skipping 168 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2755 JSObject* object, | 2727 JSObject* object, |
2756 JSObject* last) { | 2728 JSObject* last) { |
2757 // ----------- S t a t e ------------- | 2729 // ----------- S t a t e ------------- |
2758 // -- eax : receiver | 2730 // -- eax : receiver |
2759 // -- ecx : name | 2731 // -- ecx : name |
2760 // -- esp[0] : return address | 2732 // -- esp[0] : return address |
2761 // ----------------------------------- | 2733 // ----------------------------------- |
2762 Label miss; | 2734 Label miss; |
2763 | 2735 |
2764 // Check that the receiver isn't a smi. | 2736 // Check that the receiver isn't a smi. |
2765 __ test(eax, Immediate(kSmiTagMask)); | 2737 __ JumpIfSmi(eax, &miss); |
2766 __ j(zero, &miss); | |
2767 | 2738 |
2768 ASSERT(last->IsGlobalObject() || last->HasFastProperties()); | 2739 ASSERT(last->IsGlobalObject() || last->HasFastProperties()); |
2769 | 2740 |
2770 // Check the maps of the full prototype chain. Also check that | 2741 // Check the maps of the full prototype chain. Also check that |
2771 // global property cells up to (but not including) the last object | 2742 // global property cells up to (but not including) the last object |
2772 // in the prototype chain are empty. | 2743 // in the prototype chain are empty. |
2773 CheckPrototypes(object, eax, last, ebx, edx, edi, name, &miss); | 2744 CheckPrototypes(object, eax, last, ebx, edx, edi, name, &miss); |
2774 | 2745 |
2775 // If the last object in the prototype chain is a global object, | 2746 // If the last object in the prototype chain is a global object, |
2776 // check that the global property cell is empty. | 2747 // check that the global property cell is empty. |
(...skipping 131 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2908 // -- eax : receiver | 2879 // -- eax : receiver |
2909 // -- ecx : name | 2880 // -- ecx : name |
2910 // -- esp[0] : return address | 2881 // -- esp[0] : return address |
2911 // ----------------------------------- | 2882 // ----------------------------------- |
2912 Label miss; | 2883 Label miss; |
2913 | 2884 |
2914 // If the object is the holder then we know that it's a global | 2885 // If the object is the holder then we know that it's a global |
2915 // object which can only happen for contextual loads. In this case, | 2886 // object which can only happen for contextual loads. In this case, |
2916 // the receiver cannot be a smi. | 2887 // the receiver cannot be a smi. |
2917 if (object != holder) { | 2888 if (object != holder) { |
2918 __ test(eax, Immediate(kSmiTagMask)); | 2889 __ JumpIfSmi(eax, &miss); |
2919 __ j(zero, &miss); | |
2920 } | 2890 } |
2921 | 2891 |
2922 // Check that the maps haven't changed. | 2892 // Check that the maps haven't changed. |
2923 CheckPrototypes(object, eax, holder, ebx, edx, edi, name, &miss); | 2893 CheckPrototypes(object, eax, holder, ebx, edx, edi, name, &miss); |
2924 | 2894 |
2925 // Get the value from the cell. | 2895 // Get the value from the cell. |
2926 if (Serializer::enabled()) { | 2896 if (Serializer::enabled()) { |
2927 __ mov(ebx, Immediate(Handle<JSGlobalPropertyCell>(cell))); | 2897 __ mov(ebx, Immediate(Handle<JSGlobalPropertyCell>(cell))); |
2928 __ mov(ebx, FieldOperand(ebx, JSGlobalPropertyCell::kValueOffset)); | 2898 __ mov(ebx, FieldOperand(ebx, JSGlobalPropertyCell::kValueOffset)); |
2929 } else { | 2899 } else { |
(...skipping 295 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
3225 // code for the function thereby hitting the break points. | 3195 // code for the function thereby hitting the break points. |
3226 __ mov(ebx, FieldOperand(edi, JSFunction::kSharedFunctionInfoOffset)); | 3196 __ mov(ebx, FieldOperand(edi, JSFunction::kSharedFunctionInfoOffset)); |
3227 __ mov(ebx, FieldOperand(ebx, SharedFunctionInfo::kDebugInfoOffset)); | 3197 __ mov(ebx, FieldOperand(ebx, SharedFunctionInfo::kDebugInfoOffset)); |
3228 __ cmp(ebx, factory()->undefined_value()); | 3198 __ cmp(ebx, factory()->undefined_value()); |
3229 __ j(not_equal, &generic_stub_call); | 3199 __ j(not_equal, &generic_stub_call); |
3230 #endif | 3200 #endif |
3231 | 3201 |
3232 // Load the initial map and verify that it is in fact a map. | 3202 // Load the initial map and verify that it is in fact a map. |
3233 __ mov(ebx, FieldOperand(edi, JSFunction::kPrototypeOrInitialMapOffset)); | 3203 __ mov(ebx, FieldOperand(edi, JSFunction::kPrototypeOrInitialMapOffset)); |
3234 // Will both indicate a NULL and a Smi. | 3204 // Will both indicate a NULL and a Smi. |
3235 __ test(ebx, Immediate(kSmiTagMask)); | 3205 __ JumpIfSmi(ebx, &generic_stub_call); |
3236 __ j(zero, &generic_stub_call); | |
3237 __ CmpObjectType(ebx, MAP_TYPE, ecx); | 3206 __ CmpObjectType(ebx, MAP_TYPE, ecx); |
3238 __ j(not_equal, &generic_stub_call); | 3207 __ j(not_equal, &generic_stub_call); |
3239 | 3208 |
3240 #ifdef DEBUG | 3209 #ifdef DEBUG |
3241 // Cannot construct functions this way. | 3210 // Cannot construct functions this way. |
3242 // edi: constructor | 3211 // edi: constructor |
3243 // ebx: initial map | 3212 // ebx: initial map |
3244 __ CmpInstanceType(ebx, JS_FUNCTION_TYPE); | 3213 __ CmpInstanceType(ebx, JS_FUNCTION_TYPE); |
3245 __ Assert(not_equal, "Function constructed by construct stub."); | 3214 __ Assert(not_equal, "Function constructed by construct stub."); |
3246 #endif | 3215 #endif |
(...skipping 112 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
3359 // -- eax : key | 3328 // -- eax : key |
3360 // -- edx : receiver | 3329 // -- edx : receiver |
3361 // -- esp[0] : return address | 3330 // -- esp[0] : return address |
3362 // ----------------------------------- | 3331 // ----------------------------------- |
3363 Label miss_force_generic, failed_allocation, slow; | 3332 Label miss_force_generic, failed_allocation, slow; |
3364 | 3333 |
3365 // This stub is meant to be tail-jumped to, the receiver must already | 3334 // This stub is meant to be tail-jumped to, the receiver must already |
3366 // have been verified by the caller to not be a smi. | 3335 // have been verified by the caller to not be a smi. |
3367 | 3336 |
3368 // Check that the key is a smi. | 3337 // Check that the key is a smi. |
3369 __ test(eax, Immediate(kSmiTagMask)); | 3338 __ JumpIfNotSmi(eax, &miss_force_generic); |
3370 __ j(not_zero, &miss_force_generic); | |
3371 | 3339 |
3372 // Check that the index is in range. | 3340 // Check that the index is in range. |
3373 __ mov(ecx, eax); | 3341 __ mov(ecx, eax); |
3374 __ SmiUntag(ecx); // Untag the index. | 3342 __ SmiUntag(ecx); // Untag the index. |
3375 __ mov(ebx, FieldOperand(edx, JSObject::kElementsOffset)); | 3343 __ mov(ebx, FieldOperand(edx, JSObject::kElementsOffset)); |
3376 __ cmp(ecx, FieldOperand(ebx, ExternalArray::kLengthOffset)); | 3344 __ cmp(ecx, FieldOperand(ebx, ExternalArray::kLengthOffset)); |
3377 // Unsigned comparison catches both negative and too-large values. | 3345 // Unsigned comparison catches both negative and too-large values. |
3378 __ j(above_equal, &miss_force_generic); | 3346 __ j(above_equal, &miss_force_generic); |
3379 __ mov(ebx, FieldOperand(ebx, ExternalArray::kExternalPointerOffset)); | 3347 __ mov(ebx, FieldOperand(ebx, ExternalArray::kExternalPointerOffset)); |
3380 // ebx: base pointer of external storage | 3348 // ebx: base pointer of external storage |
(...skipping 134 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
3515 // -- eax : key | 3483 // -- eax : key |
3516 // -- edx : receiver | 3484 // -- edx : receiver |
3517 // -- esp[0] : return address | 3485 // -- esp[0] : return address |
3518 // ----------------------------------- | 3486 // ----------------------------------- |
3519 Label miss_force_generic, slow, check_heap_number; | 3487 Label miss_force_generic, slow, check_heap_number; |
3520 | 3488 |
3521 // This stub is meant to be tail-jumped to, the receiver must already | 3489 // This stub is meant to be tail-jumped to, the receiver must already |
3522 // have been verified by the caller to not be a smi. | 3490 // have been verified by the caller to not be a smi. |
3523 | 3491 |
3524 // Check that the key is a smi. | 3492 // Check that the key is a smi. |
3525 __ test(ecx, Immediate(kSmiTagMask)); | 3493 __ JumpIfNotSmi(ecx, &miss_force_generic); |
3526 __ j(not_zero, &miss_force_generic); | |
3527 | 3494 |
3528 // Check that the index is in range. | 3495 // Check that the index is in range. |
3529 __ mov(edi, FieldOperand(edx, JSObject::kElementsOffset)); | 3496 __ mov(edi, FieldOperand(edx, JSObject::kElementsOffset)); |
3530 __ mov(ebx, ecx); | 3497 __ mov(ebx, ecx); |
3531 __ SmiUntag(ebx); | 3498 __ SmiUntag(ebx); |
3532 __ cmp(ebx, FieldOperand(edi, ExternalArray::kLengthOffset)); | 3499 __ cmp(ebx, FieldOperand(edi, ExternalArray::kLengthOffset)); |
3533 // Unsigned comparison catches both negative and too-large values. | 3500 // Unsigned comparison catches both negative and too-large values. |
3534 __ j(above_equal, &slow); | 3501 __ j(above_equal, &slow); |
3535 | 3502 |
3536 // Handle both smis and HeapNumbers in the fast path. Go to the | 3503 // Handle both smis and HeapNumbers in the fast path. Go to the |
3537 // runtime for all other kinds of values. | 3504 // runtime for all other kinds of values. |
3538 // eax: value | 3505 // eax: value |
3539 // edx: receiver | 3506 // edx: receiver |
3540 // ecx: key | 3507 // ecx: key |
3541 // edi: elements array | 3508 // edi: elements array |
3542 // ebx: untagged index | 3509 // ebx: untagged index |
3543 __ test(eax, Immediate(kSmiTagMask)); | 3510 if (elements_kind == JSObject::EXTERNAL_PIXEL_ELEMENTS) { |
3544 if (elements_kind == JSObject::EXTERNAL_PIXEL_ELEMENTS) | 3511 __ JumpIfNotSmi(eax, &slow); |
3545 __ j(not_equal, &slow); | 3512 } else { |
3546 else | 3513 __ JumpIfNotSmi(eax, &check_heap_number); |
3547 __ j(not_equal, &check_heap_number); | 3514 } |
3548 | 3515 |
3549 // smi case | 3516 // smi case |
3550 __ mov(ecx, eax); // Preserve the value in eax. Key is no longer needed. | 3517 __ mov(ecx, eax); // Preserve the value in eax. Key is no longer needed. |
3551 __ SmiUntag(ecx); | 3518 __ SmiUntag(ecx); |
3552 __ mov(edi, FieldOperand(edi, ExternalArray::kExternalPointerOffset)); | 3519 __ mov(edi, FieldOperand(edi, ExternalArray::kExternalPointerOffset)); |
3553 // ecx: base pointer of external storage | 3520 // ecx: base pointer of external storage |
3554 switch (elements_kind) { | 3521 switch (elements_kind) { |
3555 case JSObject::EXTERNAL_PIXEL_ELEMENTS: | 3522 case JSObject::EXTERNAL_PIXEL_ELEMENTS: |
3556 { // Clamp the value to [0..255]. | 3523 { // Clamp the value to [0..255]. |
3557 Label done; | 3524 Label done; |
(...skipping 171 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
3729 // -- eax : key | 3696 // -- eax : key |
3730 // -- edx : receiver | 3697 // -- edx : receiver |
3731 // -- esp[0] : return address | 3698 // -- esp[0] : return address |
3732 // ----------------------------------- | 3699 // ----------------------------------- |
3733 Label miss_force_generic; | 3700 Label miss_force_generic; |
3734 | 3701 |
3735 // This stub is meant to be tail-jumped to, the receiver must already | 3702 // This stub is meant to be tail-jumped to, the receiver must already |
3736 // have been verified by the caller to not be a smi. | 3703 // have been verified by the caller to not be a smi. |
3737 | 3704 |
3738 // Check that the key is a smi. | 3705 // Check that the key is a smi. |
3739 __ test(eax, Immediate(kSmiTagMask)); | 3706 __ JumpIfNotSmi(eax, &miss_force_generic); |
3740 __ j(not_zero, &miss_force_generic); | |
3741 | 3707 |
3742 // Get the elements array. | 3708 // Get the elements array. |
3743 __ mov(ecx, FieldOperand(edx, JSObject::kElementsOffset)); | 3709 __ mov(ecx, FieldOperand(edx, JSObject::kElementsOffset)); |
3744 __ AssertFastElements(ecx); | 3710 __ AssertFastElements(ecx); |
3745 | 3711 |
3746 // Check that the key is within bounds. | 3712 // Check that the key is within bounds. |
3747 __ cmp(eax, FieldOperand(ecx, FixedArray::kLengthOffset)); | 3713 __ cmp(eax, FieldOperand(ecx, FixedArray::kLengthOffset)); |
3748 __ j(above_equal, &miss_force_generic); | 3714 __ j(above_equal, &miss_force_generic); |
3749 | 3715 |
3750 // Load the result and make sure it's not the hole. | 3716 // Load the result and make sure it's not the hole. |
(...skipping 17 matching lines...) Expand all Loading... |
3768 // -- eax : key | 3734 // -- eax : key |
3769 // -- edx : receiver | 3735 // -- edx : receiver |
3770 // -- esp[0] : return address | 3736 // -- esp[0] : return address |
3771 // ----------------------------------- | 3737 // ----------------------------------- |
3772 Label miss_force_generic; | 3738 Label miss_force_generic; |
3773 | 3739 |
3774 // This stub is meant to be tail-jumped to, the receiver must already | 3740 // This stub is meant to be tail-jumped to, the receiver must already |
3775 // have been verified by the caller to not be a smi. | 3741 // have been verified by the caller to not be a smi. |
3776 | 3742 |
3777 // Check that the key is a smi. | 3743 // Check that the key is a smi. |
3778 __ test(ecx, Immediate(kSmiTagMask)); | 3744 __ JumpIfNotSmi(ecx, &miss_force_generic); |
3779 __ j(not_zero, &miss_force_generic); | |
3780 | 3745 |
3781 // Get the elements array and make sure it is a fast element array, not 'cow'. | 3746 // Get the elements array and make sure it is a fast element array, not 'cow'. |
3782 __ mov(edi, FieldOperand(edx, JSObject::kElementsOffset)); | 3747 __ mov(edi, FieldOperand(edx, JSObject::kElementsOffset)); |
3783 __ cmp(FieldOperand(edi, HeapObject::kMapOffset), | 3748 __ cmp(FieldOperand(edi, HeapObject::kMapOffset), |
3784 Immediate(masm->isolate()->factory()->fixed_array_map())); | 3749 Immediate(masm->isolate()->factory()->fixed_array_map())); |
3785 __ j(not_equal, &miss_force_generic); | 3750 __ j(not_equal, &miss_force_generic); |
3786 | 3751 |
3787 if (is_js_array) { | 3752 if (is_js_array) { |
3788 // Check that the key is within bounds. | 3753 // Check that the key is within bounds. |
3789 __ cmp(ecx, FieldOperand(edx, JSArray::kLengthOffset)); // smis. | 3754 __ cmp(ecx, FieldOperand(edx, JSArray::kLengthOffset)); // smis. |
(...skipping 19 matching lines...) Expand all Loading... |
3809 masm->isolate()->builtins()->KeyedStoreIC_MissForceGeneric(); | 3774 masm->isolate()->builtins()->KeyedStoreIC_MissForceGeneric(); |
3810 __ jmp(ic_force_generic, RelocInfo::CODE_TARGET); | 3775 __ jmp(ic_force_generic, RelocInfo::CODE_TARGET); |
3811 } | 3776 } |
3812 | 3777 |
3813 | 3778 |
3814 #undef __ | 3779 #undef __ |
3815 | 3780 |
3816 } } // namespace v8::internal | 3781 } } // namespace v8::internal |
3817 | 3782 |
3818 #endif // V8_TARGET_ARCH_IA32 | 3783 #endif // V8_TARGET_ARCH_IA32 |
OLD | NEW |