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