| OLD | NEW |
| 1 // Copyright 2006-2009 the V8 project authors. All rights reserved. | 1 // Copyright 2006-2009 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 257 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 268 Register prototype) { | 268 Register prototype) { |
| 269 __ LoadGlobalFunction(index, prototype); | 269 __ LoadGlobalFunction(index, prototype); |
| 270 __ LoadGlobalFunctionInitialMap(prototype, prototype); | 270 __ LoadGlobalFunctionInitialMap(prototype, prototype); |
| 271 // Load the prototype from the initial map. | 271 // Load the prototype from the initial map. |
| 272 __ mov(prototype, FieldOperand(prototype, Map::kPrototypeOffset)); | 272 __ mov(prototype, FieldOperand(prototype, Map::kPrototypeOffset)); |
| 273 } | 273 } |
| 274 | 274 |
| 275 | 275 |
| 276 void StubCompiler::GenerateDirectLoadGlobalFunctionPrototype( | 276 void StubCompiler::GenerateDirectLoadGlobalFunctionPrototype( |
| 277 MacroAssembler* masm, int index, Register prototype, Label* miss) { | 277 MacroAssembler* masm, int index, Register prototype, Label* miss) { |
| 278 Isolate* isolate = masm->isolate(); | |
| 279 // Check we're still in the same context. | 278 // Check we're still in the same context. |
| 280 __ cmp(Operand(esi, Context::SlotOffset(Context::GLOBAL_INDEX)), | 279 __ cmp(Operand(esi, Context::SlotOffset(Context::GLOBAL_INDEX)), |
| 281 isolate->global()); | 280 masm->isolate()->global()); |
| 282 __ j(not_equal, miss); | 281 __ j(not_equal, miss); |
| 283 // Get the global function with the given index. | 282 // Get the global function with the given index. |
| 284 JSFunction* function = | 283 JSFunction* function = |
| 285 JSFunction::cast(isolate->global_context()->get(index)); | 284 JSFunction::cast(masm->isolate()->global_context()->get(index)); |
| 286 // Load its initial map. The global functions all have initial maps. | 285 // Load its initial map. The global functions all have initial maps. |
| 287 __ Set(prototype, Immediate(Handle<Map>(function->initial_map()))); | 286 __ Set(prototype, Immediate(Handle<Map>(function->initial_map()))); |
| 288 // Load the prototype from the initial map. | 287 // Load the prototype from the initial map. |
| 289 __ mov(prototype, FieldOperand(prototype, Map::kPrototypeOffset)); | 288 __ mov(prototype, FieldOperand(prototype, Map::kPrototypeOffset)); |
| 290 } | 289 } |
| 291 | 290 |
| 292 | 291 |
| 293 void StubCompiler::GenerateLoadArrayLength(MacroAssembler* masm, | 292 void StubCompiler::GenerateLoadArrayLength(MacroAssembler* masm, |
| 294 Register receiver, | 293 Register receiver, |
| 295 Register scratch, | 294 Register scratch, |
| (...skipping 97 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 393 } | 392 } |
| 394 | 393 |
| 395 | 394 |
| 396 static void PushInterceptorArguments(MacroAssembler* masm, | 395 static void PushInterceptorArguments(MacroAssembler* masm, |
| 397 Register receiver, | 396 Register receiver, |
| 398 Register holder, | 397 Register holder, |
| 399 Register name, | 398 Register name, |
| 400 JSObject* holder_obj) { | 399 JSObject* holder_obj) { |
| 401 __ push(name); | 400 __ push(name); |
| 402 InterceptorInfo* interceptor = holder_obj->GetNamedInterceptor(); | 401 InterceptorInfo* interceptor = holder_obj->GetNamedInterceptor(); |
| 403 ASSERT(!HEAP->InNewSpace(interceptor)); | 402 ASSERT(!masm->isolate()->heap()->InNewSpace(interceptor)); |
| 404 Register scratch = name; | 403 Register scratch = name; |
| 405 __ mov(scratch, Immediate(Handle<Object>(interceptor))); | 404 __ mov(scratch, Immediate(Handle<Object>(interceptor))); |
| 406 __ push(scratch); | 405 __ push(scratch); |
| 407 __ push(receiver); | 406 __ push(receiver); |
| 408 __ push(holder); | 407 __ push(holder); |
| 409 __ push(FieldOperand(scratch, InterceptorInfo::kDataOffset)); | 408 __ push(FieldOperand(scratch, InterceptorInfo::kDataOffset)); |
| 410 } | 409 } |
| 411 | 410 |
| 412 | 411 |
| 413 static void CompileCallLoadPropertyWithInterceptor(MacroAssembler* masm, | 412 static void CompileCallLoadPropertyWithInterceptor(MacroAssembler* masm, |
| (...skipping 65 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 479 // ----------------------------------- | 478 // ----------------------------------- |
| 480 // Get the function and setup the context. | 479 // Get the function and setup the context. |
| 481 JSFunction* function = optimization.constant_function(); | 480 JSFunction* function = optimization.constant_function(); |
| 482 __ mov(edi, Immediate(Handle<JSFunction>(function))); | 481 __ mov(edi, Immediate(Handle<JSFunction>(function))); |
| 483 __ mov(esi, FieldOperand(edi, JSFunction::kContextOffset)); | 482 __ mov(esi, FieldOperand(edi, JSFunction::kContextOffset)); |
| 484 | 483 |
| 485 // Pass the additional arguments. | 484 // Pass the additional arguments. |
| 486 __ mov(Operand(esp, 2 * kPointerSize), edi); | 485 __ mov(Operand(esp, 2 * kPointerSize), edi); |
| 487 Object* call_data = optimization.api_call_info()->data(); | 486 Object* call_data = optimization.api_call_info()->data(); |
| 488 Handle<CallHandlerInfo> api_call_info_handle(optimization.api_call_info()); | 487 Handle<CallHandlerInfo> api_call_info_handle(optimization.api_call_info()); |
| 489 if (HEAP->InNewSpace(call_data)) { | 488 if (masm->isolate()->heap()->InNewSpace(call_data)) { |
| 490 __ mov(ecx, api_call_info_handle); | 489 __ mov(ecx, api_call_info_handle); |
| 491 __ mov(ebx, FieldOperand(ecx, CallHandlerInfo::kDataOffset)); | 490 __ mov(ebx, FieldOperand(ecx, CallHandlerInfo::kDataOffset)); |
| 492 __ mov(Operand(esp, 3 * kPointerSize), ebx); | 491 __ mov(Operand(esp, 3 * kPointerSize), ebx); |
| 493 } else { | 492 } else { |
| 494 __ mov(Operand(esp, 3 * kPointerSize), | 493 __ mov(Operand(esp, 3 * kPointerSize), |
| 495 Immediate(Handle<Object>(call_data))); | 494 Immediate(Handle<Object>(call_data))); |
| 496 } | 495 } |
| 497 | 496 |
| 498 // Prepare arguments. | 497 // Prepare arguments. |
| 499 __ lea(eax, Operand(esp, 3 * kPointerSize)); | 498 __ lea(eax, Operand(esp, 3 * kPointerSize)); |
| (...skipping 73 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 573 } else { | 572 } else { |
| 574 CompileRegular(masm, | 573 CompileRegular(masm, |
| 575 object, | 574 object, |
| 576 receiver, | 575 receiver, |
| 577 scratch1, | 576 scratch1, |
| 578 scratch2, | 577 scratch2, |
| 579 scratch3, | 578 scratch3, |
| 580 name, | 579 name, |
| 581 holder, | 580 holder, |
| 582 miss); | 581 miss); |
| 583 return HEAP->undefined_value(); // Success. | 582 return masm->isolate()->heap()->undefined_value(); // Success. |
| 584 } | 583 } |
| 585 } | 584 } |
| 586 | 585 |
| 587 private: | 586 private: |
| 588 MaybeObject* CompileCacheable(MacroAssembler* masm, | 587 MaybeObject* CompileCacheable(MacroAssembler* masm, |
| 589 JSObject* object, | 588 JSObject* object, |
| 590 Register receiver, | 589 Register receiver, |
| 591 Register scratch1, | 590 Register scratch1, |
| 592 Register scratch2, | 591 Register scratch2, |
| 593 Register scratch3, | 592 Register scratch3, |
| (...skipping 78 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 672 FreeSpaceForFastApiCall(masm, scratch1); | 671 FreeSpaceForFastApiCall(masm, scratch1); |
| 673 __ jmp(miss_label); | 672 __ jmp(miss_label); |
| 674 } | 673 } |
| 675 | 674 |
| 676 // Invoke a regular function. | 675 // Invoke a regular function. |
| 677 __ bind(®ular_invoke); | 676 __ bind(®ular_invoke); |
| 678 if (can_do_fast_api_call) { | 677 if (can_do_fast_api_call) { |
| 679 FreeSpaceForFastApiCall(masm, scratch1); | 678 FreeSpaceForFastApiCall(masm, scratch1); |
| 680 } | 679 } |
| 681 | 680 |
| 682 return HEAP->undefined_value(); // Success. | 681 return masm->isolate()->heap()->undefined_value(); // Success. |
| 683 } | 682 } |
| 684 | 683 |
| 685 void CompileRegular(MacroAssembler* masm, | 684 void CompileRegular(MacroAssembler* masm, |
| 686 JSObject* object, | 685 JSObject* object, |
| 687 Register receiver, | 686 Register receiver, |
| 688 Register scratch1, | 687 Register scratch1, |
| 689 Register scratch2, | 688 Register scratch2, |
| 690 Register scratch3, | 689 Register scratch3, |
| 691 String* name, | 690 String* name, |
| 692 JSObject* interceptor_holder, | 691 JSObject* interceptor_holder, |
| (...skipping 216 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 909 Register holder_reg, | 908 Register holder_reg, |
| 910 Register scratch1, | 909 Register scratch1, |
| 911 Register scratch2, | 910 Register scratch2, |
| 912 String* name, | 911 String* name, |
| 913 int save_at_depth, | 912 int save_at_depth, |
| 914 Label* miss) { | 913 Label* miss) { |
| 915 // Make sure there's no overlap between holder and object registers. | 914 // Make sure there's no overlap between holder and object registers. |
| 916 ASSERT(!scratch1.is(object_reg) && !scratch1.is(holder_reg)); | 915 ASSERT(!scratch1.is(object_reg) && !scratch1.is(holder_reg)); |
| 917 ASSERT(!scratch2.is(object_reg) && !scratch2.is(holder_reg) | 916 ASSERT(!scratch2.is(object_reg) && !scratch2.is(holder_reg) |
| 918 && !scratch2.is(scratch1)); | 917 && !scratch2.is(scratch1)); |
| 918 |
| 919 Heap* heap = isolate()->heap(); |
| 920 |
| 919 // Keep track of the current object in register reg. | 921 // Keep track of the current object in register reg. |
| 920 Register reg = object_reg; | 922 Register reg = object_reg; |
| 921 JSObject* current = object; | 923 JSObject* current = object; |
| 922 int depth = 0; | 924 int depth = 0; |
| 923 | 925 |
| 924 if (save_at_depth == depth) { | 926 if (save_at_depth == depth) { |
| 925 __ mov(Operand(esp, kPointerSize), reg); | 927 __ mov(Operand(esp, kPointerSize), reg); |
| 926 } | 928 } |
| 927 | 929 |
| 928 // Traverse the prototype chain and check the maps in the prototype chain for | 930 // Traverse the prototype chain and check the maps in the prototype chain for |
| 929 // fast and global objects or do negative lookup for normal objects. | 931 // fast and global objects or do negative lookup for normal objects. |
| 930 while (current != holder) { | 932 while (current != holder) { |
| 931 depth++; | 933 depth++; |
| 932 | 934 |
| 933 // Only global objects and objects that do not require access | 935 // Only global objects and objects that do not require access |
| 934 // checks are allowed in stubs. | 936 // checks are allowed in stubs. |
| 935 ASSERT(current->IsJSGlobalProxy() || !current->IsAccessCheckNeeded()); | 937 ASSERT(current->IsJSGlobalProxy() || !current->IsAccessCheckNeeded()); |
| 936 | 938 |
| 937 ASSERT(current->GetPrototype()->IsJSObject()); | 939 ASSERT(current->GetPrototype()->IsJSObject()); |
| 938 JSObject* prototype = JSObject::cast(current->GetPrototype()); | 940 JSObject* prototype = JSObject::cast(current->GetPrototype()); |
| 939 if (!current->HasFastProperties() && | 941 if (!current->HasFastProperties() && |
| 940 !current->IsJSGlobalObject() && | 942 !current->IsJSGlobalObject() && |
| 941 !current->IsJSGlobalProxy()) { | 943 !current->IsJSGlobalProxy()) { |
| 942 if (!name->IsSymbol()) { | 944 if (!name->IsSymbol()) { |
| 943 MaybeObject* maybe_lookup_result = HEAP->LookupSymbol(name); | 945 MaybeObject* maybe_lookup_result = heap->LookupSymbol(name); |
| 944 Object* lookup_result = NULL; // Initialization to please compiler. | 946 Object* lookup_result = NULL; // Initialization to please compiler. |
| 945 if (!maybe_lookup_result->ToObject(&lookup_result)) { | 947 if (!maybe_lookup_result->ToObject(&lookup_result)) { |
| 946 set_failure(Failure::cast(maybe_lookup_result)); | 948 set_failure(Failure::cast(maybe_lookup_result)); |
| 947 return reg; | 949 return reg; |
| 948 } | 950 } |
| 949 name = String::cast(lookup_result); | 951 name = String::cast(lookup_result); |
| 950 } | 952 } |
| 951 ASSERT(current->property_dictionary()->FindEntry(name) == | 953 ASSERT(current->property_dictionary()->FindEntry(name) == |
| 952 StringDictionary::kNotFound); | 954 StringDictionary::kNotFound); |
| 953 | 955 |
| 954 GenerateDictionaryNegativeLookup(masm(), | 956 GenerateDictionaryNegativeLookup(masm(), |
| 955 miss, | 957 miss, |
| 956 reg, | 958 reg, |
| 957 name, | 959 name, |
| 958 scratch1, | 960 scratch1, |
| 959 scratch2); | 961 scratch2); |
| 960 __ mov(scratch1, FieldOperand(reg, HeapObject::kMapOffset)); | 962 __ mov(scratch1, FieldOperand(reg, HeapObject::kMapOffset)); |
| 961 reg = holder_reg; // from now the object is in holder_reg | 963 reg = holder_reg; // from now the object is in holder_reg |
| 962 __ mov(reg, FieldOperand(scratch1, Map::kPrototypeOffset)); | 964 __ mov(reg, FieldOperand(scratch1, Map::kPrototypeOffset)); |
| 963 } else if (HEAP->InNewSpace(prototype)) { | 965 } else if (heap->InNewSpace(prototype)) { |
| 964 // Get the map of the current object. | 966 // Get the map of the current object. |
| 965 __ mov(scratch1, FieldOperand(reg, HeapObject::kMapOffset)); | 967 __ mov(scratch1, FieldOperand(reg, HeapObject::kMapOffset)); |
| 966 __ cmp(Operand(scratch1), Immediate(Handle<Map>(current->map()))); | 968 __ cmp(Operand(scratch1), Immediate(Handle<Map>(current->map()))); |
| 967 // Branch on the result of the map check. | 969 // Branch on the result of the map check. |
| 968 __ j(not_equal, miss, not_taken); | 970 __ j(not_equal, miss, not_taken); |
| 969 // Check access rights to the global object. This has to happen | 971 // Check access rights to the global object. This has to happen |
| 970 // after the map check so that we know that the object is | 972 // after the map check so that we know that the object is |
| 971 // actually a global object. | 973 // actually a global object. |
| 972 if (current->IsJSGlobalProxy()) { | 974 if (current->IsJSGlobalProxy()) { |
| 973 __ CheckAccessGlobalProxy(reg, scratch1, miss); | 975 __ CheckAccessGlobalProxy(reg, scratch1, miss); |
| (...skipping 109 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1083 | 1085 |
| 1084 // Insert additional parameters into the stack frame above return address. | 1086 // Insert additional parameters into the stack frame above return address. |
| 1085 ASSERT(!scratch3.is(reg)); | 1087 ASSERT(!scratch3.is(reg)); |
| 1086 __ pop(scratch3); // Get return address to place it below. | 1088 __ pop(scratch3); // Get return address to place it below. |
| 1087 | 1089 |
| 1088 __ push(receiver); // receiver | 1090 __ push(receiver); // receiver |
| 1089 __ mov(scratch2, Operand(esp)); | 1091 __ mov(scratch2, Operand(esp)); |
| 1090 ASSERT(!scratch2.is(reg)); | 1092 ASSERT(!scratch2.is(reg)); |
| 1091 __ push(reg); // holder | 1093 __ push(reg); // holder |
| 1092 // Push data from AccessorInfo. | 1094 // Push data from AccessorInfo. |
| 1093 if (HEAP->InNewSpace(callback_handle->data())) { | 1095 if (isolate()->heap()->InNewSpace(callback_handle->data())) { |
| 1094 __ mov(scratch1, Immediate(callback_handle)); | 1096 __ mov(scratch1, Immediate(callback_handle)); |
| 1095 __ push(FieldOperand(scratch1, AccessorInfo::kDataOffset)); | 1097 __ push(FieldOperand(scratch1, AccessorInfo::kDataOffset)); |
| 1096 } else { | 1098 } else { |
| 1097 __ push(Immediate(Handle<Object>(callback_handle->data()))); | 1099 __ push(Immediate(Handle<Object>(callback_handle->data()))); |
| 1098 } | 1100 } |
| 1099 | 1101 |
| 1100 // Save a pointer to where we pushed the arguments pointer. | 1102 // Save a pointer to where we pushed the arguments pointer. |
| 1101 // This will be passed as the const AccessorInfo& to the C++ callback. | 1103 // This will be passed as the const AccessorInfo& to the C++ callback. |
| 1102 __ push(scratch2); | 1104 __ push(scratch2); |
| 1103 | 1105 |
| (...skipping 175 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1279 Register holder_reg = | 1281 Register holder_reg = |
| 1280 CheckPrototypes(object, receiver, interceptor_holder, | 1282 CheckPrototypes(object, receiver, interceptor_holder, |
| 1281 scratch1, scratch2, scratch3, name, miss); | 1283 scratch1, scratch2, scratch3, name, miss); |
| 1282 __ pop(scratch2); // save old return address | 1284 __ pop(scratch2); // save old return address |
| 1283 PushInterceptorArguments(masm(), receiver, holder_reg, | 1285 PushInterceptorArguments(masm(), receiver, holder_reg, |
| 1284 name_reg, interceptor_holder); | 1286 name_reg, interceptor_holder); |
| 1285 __ push(scratch2); // restore old return address | 1287 __ push(scratch2); // restore old return address |
| 1286 | 1288 |
| 1287 ExternalReference ref = | 1289 ExternalReference ref = |
| 1288 ExternalReference(IC_Utility(IC::kLoadPropertyWithInterceptorForLoad), | 1290 ExternalReference(IC_Utility(IC::kLoadPropertyWithInterceptorForLoad), |
| 1289 masm()->isolate()); | 1291 isolate()); |
| 1290 __ TailCallExternalReference(ref, 5, 1); | 1292 __ TailCallExternalReference(ref, 5, 1); |
| 1291 } | 1293 } |
| 1292 } | 1294 } |
| 1293 | 1295 |
| 1294 | 1296 |
| 1295 void CallStubCompiler::GenerateNameCheck(String* name, Label* miss) { | 1297 void CallStubCompiler::GenerateNameCheck(String* name, Label* miss) { |
| 1296 if (kind_ == Code::KEYED_CALL_IC) { | 1298 if (kind_ == Code::KEYED_CALL_IC) { |
| 1297 __ cmp(Operand(ecx), Immediate(Handle<String>(name))); | 1299 __ cmp(Operand(ecx), Immediate(Handle<String>(name))); |
| 1298 __ j(not_equal, miss, not_taken); | 1300 __ j(not_equal, miss, not_taken); |
| 1299 } | 1301 } |
| (...skipping 30 matching lines...) Expand all Loading... |
| 1330 Label* miss) { | 1332 Label* miss) { |
| 1331 // Get the value from the cell. | 1333 // Get the value from the cell. |
| 1332 if (Serializer::enabled()) { | 1334 if (Serializer::enabled()) { |
| 1333 __ mov(edi, Immediate(Handle<JSGlobalPropertyCell>(cell))); | 1335 __ mov(edi, Immediate(Handle<JSGlobalPropertyCell>(cell))); |
| 1334 __ mov(edi, FieldOperand(edi, JSGlobalPropertyCell::kValueOffset)); | 1336 __ mov(edi, FieldOperand(edi, JSGlobalPropertyCell::kValueOffset)); |
| 1335 } else { | 1337 } else { |
| 1336 __ mov(edi, Operand::Cell(Handle<JSGlobalPropertyCell>(cell))); | 1338 __ mov(edi, Operand::Cell(Handle<JSGlobalPropertyCell>(cell))); |
| 1337 } | 1339 } |
| 1338 | 1340 |
| 1339 // Check that the cell contains the same function. | 1341 // Check that the cell contains the same function. |
| 1340 if (HEAP->InNewSpace(function)) { | 1342 if (isolate()->heap()->InNewSpace(function)) { |
| 1341 // We can't embed a pointer to a function in new space so we have | 1343 // We can't embed a pointer to a function in new space so we have |
| 1342 // to verify that the shared function info is unchanged. This has | 1344 // to verify that the shared function info is unchanged. This has |
| 1343 // the nice side effect that multiple closures based on the same | 1345 // the nice side effect that multiple closures based on the same |
| 1344 // function can all use this call IC. Before we load through the | 1346 // function can all use this call IC. Before we load through the |
| 1345 // function, we have to verify that it still is a function. | 1347 // function, we have to verify that it still is a function. |
| 1346 __ test(edi, Immediate(kSmiTagMask)); | 1348 __ test(edi, Immediate(kSmiTagMask)); |
| 1347 __ j(zero, miss, not_taken); | 1349 __ j(zero, miss, not_taken); |
| 1348 __ CmpObjectType(edi, JS_FUNCTION_TYPE, ebx); | 1350 __ CmpObjectType(edi, JS_FUNCTION_TYPE, ebx); |
| 1349 __ j(not_equal, miss, not_taken); | 1351 __ j(not_equal, miss, not_taken); |
| 1350 | 1352 |
| 1351 // Check the shared function info. Make sure it hasn't changed. | 1353 // Check the shared function info. Make sure it hasn't changed. |
| 1352 __ cmp(FieldOperand(edi, JSFunction::kSharedFunctionInfoOffset), | 1354 __ cmp(FieldOperand(edi, JSFunction::kSharedFunctionInfoOffset), |
| 1353 Immediate(Handle<SharedFunctionInfo>(function->shared()))); | 1355 Immediate(Handle<SharedFunctionInfo>(function->shared()))); |
| 1354 __ j(not_equal, miss, not_taken); | 1356 __ j(not_equal, miss, not_taken); |
| 1355 } else { | 1357 } else { |
| 1356 __ cmp(Operand(edi), Immediate(Handle<JSFunction>(function))); | 1358 __ cmp(Operand(edi), Immediate(Handle<JSFunction>(function))); |
| 1357 __ j(not_equal, miss, not_taken); | 1359 __ j(not_equal, miss, not_taken); |
| 1358 } | 1360 } |
| 1359 } | 1361 } |
| 1360 | 1362 |
| 1361 | 1363 |
| 1362 MaybeObject* CallStubCompiler::GenerateMissBranch() { | 1364 MaybeObject* CallStubCompiler::GenerateMissBranch() { |
| 1363 MaybeObject* maybe_obj = | 1365 MaybeObject* maybe_obj = |
| 1364 masm()->isolate()->stub_cache()->ComputeCallMiss(arguments().immediate(), | 1366 isolate()->stub_cache()->ComputeCallMiss(arguments().immediate(), |
| 1365 kind_); | 1367 kind_); |
| 1366 Object* obj; | 1368 Object* obj; |
| 1367 if (!maybe_obj->ToObject(&obj)) return maybe_obj; | 1369 if (!maybe_obj->ToObject(&obj)) return maybe_obj; |
| 1368 __ jmp(Handle<Code>(Code::cast(obj)), RelocInfo::CODE_TARGET); | 1370 __ jmp(Handle<Code>(Code::cast(obj)), RelocInfo::CODE_TARGET); |
| 1369 return obj; | 1371 return obj; |
| 1370 } | 1372 } |
| 1371 | 1373 |
| 1372 | 1374 |
| 1373 MUST_USE_RESULT MaybeObject* CallStubCompiler::CompileCallField( | 1375 MUST_USE_RESULT MaybeObject* CallStubCompiler::CompileCallField( |
| 1374 JSObject* object, | 1376 JSObject* object, |
| (...skipping 58 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1433 String* name) { | 1435 String* name) { |
| 1434 // ----------- S t a t e ------------- | 1436 // ----------- S t a t e ------------- |
| 1435 // -- ecx : name | 1437 // -- ecx : name |
| 1436 // -- esp[0] : return address | 1438 // -- esp[0] : return address |
| 1437 // -- esp[(argc - n) * 4] : arg[n] (zero-based) | 1439 // -- esp[(argc - n) * 4] : arg[n] (zero-based) |
| 1438 // -- ... | 1440 // -- ... |
| 1439 // -- esp[(argc + 1) * 4] : receiver | 1441 // -- esp[(argc + 1) * 4] : receiver |
| 1440 // ----------------------------------- | 1442 // ----------------------------------- |
| 1441 | 1443 |
| 1442 // If object is not an array, bail out to regular call. | 1444 // If object is not an array, bail out to regular call. |
| 1443 if (!object->IsJSArray() || cell != NULL) return HEAP->undefined_value(); | 1445 if (!object->IsJSArray() || cell != NULL) { |
| 1446 return isolate()->heap()->undefined_value(); |
| 1447 } |
| 1444 | 1448 |
| 1445 Label miss; | 1449 Label miss; |
| 1446 | 1450 |
| 1447 GenerateNameCheck(name, &miss); | 1451 GenerateNameCheck(name, &miss); |
| 1448 | 1452 |
| 1449 // Get the receiver from the stack. | 1453 // Get the receiver from the stack. |
| 1450 const int argc = arguments().immediate(); | 1454 const int argc = arguments().immediate(); |
| 1451 __ mov(edx, Operand(esp, (argc + 1) * kPointerSize)); | 1455 __ mov(edx, Operand(esp, (argc + 1) * kPointerSize)); |
| 1452 | 1456 |
| 1453 // Check that the receiver isn't a smi. | 1457 // Check that the receiver isn't a smi. |
| (...skipping 57 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1511 __ InNewSpace(ebx, ecx, equal, &exit); | 1515 __ InNewSpace(ebx, ecx, equal, &exit); |
| 1512 | 1516 |
| 1513 __ RecordWriteHelper(ebx, edx, ecx); | 1517 __ RecordWriteHelper(ebx, edx, ecx); |
| 1514 __ ret((argc + 1) * kPointerSize); | 1518 __ ret((argc + 1) * kPointerSize); |
| 1515 | 1519 |
| 1516 __ bind(&attempt_to_grow_elements); | 1520 __ bind(&attempt_to_grow_elements); |
| 1517 if (!FLAG_inline_new) { | 1521 if (!FLAG_inline_new) { |
| 1518 __ jmp(&call_builtin); | 1522 __ jmp(&call_builtin); |
| 1519 } | 1523 } |
| 1520 | 1524 |
| 1521 Isolate* isolate = masm()->isolate(); | |
| 1522 ExternalReference new_space_allocation_top = | 1525 ExternalReference new_space_allocation_top = |
| 1523 ExternalReference::new_space_allocation_top_address(isolate); | 1526 ExternalReference::new_space_allocation_top_address(isolate()); |
| 1524 ExternalReference new_space_allocation_limit = | 1527 ExternalReference new_space_allocation_limit = |
| 1525 ExternalReference::new_space_allocation_limit_address(isolate); | 1528 ExternalReference::new_space_allocation_limit_address(isolate()); |
| 1526 | 1529 |
| 1527 const int kAllocationDelta = 4; | 1530 const int kAllocationDelta = 4; |
| 1528 // Load top. | 1531 // Load top. |
| 1529 __ mov(ecx, Operand::StaticVariable(new_space_allocation_top)); | 1532 __ mov(ecx, Operand::StaticVariable(new_space_allocation_top)); |
| 1530 | 1533 |
| 1531 // Check if it's the end of elements. | 1534 // Check if it's the end of elements. |
| 1532 __ lea(edx, FieldOperand(ebx, | 1535 __ lea(edx, FieldOperand(ebx, |
| 1533 eax, times_half_pointer_size, | 1536 eax, times_half_pointer_size, |
| 1534 FixedArray::kHeaderSize - argc * kPointerSize)); | 1537 FixedArray::kHeaderSize - argc * kPointerSize)); |
| 1535 __ cmp(edx, Operand(ecx)); | 1538 __ cmp(edx, Operand(ecx)); |
| (...skipping 21 matching lines...) Expand all Loading... |
| 1557 __ add(FieldOperand(ebx, FixedArray::kLengthOffset), | 1560 __ add(FieldOperand(ebx, FixedArray::kLengthOffset), |
| 1558 Immediate(Smi::FromInt(kAllocationDelta))); | 1561 Immediate(Smi::FromInt(kAllocationDelta))); |
| 1559 __ mov(FieldOperand(edx, JSArray::kLengthOffset), eax); | 1562 __ mov(FieldOperand(edx, JSArray::kLengthOffset), eax); |
| 1560 | 1563 |
| 1561 // Elements are in new space, so write barrier is not required. | 1564 // Elements are in new space, so write barrier is not required. |
| 1562 __ ret((argc + 1) * kPointerSize); | 1565 __ ret((argc + 1) * kPointerSize); |
| 1563 } | 1566 } |
| 1564 | 1567 |
| 1565 __ bind(&call_builtin); | 1568 __ bind(&call_builtin); |
| 1566 __ TailCallExternalReference( | 1569 __ TailCallExternalReference( |
| 1567 ExternalReference(Builtins::c_ArrayPush, masm()->isolate()), | 1570 ExternalReference(Builtins::c_ArrayPush, isolate()), |
| 1568 argc + 1, | 1571 argc + 1, |
| 1569 1); | 1572 1); |
| 1570 } | 1573 } |
| 1571 | 1574 |
| 1572 __ bind(&miss); | 1575 __ bind(&miss); |
| 1573 MaybeObject* maybe_result = GenerateMissBranch(); | 1576 MaybeObject* maybe_result = GenerateMissBranch(); |
| 1574 if (maybe_result->IsFailure()) return maybe_result; | 1577 if (maybe_result->IsFailure()) return maybe_result; |
| 1575 | 1578 |
| 1576 // Return the generated code. | 1579 // Return the generated code. |
| 1577 return GetCode(function); | 1580 return GetCode(function); |
| 1578 } | 1581 } |
| 1579 | 1582 |
| 1580 | 1583 |
| 1581 MaybeObject* CallStubCompiler::CompileArrayPopCall(Object* object, | 1584 MaybeObject* CallStubCompiler::CompileArrayPopCall(Object* object, |
| 1582 JSObject* holder, | 1585 JSObject* holder, |
| 1583 JSGlobalPropertyCell* cell, | 1586 JSGlobalPropertyCell* cell, |
| 1584 JSFunction* function, | 1587 JSFunction* function, |
| 1585 String* name) { | 1588 String* name) { |
| 1586 // ----------- S t a t e ------------- | 1589 // ----------- S t a t e ------------- |
| 1587 // -- ecx : name | 1590 // -- ecx : name |
| 1588 // -- esp[0] : return address | 1591 // -- esp[0] : return address |
| 1589 // -- esp[(argc - n) * 4] : arg[n] (zero-based) | 1592 // -- esp[(argc - n) * 4] : arg[n] (zero-based) |
| 1590 // -- ... | 1593 // -- ... |
| 1591 // -- esp[(argc + 1) * 4] : receiver | 1594 // -- esp[(argc + 1) * 4] : receiver |
| 1592 // ----------------------------------- | 1595 // ----------------------------------- |
| 1593 | 1596 |
| 1594 // If object is not an array, bail out to regular call. | 1597 // If object is not an array, bail out to regular call. |
| 1595 if (!object->IsJSArray() || cell != NULL) return HEAP->undefined_value(); | 1598 if (!object->IsJSArray() || cell != NULL) { |
| 1599 return isolate()->heap()->undefined_value(); |
| 1600 } |
| 1596 | 1601 |
| 1597 Label miss, return_undefined, call_builtin; | 1602 Label miss, return_undefined, call_builtin; |
| 1598 | 1603 |
| 1599 GenerateNameCheck(name, &miss); | 1604 GenerateNameCheck(name, &miss); |
| 1600 | 1605 |
| 1601 // Get the receiver from the stack. | 1606 // Get the receiver from the stack. |
| 1602 const int argc = arguments().immediate(); | 1607 const int argc = arguments().immediate(); |
| 1603 __ mov(edx, Operand(esp, (argc + 1) * kPointerSize)); | 1608 __ mov(edx, Operand(esp, (argc + 1) * kPointerSize)); |
| 1604 | 1609 |
| 1605 // Check that the receiver isn't a smi. | 1610 // Check that the receiver isn't a smi. |
| (...skipping 34 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1640 FixedArray::kHeaderSize), | 1645 FixedArray::kHeaderSize), |
| 1641 Immediate(FACTORY->the_hole_value())); | 1646 Immediate(FACTORY->the_hole_value())); |
| 1642 __ ret((argc + 1) * kPointerSize); | 1647 __ ret((argc + 1) * kPointerSize); |
| 1643 | 1648 |
| 1644 __ bind(&return_undefined); | 1649 __ bind(&return_undefined); |
| 1645 __ mov(eax, Immediate(FACTORY->undefined_value())); | 1650 __ mov(eax, Immediate(FACTORY->undefined_value())); |
| 1646 __ ret((argc + 1) * kPointerSize); | 1651 __ ret((argc + 1) * kPointerSize); |
| 1647 | 1652 |
| 1648 __ bind(&call_builtin); | 1653 __ bind(&call_builtin); |
| 1649 __ TailCallExternalReference( | 1654 __ TailCallExternalReference( |
| 1650 ExternalReference(Builtins::c_ArrayPop, masm()->isolate()), | 1655 ExternalReference(Builtins::c_ArrayPop, isolate()), |
| 1651 argc + 1, | 1656 argc + 1, |
| 1652 1); | 1657 1); |
| 1653 | 1658 |
| 1654 __ bind(&miss); | 1659 __ bind(&miss); |
| 1655 MaybeObject* maybe_result = GenerateMissBranch(); | 1660 MaybeObject* maybe_result = GenerateMissBranch(); |
| 1656 if (maybe_result->IsFailure()) return maybe_result; | 1661 if (maybe_result->IsFailure()) return maybe_result; |
| 1657 | 1662 |
| 1658 // Return the generated code. | 1663 // Return the generated code. |
| 1659 return GetCode(function); | 1664 return GetCode(function); |
| 1660 } | 1665 } |
| 1661 | 1666 |
| 1662 | 1667 |
| 1663 MaybeObject* CallStubCompiler::CompileStringCharCodeAtCall( | 1668 MaybeObject* CallStubCompiler::CompileStringCharCodeAtCall( |
| 1664 Object* object, | 1669 Object* object, |
| 1665 JSObject* holder, | 1670 JSObject* holder, |
| 1666 JSGlobalPropertyCell* cell, | 1671 JSGlobalPropertyCell* cell, |
| 1667 JSFunction* function, | 1672 JSFunction* function, |
| 1668 String* name) { | 1673 String* name) { |
| 1669 // ----------- S t a t e ------------- | 1674 // ----------- S t a t e ------------- |
| 1670 // -- ecx : function name | 1675 // -- ecx : function name |
| 1671 // -- esp[0] : return address | 1676 // -- esp[0] : return address |
| 1672 // -- esp[(argc - n) * 4] : arg[n] (zero-based) | 1677 // -- esp[(argc - n) * 4] : arg[n] (zero-based) |
| 1673 // -- ... | 1678 // -- ... |
| 1674 // -- esp[(argc + 1) * 4] : receiver | 1679 // -- esp[(argc + 1) * 4] : receiver |
| 1675 // ----------------------------------- | 1680 // ----------------------------------- |
| 1676 | 1681 |
| 1677 // If object is not a string, bail out to regular call. | 1682 // If object is not a string, bail out to regular call. |
| 1678 if (!object->IsString() || cell != NULL) { | 1683 if (!object->IsString() || cell != NULL) { |
| 1679 return masm()->isolate()->heap()->undefined_value(); | 1684 return isolate()->heap()->undefined_value(); |
| 1680 } | 1685 } |
| 1681 | 1686 |
| 1682 const int argc = arguments().immediate(); | 1687 const int argc = arguments().immediate(); |
| 1683 | 1688 |
| 1684 Label miss; | 1689 Label miss; |
| 1685 Label name_miss; | 1690 Label name_miss; |
| 1686 Label index_out_of_range; | 1691 Label index_out_of_range; |
| 1687 Label* index_out_of_range_label = &index_out_of_range; | 1692 Label* index_out_of_range_label = &index_out_of_range; |
| 1688 | 1693 |
| 1689 if (kind_ == Code::CALL_IC && extra_ic_state_ == DEFAULT_STRING_STUB) { | 1694 if (kind_ == Code::CALL_IC && extra_ic_state_ == DEFAULT_STRING_STUB) { |
| (...skipping 62 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1752 String* name) { | 1757 String* name) { |
| 1753 // ----------- S t a t e ------------- | 1758 // ----------- S t a t e ------------- |
| 1754 // -- ecx : function name | 1759 // -- ecx : function name |
| 1755 // -- esp[0] : return address | 1760 // -- esp[0] : return address |
| 1756 // -- esp[(argc - n) * 4] : arg[n] (zero-based) | 1761 // -- esp[(argc - n) * 4] : arg[n] (zero-based) |
| 1757 // -- ... | 1762 // -- ... |
| 1758 // -- esp[(argc + 1) * 4] : receiver | 1763 // -- esp[(argc + 1) * 4] : receiver |
| 1759 // ----------------------------------- | 1764 // ----------------------------------- |
| 1760 | 1765 |
| 1761 // If object is not a string, bail out to regular call. | 1766 // If object is not a string, bail out to regular call. |
| 1762 if (!object->IsString() || cell != NULL) return HEAP->undefined_value(); | 1767 if (!object->IsString() || cell != NULL) { |
| 1768 return isolate()->heap()->undefined_value(); |
| 1769 } |
| 1763 | 1770 |
| 1764 const int argc = arguments().immediate(); | 1771 const int argc = arguments().immediate(); |
| 1765 | 1772 |
| 1766 Label miss; | 1773 Label miss; |
| 1767 Label name_miss; | 1774 Label name_miss; |
| 1768 Label index_out_of_range; | 1775 Label index_out_of_range; |
| 1769 Label* index_out_of_range_label = &index_out_of_range; | 1776 Label* index_out_of_range_label = &index_out_of_range; |
| 1770 | 1777 |
| 1771 if (kind_ == Code::CALL_IC && extra_ic_state_ == DEFAULT_STRING_STUB) { | 1778 if (kind_ == Code::CALL_IC && extra_ic_state_ == DEFAULT_STRING_STUB) { |
| 1772 index_out_of_range_label = &miss; | 1779 index_out_of_range_label = &miss; |
| (...skipping 66 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1839 // -- esp[0] : return address | 1846 // -- esp[0] : return address |
| 1840 // -- esp[(argc - n) * 4] : arg[n] (zero-based) | 1847 // -- esp[(argc - n) * 4] : arg[n] (zero-based) |
| 1841 // -- ... | 1848 // -- ... |
| 1842 // -- esp[(argc + 1) * 4] : receiver | 1849 // -- esp[(argc + 1) * 4] : receiver |
| 1843 // ----------------------------------- | 1850 // ----------------------------------- |
| 1844 | 1851 |
| 1845 const int argc = arguments().immediate(); | 1852 const int argc = arguments().immediate(); |
| 1846 | 1853 |
| 1847 // If the object is not a JSObject or we got an unexpected number of | 1854 // If the object is not a JSObject or we got an unexpected number of |
| 1848 // arguments, bail out to the regular call. | 1855 // arguments, bail out to the regular call. |
| 1849 if (!object->IsJSObject() || argc != 1) return HEAP->undefined_value(); | 1856 if (!object->IsJSObject() || argc != 1) { |
| 1857 return isolate()->heap()->undefined_value(); |
| 1858 } |
| 1850 | 1859 |
| 1851 Label miss; | 1860 Label miss; |
| 1852 GenerateNameCheck(name, &miss); | 1861 GenerateNameCheck(name, &miss); |
| 1853 | 1862 |
| 1854 if (cell == NULL) { | 1863 if (cell == NULL) { |
| 1855 __ mov(edx, Operand(esp, 2 * kPointerSize)); | 1864 __ mov(edx, Operand(esp, 2 * kPointerSize)); |
| 1856 | 1865 |
| 1857 STATIC_ASSERT(kSmiTag == 0); | 1866 STATIC_ASSERT(kSmiTag == 0); |
| 1858 __ test(edx, Immediate(kSmiTagMask)); | 1867 __ test(edx, Immediate(kSmiTagMask)); |
| 1859 __ j(zero, &miss); | 1868 __ j(zero, &miss); |
| (...skipping 47 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1907 JSFunction* function, | 1916 JSFunction* function, |
| 1908 String* name) { | 1917 String* name) { |
| 1909 // ----------- S t a t e ------------- | 1918 // ----------- S t a t e ------------- |
| 1910 // -- ecx : name | 1919 // -- ecx : name |
| 1911 // -- esp[0] : return address | 1920 // -- esp[0] : return address |
| 1912 // -- esp[(argc - n) * 4] : arg[n] (zero-based) | 1921 // -- esp[(argc - n) * 4] : arg[n] (zero-based) |
| 1913 // -- ... | 1922 // -- ... |
| 1914 // -- esp[(argc + 1) * 4] : receiver | 1923 // -- esp[(argc + 1) * 4] : receiver |
| 1915 // ----------------------------------- | 1924 // ----------------------------------- |
| 1916 | 1925 |
| 1917 if (masm()->isolate()->cpu_features()->IsSupported(SSE2)) | 1926 if (isolate()->cpu_features()->IsSupported(SSE2)) { |
| 1918 return HEAP->undefined_value(); | 1927 return isolate()->heap()->undefined_value(); |
| 1928 } |
| 1929 |
| 1919 CpuFeatures::Scope use_sse2(SSE2); | 1930 CpuFeatures::Scope use_sse2(SSE2); |
| 1920 | 1931 |
| 1921 const int argc = arguments().immediate(); | 1932 const int argc = arguments().immediate(); |
| 1922 | 1933 |
| 1923 // If the object is not a JSObject or we got an unexpected number of | 1934 // If the object is not a JSObject or we got an unexpected number of |
| 1924 // arguments, bail out to the regular call. | 1935 // arguments, bail out to the regular call. |
| 1925 if (!object->IsJSObject() || argc != 1) return HEAP->undefined_value(); | 1936 if (!object->IsJSObject() || argc != 1) { |
| 1937 return isolate()->heap()->undefined_value(); |
| 1938 } |
| 1926 | 1939 |
| 1927 Label miss; | 1940 Label miss; |
| 1928 GenerateNameCheck(name, &miss); | 1941 GenerateNameCheck(name, &miss); |
| 1929 | 1942 |
| 1930 if (cell == NULL) { | 1943 if (cell == NULL) { |
| 1931 __ mov(edx, Operand(esp, 2 * kPointerSize)); | 1944 __ mov(edx, Operand(esp, 2 * kPointerSize)); |
| 1932 | 1945 |
| 1933 STATIC_ASSERT(kSmiTag == 0); | 1946 STATIC_ASSERT(kSmiTag == 0); |
| 1934 __ test(edx, Immediate(kSmiTagMask)); | 1947 __ test(edx, Immediate(kSmiTagMask)); |
| 1935 __ j(zero, &miss); | 1948 __ j(zero, &miss); |
| (...skipping 101 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2037 // -- esp[0] : return address | 2050 // -- esp[0] : return address |
| 2038 // -- esp[(argc - n) * 4] : arg[n] (zero-based) | 2051 // -- esp[(argc - n) * 4] : arg[n] (zero-based) |
| 2039 // -- ... | 2052 // -- ... |
| 2040 // -- esp[(argc + 1) * 4] : receiver | 2053 // -- esp[(argc + 1) * 4] : receiver |
| 2041 // ----------------------------------- | 2054 // ----------------------------------- |
| 2042 | 2055 |
| 2043 const int argc = arguments().immediate(); | 2056 const int argc = arguments().immediate(); |
| 2044 | 2057 |
| 2045 // If the object is not a JSObject or we got an unexpected number of | 2058 // If the object is not a JSObject or we got an unexpected number of |
| 2046 // arguments, bail out to the regular call. | 2059 // arguments, bail out to the regular call. |
| 2047 if (!object->IsJSObject() || argc != 1) return HEAP->undefined_value(); | 2060 if (!object->IsJSObject() || argc != 1) { |
| 2061 return isolate()->heap()->undefined_value(); |
| 2062 } |
| 2048 | 2063 |
| 2049 Label miss; | 2064 Label miss; |
| 2050 GenerateNameCheck(name, &miss); | 2065 GenerateNameCheck(name, &miss); |
| 2051 | 2066 |
| 2052 if (cell == NULL) { | 2067 if (cell == NULL) { |
| 2053 __ mov(edx, Operand(esp, 2 * kPointerSize)); | 2068 __ mov(edx, Operand(esp, 2 * kPointerSize)); |
| 2054 | 2069 |
| 2055 STATIC_ASSERT(kSmiTag == 0); | 2070 STATIC_ASSERT(kSmiTag == 0); |
| 2056 __ test(edx, Immediate(kSmiTagMask)); | 2071 __ test(edx, Immediate(kSmiTagMask)); |
| 2057 __ j(zero, &miss); | 2072 __ j(zero, &miss); |
| (...skipping 75 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2133 MaybeObject* CallStubCompiler::CompileFastApiCall( | 2148 MaybeObject* CallStubCompiler::CompileFastApiCall( |
| 2134 const CallOptimization& optimization, | 2149 const CallOptimization& optimization, |
| 2135 Object* object, | 2150 Object* object, |
| 2136 JSObject* holder, | 2151 JSObject* holder, |
| 2137 JSGlobalPropertyCell* cell, | 2152 JSGlobalPropertyCell* cell, |
| 2138 JSFunction* function, | 2153 JSFunction* function, |
| 2139 String* name) { | 2154 String* name) { |
| 2140 ASSERT(optimization.is_simple_api_call()); | 2155 ASSERT(optimization.is_simple_api_call()); |
| 2141 // Bail out if object is a global object as we don't want to | 2156 // Bail out if object is a global object as we don't want to |
| 2142 // repatch it to global receiver. | 2157 // repatch it to global receiver. |
| 2143 if (object->IsGlobalObject()) return HEAP->undefined_value(); | 2158 Heap* heap = isolate()->heap(); |
| 2144 if (cell != NULL) return HEAP->undefined_value(); | 2159 if (object->IsGlobalObject()) return heap->undefined_value(); |
| 2160 if (cell != NULL) return heap->undefined_value(); |
| 2145 int depth = optimization.GetPrototypeDepthOfExpectedType( | 2161 int depth = optimization.GetPrototypeDepthOfExpectedType( |
| 2146 JSObject::cast(object), holder); | 2162 JSObject::cast(object), holder); |
| 2147 if (depth == kInvalidProtoDepth) return HEAP->undefined_value(); | 2163 if (depth == kInvalidProtoDepth) return heap->undefined_value(); |
| 2148 | 2164 |
| 2149 Label miss, miss_before_stack_reserved; | 2165 Label miss, miss_before_stack_reserved; |
| 2150 | 2166 |
| 2151 GenerateNameCheck(name, &miss_before_stack_reserved); | 2167 GenerateNameCheck(name, &miss_before_stack_reserved); |
| 2152 | 2168 |
| 2153 // Get the receiver from the stack. | 2169 // Get the receiver from the stack. |
| 2154 const int argc = arguments().immediate(); | 2170 const int argc = arguments().immediate(); |
| 2155 __ mov(edx, Operand(esp, (argc + 1) * kPointerSize)); | 2171 __ mov(edx, Operand(esp, (argc + 1) * kPointerSize)); |
| 2156 | 2172 |
| 2157 // Check that the receiver isn't a smi. | 2173 // Check that the receiver isn't a smi. |
| 2158 __ test(edx, Immediate(kSmiTagMask)); | 2174 __ test(edx, Immediate(kSmiTagMask)); |
| 2159 __ j(zero, &miss_before_stack_reserved, not_taken); | 2175 __ j(zero, &miss_before_stack_reserved, not_taken); |
| 2160 | 2176 |
| 2161 Counters* counters = masm()->isolate()->counters(); | 2177 Counters* counters = isolate()->counters(); |
| 2162 __ IncrementCounter(counters->call_const(), 1); | 2178 __ IncrementCounter(counters->call_const(), 1); |
| 2163 __ IncrementCounter(counters->call_const_fast_api(), 1); | 2179 __ IncrementCounter(counters->call_const_fast_api(), 1); |
| 2164 | 2180 |
| 2165 // Allocate space for v8::Arguments implicit values. Must be initialized | 2181 // Allocate space for v8::Arguments implicit values. Must be initialized |
| 2166 // before calling any runtime function. | 2182 // before calling any runtime function. |
| 2167 __ sub(Operand(esp), Immediate(kFastApiCallArguments * kPointerSize)); | 2183 __ sub(Operand(esp), Immediate(kFastApiCallArguments * kPointerSize)); |
| 2168 | 2184 |
| 2169 // Check that the maps haven't changed and find a Holder as a side effect. | 2185 // Check that the maps haven't changed and find a Holder as a side effect. |
| 2170 CheckPrototypes(JSObject::cast(object), edx, holder, | 2186 CheckPrototypes(JSObject::cast(object), edx, holder, |
| 2171 ebx, eax, edi, name, depth, &miss); | 2187 ebx, eax, edi, name, depth, &miss); |
| (...skipping 55 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2227 __ j(zero, &miss, not_taken); | 2243 __ j(zero, &miss, not_taken); |
| 2228 } | 2244 } |
| 2229 | 2245 |
| 2230 // Make sure that it's okay not to patch the on stack receiver | 2246 // Make sure that it's okay not to patch the on stack receiver |
| 2231 // unless we're doing a receiver map check. | 2247 // unless we're doing a receiver map check. |
| 2232 ASSERT(!object->IsGlobalObject() || check == RECEIVER_MAP_CHECK); | 2248 ASSERT(!object->IsGlobalObject() || check == RECEIVER_MAP_CHECK); |
| 2233 | 2249 |
| 2234 SharedFunctionInfo* function_info = function->shared(); | 2250 SharedFunctionInfo* function_info = function->shared(); |
| 2235 switch (check) { | 2251 switch (check) { |
| 2236 case RECEIVER_MAP_CHECK: | 2252 case RECEIVER_MAP_CHECK: |
| 2237 __ IncrementCounter(masm()->isolate()->counters()->call_const(), 1); | 2253 __ IncrementCounter(isolate()->counters()->call_const(), 1); |
| 2238 | 2254 |
| 2239 // Check that the maps haven't changed. | 2255 // Check that the maps haven't changed. |
| 2240 CheckPrototypes(JSObject::cast(object), edx, holder, | 2256 CheckPrototypes(JSObject::cast(object), edx, holder, |
| 2241 ebx, eax, edi, name, &miss); | 2257 ebx, eax, edi, name, &miss); |
| 2242 | 2258 |
| 2243 // Patch the receiver on the stack with the global proxy if | 2259 // Patch the receiver on the stack with the global proxy if |
| 2244 // necessary. | 2260 // necessary. |
| 2245 if (object->IsGlobalObject()) { | 2261 if (object->IsGlobalObject()) { |
| 2246 __ mov(edx, FieldOperand(edx, GlobalObject::kGlobalReceiverOffset)); | 2262 __ mov(edx, FieldOperand(edx, GlobalObject::kGlobalReceiverOffset)); |
| 2247 __ mov(Operand(esp, (argc + 1) * kPointerSize), edx); | 2263 __ mov(Operand(esp, (argc + 1) * kPointerSize), edx); |
| (...skipping 179 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2427 // Patch the receiver on the stack with the global proxy. | 2443 // Patch the receiver on the stack with the global proxy. |
| 2428 if (object->IsGlobalObject()) { | 2444 if (object->IsGlobalObject()) { |
| 2429 __ mov(edx, FieldOperand(edx, GlobalObject::kGlobalReceiverOffset)); | 2445 __ mov(edx, FieldOperand(edx, GlobalObject::kGlobalReceiverOffset)); |
| 2430 __ mov(Operand(esp, (argc + 1) * kPointerSize), edx); | 2446 __ mov(Operand(esp, (argc + 1) * kPointerSize), edx); |
| 2431 } | 2447 } |
| 2432 | 2448 |
| 2433 // Setup the context (function already in edi). | 2449 // Setup the context (function already in edi). |
| 2434 __ mov(esi, FieldOperand(edi, JSFunction::kContextOffset)); | 2450 __ mov(esi, FieldOperand(edi, JSFunction::kContextOffset)); |
| 2435 | 2451 |
| 2436 // Jump to the cached code (tail call). | 2452 // Jump to the cached code (tail call). |
| 2437 Counters* counters = masm()->isolate()->counters(); | 2453 Counters* counters = isolate()->counters(); |
| 2438 __ IncrementCounter(counters->call_global_inline(), 1); | 2454 __ IncrementCounter(counters->call_global_inline(), 1); |
| 2439 ASSERT(function->is_compiled()); | 2455 ASSERT(function->is_compiled()); |
| 2440 ParameterCount expected(function->shared()->formal_parameter_count()); | 2456 ParameterCount expected(function->shared()->formal_parameter_count()); |
| 2441 if (V8::UseCrankshaft()) { | 2457 if (V8::UseCrankshaft()) { |
| 2442 // TODO(kasperl): For now, we always call indirectly through the | 2458 // TODO(kasperl): For now, we always call indirectly through the |
| 2443 // code field in the function to allow recompilation to take effect | 2459 // code field in the function to allow recompilation to take effect |
| 2444 // without changing any of the call sites. | 2460 // without changing any of the call sites. |
| 2445 __ InvokeCode(FieldOperand(edi, JSFunction::kCodeEntryOffset), | 2461 __ InvokeCode(FieldOperand(edi, JSFunction::kCodeEntryOffset), |
| 2446 expected, arguments(), JUMP_FUNCTION); | 2462 expected, arguments(), JUMP_FUNCTION); |
| 2447 } else { | 2463 } else { |
| (...skipping 29 matching lines...) Expand all Loading... |
| 2477 GenerateStoreField(masm(), | 2493 GenerateStoreField(masm(), |
| 2478 object, | 2494 object, |
| 2479 index, | 2495 index, |
| 2480 transition, | 2496 transition, |
| 2481 edx, ecx, ebx, | 2497 edx, ecx, ebx, |
| 2482 &miss); | 2498 &miss); |
| 2483 | 2499 |
| 2484 // Handle store cache miss. | 2500 // Handle store cache miss. |
| 2485 __ bind(&miss); | 2501 __ bind(&miss); |
| 2486 __ mov(ecx, Immediate(Handle<String>(name))); // restore name | 2502 __ mov(ecx, Immediate(Handle<String>(name))); // restore name |
| 2487 Handle<Code> ic = masm()->isolate()->builtins()->StoreIC_Miss(); | 2503 Handle<Code> ic = isolate()->builtins()->StoreIC_Miss(); |
| 2488 __ jmp(ic, RelocInfo::CODE_TARGET); | 2504 __ jmp(ic, RelocInfo::CODE_TARGET); |
| 2489 | 2505 |
| 2490 // Return the generated code. | 2506 // Return the generated code. |
| 2491 return GetCode(transition == NULL ? FIELD : MAP_TRANSITION, name); | 2507 return GetCode(transition == NULL ? FIELD : MAP_TRANSITION, name); |
| 2492 } | 2508 } |
| 2493 | 2509 |
| 2494 | 2510 |
| 2495 MaybeObject* StoreStubCompiler::CompileStoreCallback(JSObject* object, | 2511 MaybeObject* StoreStubCompiler::CompileStoreCallback(JSObject* object, |
| 2496 AccessorInfo* callback, | 2512 AccessorInfo* callback, |
| 2497 String* name) { | 2513 String* name) { |
| (...skipping 24 matching lines...) Expand all Loading... |
| 2522 ASSERT(object->IsJSGlobalProxy() || !object->IsAccessCheckNeeded()); | 2538 ASSERT(object->IsJSGlobalProxy() || !object->IsAccessCheckNeeded()); |
| 2523 | 2539 |
| 2524 __ pop(ebx); // remove the return address | 2540 __ pop(ebx); // remove the return address |
| 2525 __ push(edx); // receiver | 2541 __ push(edx); // receiver |
| 2526 __ push(Immediate(Handle<AccessorInfo>(callback))); // callback info | 2542 __ push(Immediate(Handle<AccessorInfo>(callback))); // callback info |
| 2527 __ push(ecx); // name | 2543 __ push(ecx); // name |
| 2528 __ push(eax); // value | 2544 __ push(eax); // value |
| 2529 __ push(ebx); // restore return address | 2545 __ push(ebx); // restore return address |
| 2530 | 2546 |
| 2531 // Do tail-call to the runtime system. | 2547 // Do tail-call to the runtime system. |
| 2532 Isolate* isolate = masm()->isolate(); | |
| 2533 ExternalReference store_callback_property = | 2548 ExternalReference store_callback_property = |
| 2534 ExternalReference(IC_Utility(IC::kStoreCallbackProperty), isolate); | 2549 ExternalReference(IC_Utility(IC::kStoreCallbackProperty), isolate()); |
| 2535 __ TailCallExternalReference(store_callback_property, 4, 1); | 2550 __ TailCallExternalReference(store_callback_property, 4, 1); |
| 2536 | 2551 |
| 2537 // Handle store cache miss. | 2552 // Handle store cache miss. |
| 2538 __ bind(&miss); | 2553 __ bind(&miss); |
| 2539 Handle<Code> ic = isolate->builtins()->StoreIC_Miss(); | 2554 Handle<Code> ic = isolate()->builtins()->StoreIC_Miss(); |
| 2540 __ jmp(ic, RelocInfo::CODE_TARGET); | 2555 __ jmp(ic, RelocInfo::CODE_TARGET); |
| 2541 | 2556 |
| 2542 // Return the generated code. | 2557 // Return the generated code. |
| 2543 return GetCode(CALLBACKS, name); | 2558 return GetCode(CALLBACKS, name); |
| 2544 } | 2559 } |
| 2545 | 2560 |
| 2546 | 2561 |
| 2547 MaybeObject* StoreStubCompiler::CompileStoreInterceptor(JSObject* receiver, | 2562 MaybeObject* StoreStubCompiler::CompileStoreInterceptor(JSObject* receiver, |
| 2548 String* name) { | 2563 String* name) { |
| 2549 // ----------- S t a t e ------------- | 2564 // ----------- S t a t e ------------- |
| (...skipping 23 matching lines...) Expand all Loading... |
| 2573 ASSERT(receiver->IsJSGlobalProxy() || !receiver->IsAccessCheckNeeded()); | 2588 ASSERT(receiver->IsJSGlobalProxy() || !receiver->IsAccessCheckNeeded()); |
| 2574 | 2589 |
| 2575 __ pop(ebx); // remove the return address | 2590 __ pop(ebx); // remove the return address |
| 2576 __ push(edx); // receiver | 2591 __ push(edx); // receiver |
| 2577 __ push(ecx); // name | 2592 __ push(ecx); // name |
| 2578 __ push(eax); // value | 2593 __ push(eax); // value |
| 2579 __ push(Immediate(Smi::FromInt(strict_mode_))); | 2594 __ push(Immediate(Smi::FromInt(strict_mode_))); |
| 2580 __ push(ebx); // restore return address | 2595 __ push(ebx); // restore return address |
| 2581 | 2596 |
| 2582 // Do tail-call to the runtime system. | 2597 // Do tail-call to the runtime system. |
| 2583 Isolate* isolate = masm()->isolate(); | |
| 2584 ExternalReference store_ic_property = | 2598 ExternalReference store_ic_property = |
| 2585 ExternalReference(IC_Utility(IC::kStoreInterceptorProperty), isolate); | 2599 ExternalReference(IC_Utility(IC::kStoreInterceptorProperty), isolate()); |
| 2586 __ TailCallExternalReference(store_ic_property, 4, 1); | 2600 __ TailCallExternalReference(store_ic_property, 4, 1); |
| 2587 | 2601 |
| 2588 // Handle store cache miss. | 2602 // Handle store cache miss. |
| 2589 __ bind(&miss); | 2603 __ bind(&miss); |
| 2590 Handle<Code> ic = isolate->builtins()->StoreIC_Miss(); | 2604 Handle<Code> ic = isolate()->builtins()->StoreIC_Miss(); |
| 2591 __ jmp(ic, RelocInfo::CODE_TARGET); | 2605 __ jmp(ic, RelocInfo::CODE_TARGET); |
| 2592 | 2606 |
| 2593 // Return the generated code. | 2607 // Return the generated code. |
| 2594 return GetCode(INTERCEPTOR, name); | 2608 return GetCode(INTERCEPTOR, name); |
| 2595 } | 2609 } |
| 2596 | 2610 |
| 2597 | 2611 |
| 2598 MaybeObject* StoreStubCompiler::CompileStoreGlobal(GlobalObject* object, | 2612 MaybeObject* StoreStubCompiler::CompileStoreGlobal(GlobalObject* object, |
| 2599 JSGlobalPropertyCell* cell, | 2613 JSGlobalPropertyCell* cell, |
| 2600 String* name) { | 2614 String* name) { |
| (...skipping 22 matching lines...) Expand all Loading... |
| 2623 // cell could have been deleted and reintroducing the global needs | 2637 // cell could have been deleted and reintroducing the global needs |
| 2624 // to update the property details in the property dictionary of the | 2638 // to update the property details in the property dictionary of the |
| 2625 // global object. We bail out to the runtime system to do that. | 2639 // global object. We bail out to the runtime system to do that. |
| 2626 __ cmp(cell_operand, FACTORY->the_hole_value()); | 2640 __ cmp(cell_operand, FACTORY->the_hole_value()); |
| 2627 __ j(equal, &miss); | 2641 __ j(equal, &miss); |
| 2628 | 2642 |
| 2629 // Store the value in the cell. | 2643 // Store the value in the cell. |
| 2630 __ mov(cell_operand, eax); | 2644 __ mov(cell_operand, eax); |
| 2631 | 2645 |
| 2632 // Return the value (register eax). | 2646 // Return the value (register eax). |
| 2633 Counters* counters = masm()->isolate()->counters(); | 2647 Counters* counters = isolate()->counters(); |
| 2634 __ IncrementCounter(counters->named_store_global_inline(), 1); | 2648 __ IncrementCounter(counters->named_store_global_inline(), 1); |
| 2635 __ ret(0); | 2649 __ ret(0); |
| 2636 | 2650 |
| 2637 // Handle store cache miss. | 2651 // Handle store cache miss. |
| 2638 __ bind(&miss); | 2652 __ bind(&miss); |
| 2639 __ IncrementCounter(counters->named_store_global_inline_miss(), 1); | 2653 __ IncrementCounter(counters->named_store_global_inline_miss(), 1); |
| 2640 Handle<Code> ic = masm()->isolate()->builtins()->StoreIC_Miss(); | 2654 Handle<Code> ic = isolate()->builtins()->StoreIC_Miss(); |
| 2641 __ jmp(ic, RelocInfo::CODE_TARGET); | 2655 __ jmp(ic, RelocInfo::CODE_TARGET); |
| 2642 | 2656 |
| 2643 // Return the generated code. | 2657 // Return the generated code. |
| 2644 return GetCode(NORMAL, name); | 2658 return GetCode(NORMAL, name); |
| 2645 } | 2659 } |
| 2646 | 2660 |
| 2647 | 2661 |
| 2648 MaybeObject* KeyedStoreStubCompiler::CompileStoreField(JSObject* object, | 2662 MaybeObject* KeyedStoreStubCompiler::CompileStoreField(JSObject* object, |
| 2649 int index, | 2663 int index, |
| 2650 Map* transition, | 2664 Map* transition, |
| 2651 String* name) { | 2665 String* name) { |
| 2652 // ----------- S t a t e ------------- | 2666 // ----------- S t a t e ------------- |
| 2653 // -- eax : value | 2667 // -- eax : value |
| 2654 // -- ecx : key | 2668 // -- ecx : key |
| 2655 // -- edx : receiver | 2669 // -- edx : receiver |
| 2656 // -- esp[0] : return address | 2670 // -- esp[0] : return address |
| 2657 // ----------------------------------- | 2671 // ----------------------------------- |
| 2658 Label miss; | 2672 Label miss; |
| 2659 | 2673 |
| 2660 Counters* counters = masm()->isolate()->counters(); | 2674 Counters* counters = isolate()->counters(); |
| 2661 __ IncrementCounter(counters->keyed_store_field(), 1); | 2675 __ IncrementCounter(counters->keyed_store_field(), 1); |
| 2662 | 2676 |
| 2663 // Check that the name has not changed. | 2677 // Check that the name has not changed. |
| 2664 __ cmp(Operand(ecx), Immediate(Handle<String>(name))); | 2678 __ cmp(Operand(ecx), Immediate(Handle<String>(name))); |
| 2665 __ j(not_equal, &miss, not_taken); | 2679 __ j(not_equal, &miss, not_taken); |
| 2666 | 2680 |
| 2667 // Generate store field code. Trashes the name register. | 2681 // Generate store field code. Trashes the name register. |
| 2668 GenerateStoreField(masm(), | 2682 GenerateStoreField(masm(), |
| 2669 object, | 2683 object, |
| 2670 index, | 2684 index, |
| 2671 transition, | 2685 transition, |
| 2672 edx, ecx, ebx, | 2686 edx, ecx, ebx, |
| 2673 &miss); | 2687 &miss); |
| 2674 | 2688 |
| 2675 // Handle store cache miss. | 2689 // Handle store cache miss. |
| 2676 __ bind(&miss); | 2690 __ bind(&miss); |
| 2677 __ DecrementCounter(counters->keyed_store_field(), 1); | 2691 __ DecrementCounter(counters->keyed_store_field(), 1); |
| 2678 Handle<Code> ic = masm()->isolate()->builtins()->KeyedStoreIC_Miss(); | 2692 Handle<Code> ic = isolate()->builtins()->KeyedStoreIC_Miss(); |
| 2679 __ jmp(ic, RelocInfo::CODE_TARGET); | 2693 __ jmp(ic, RelocInfo::CODE_TARGET); |
| 2680 | 2694 |
| 2681 // Return the generated code. | 2695 // Return the generated code. |
| 2682 return GetCode(transition == NULL ? FIELD : MAP_TRANSITION, name); | 2696 return GetCode(transition == NULL ? FIELD : MAP_TRANSITION, name); |
| 2683 } | 2697 } |
| 2684 | 2698 |
| 2685 | 2699 |
| 2686 MaybeObject* KeyedStoreStubCompiler::CompileStoreSpecialized( | 2700 MaybeObject* KeyedStoreStubCompiler::CompileStoreSpecialized( |
| 2687 JSObject* receiver) { | 2701 JSObject* receiver) { |
| 2688 // ----------- S t a t e ------------- | 2702 // ----------- S t a t e ------------- |
| (...skipping 36 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2725 // the value in register eax. | 2739 // the value in register eax. |
| 2726 __ mov(edx, Operand(eax)); | 2740 __ mov(edx, Operand(eax)); |
| 2727 __ mov(FieldOperand(edi, ecx, times_2, FixedArray::kHeaderSize), eax); | 2741 __ mov(FieldOperand(edi, ecx, times_2, FixedArray::kHeaderSize), eax); |
| 2728 __ RecordWrite(edi, 0, edx, ecx); | 2742 __ RecordWrite(edi, 0, edx, ecx); |
| 2729 | 2743 |
| 2730 // Done. | 2744 // Done. |
| 2731 __ ret(0); | 2745 __ ret(0); |
| 2732 | 2746 |
| 2733 // Handle store cache miss. | 2747 // Handle store cache miss. |
| 2734 __ bind(&miss); | 2748 __ bind(&miss); |
| 2735 Handle<Code> ic = masm()->isolate()->builtins()->KeyedStoreIC_Miss(); | 2749 Handle<Code> ic = isolate()->builtins()->KeyedStoreIC_Miss(); |
| 2736 __ jmp(ic, RelocInfo::CODE_TARGET); | 2750 __ jmp(ic, RelocInfo::CODE_TARGET); |
| 2737 | 2751 |
| 2738 // Return the generated code. | 2752 // Return the generated code. |
| 2739 return GetCode(NORMAL, NULL); | 2753 return GetCode(NORMAL, NULL); |
| 2740 } | 2754 } |
| 2741 | 2755 |
| 2742 | 2756 |
| 2743 MaybeObject* LoadStubCompiler::CompileLoadNonexistent(String* name, | 2757 MaybeObject* LoadStubCompiler::CompileLoadNonexistent(String* name, |
| 2744 JSObject* object, | 2758 JSObject* object, |
| 2745 JSObject* last) { | 2759 JSObject* last) { |
| (...skipping 24 matching lines...) Expand all Loading... |
| 2770 edx, | 2784 edx, |
| 2771 &miss); | 2785 &miss); |
| 2772 if (cell->IsFailure()) { | 2786 if (cell->IsFailure()) { |
| 2773 miss.Unuse(); | 2787 miss.Unuse(); |
| 2774 return cell; | 2788 return cell; |
| 2775 } | 2789 } |
| 2776 } | 2790 } |
| 2777 | 2791 |
| 2778 // Return undefined if maps of the full prototype chain are still the | 2792 // Return undefined if maps of the full prototype chain are still the |
| 2779 // same and no global property with this name contains a value. | 2793 // same and no global property with this name contains a value. |
| 2780 __ mov(eax, FACTORY->undefined_value()); | 2794 __ mov(eax, isolate()->factory()->undefined_value()); |
| 2781 __ ret(0); | 2795 __ ret(0); |
| 2782 | 2796 |
| 2783 __ bind(&miss); | 2797 __ bind(&miss); |
| 2784 GenerateLoadMiss(masm(), Code::LOAD_IC); | 2798 GenerateLoadMiss(masm(), Code::LOAD_IC); |
| 2785 | 2799 |
| 2786 // Return the generated code. | 2800 // Return the generated code. |
| 2787 return GetCode(NONEXISTENT, HEAP->empty_string()); | 2801 return GetCode(NONEXISTENT, isolate()->heap()->empty_string()); |
| 2788 } | 2802 } |
| 2789 | 2803 |
| 2790 | 2804 |
| 2791 MaybeObject* LoadStubCompiler::CompileLoadField(JSObject* object, | 2805 MaybeObject* LoadStubCompiler::CompileLoadField(JSObject* object, |
| 2792 JSObject* holder, | 2806 JSObject* holder, |
| 2793 int index, | 2807 int index, |
| 2794 String* name) { | 2808 String* name) { |
| 2795 // ----------- S t a t e ------------- | 2809 // ----------- S t a t e ------------- |
| 2796 // -- eax : receiver | 2810 // -- eax : receiver |
| 2797 // -- ecx : name | 2811 // -- ecx : name |
| (...skipping 123 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2921 | 2935 |
| 2922 // Check for deleted property if property can actually be deleted. | 2936 // Check for deleted property if property can actually be deleted. |
| 2923 if (!is_dont_delete) { | 2937 if (!is_dont_delete) { |
| 2924 __ cmp(ebx, FACTORY->the_hole_value()); | 2938 __ cmp(ebx, FACTORY->the_hole_value()); |
| 2925 __ j(equal, &miss, not_taken); | 2939 __ j(equal, &miss, not_taken); |
| 2926 } else if (FLAG_debug_code) { | 2940 } else if (FLAG_debug_code) { |
| 2927 __ cmp(ebx, FACTORY->the_hole_value()); | 2941 __ cmp(ebx, FACTORY->the_hole_value()); |
| 2928 __ Check(not_equal, "DontDelete cells can't contain the hole"); | 2942 __ Check(not_equal, "DontDelete cells can't contain the hole"); |
| 2929 } | 2943 } |
| 2930 | 2944 |
| 2931 Counters* counters = masm()->isolate()->counters(); | 2945 Counters* counters = isolate()->counters(); |
| 2932 __ IncrementCounter(counters->named_load_global_stub(), 1); | 2946 __ IncrementCounter(counters->named_load_global_stub(), 1); |
| 2933 __ mov(eax, ebx); | 2947 __ mov(eax, ebx); |
| 2934 __ ret(0); | 2948 __ ret(0); |
| 2935 | 2949 |
| 2936 __ bind(&miss); | 2950 __ bind(&miss); |
| 2937 __ IncrementCounter(counters->named_load_global_stub_miss(), 1); | 2951 __ IncrementCounter(counters->named_load_global_stub_miss(), 1); |
| 2938 GenerateLoadMiss(masm(), Code::LOAD_IC); | 2952 GenerateLoadMiss(masm(), Code::LOAD_IC); |
| 2939 | 2953 |
| 2940 // Return the generated code. | 2954 // Return the generated code. |
| 2941 return GetCode(NORMAL, name); | 2955 return GetCode(NORMAL, name); |
| 2942 } | 2956 } |
| 2943 | 2957 |
| 2944 | 2958 |
| 2945 MaybeObject* KeyedLoadStubCompiler::CompileLoadField(String* name, | 2959 MaybeObject* KeyedLoadStubCompiler::CompileLoadField(String* name, |
| 2946 JSObject* receiver, | 2960 JSObject* receiver, |
| 2947 JSObject* holder, | 2961 JSObject* holder, |
| 2948 int index) { | 2962 int index) { |
| 2949 // ----------- S t a t e ------------- | 2963 // ----------- S t a t e ------------- |
| 2950 // -- eax : key | 2964 // -- eax : key |
| 2951 // -- edx : receiver | 2965 // -- edx : receiver |
| 2952 // -- esp[0] : return address | 2966 // -- esp[0] : return address |
| 2953 // ----------------------------------- | 2967 // ----------------------------------- |
| 2954 Label miss; | 2968 Label miss; |
| 2955 | 2969 |
| 2956 Counters* counters = masm()->isolate()->counters(); | 2970 Counters* counters = isolate()->counters(); |
| 2957 __ IncrementCounter(counters->keyed_load_field(), 1); | 2971 __ IncrementCounter(counters->keyed_load_field(), 1); |
| 2958 | 2972 |
| 2959 // Check that the name has not changed. | 2973 // Check that the name has not changed. |
| 2960 __ cmp(Operand(eax), Immediate(Handle<String>(name))); | 2974 __ cmp(Operand(eax), Immediate(Handle<String>(name))); |
| 2961 __ j(not_equal, &miss, not_taken); | 2975 __ j(not_equal, &miss, not_taken); |
| 2962 | 2976 |
| 2963 GenerateLoadField(receiver, holder, edx, ebx, ecx, edi, index, name, &miss); | 2977 GenerateLoadField(receiver, holder, edx, ebx, ecx, edi, index, name, &miss); |
| 2964 | 2978 |
| 2965 __ bind(&miss); | 2979 __ bind(&miss); |
| 2966 __ DecrementCounter(counters->keyed_load_field(), 1); | 2980 __ DecrementCounter(counters->keyed_load_field(), 1); |
| 2967 GenerateLoadMiss(masm(), Code::KEYED_LOAD_IC); | 2981 GenerateLoadMiss(masm(), Code::KEYED_LOAD_IC); |
| 2968 | 2982 |
| 2969 // Return the generated code. | 2983 // Return the generated code. |
| 2970 return GetCode(FIELD, name); | 2984 return GetCode(FIELD, name); |
| 2971 } | 2985 } |
| 2972 | 2986 |
| 2973 | 2987 |
| 2974 MaybeObject* KeyedLoadStubCompiler::CompileLoadCallback( | 2988 MaybeObject* KeyedLoadStubCompiler::CompileLoadCallback( |
| 2975 String* name, | 2989 String* name, |
| 2976 JSObject* receiver, | 2990 JSObject* receiver, |
| 2977 JSObject* holder, | 2991 JSObject* holder, |
| 2978 AccessorInfo* callback) { | 2992 AccessorInfo* callback) { |
| 2979 // ----------- S t a t e ------------- | 2993 // ----------- S t a t e ------------- |
| 2980 // -- eax : key | 2994 // -- eax : key |
| 2981 // -- edx : receiver | 2995 // -- edx : receiver |
| 2982 // -- esp[0] : return address | 2996 // -- esp[0] : return address |
| 2983 // ----------------------------------- | 2997 // ----------------------------------- |
| 2984 Label miss; | 2998 Label miss; |
| 2985 | 2999 |
| 2986 Counters* counters = masm()->isolate()->counters(); | 3000 Counters* counters = isolate()->counters(); |
| 2987 __ IncrementCounter(counters->keyed_load_callback(), 1); | 3001 __ IncrementCounter(counters->keyed_load_callback(), 1); |
| 2988 | 3002 |
| 2989 // Check that the name has not changed. | 3003 // Check that the name has not changed. |
| 2990 __ cmp(Operand(eax), Immediate(Handle<String>(name))); | 3004 __ cmp(Operand(eax), Immediate(Handle<String>(name))); |
| 2991 __ j(not_equal, &miss, not_taken); | 3005 __ j(not_equal, &miss, not_taken); |
| 2992 | 3006 |
| 2993 MaybeObject* result = GenerateLoadCallback(receiver, holder, edx, eax, ebx, | 3007 MaybeObject* result = GenerateLoadCallback(receiver, holder, edx, eax, ebx, |
| 2994 ecx, edi, callback, name, &miss); | 3008 ecx, edi, callback, name, &miss); |
| 2995 if (result->IsFailure()) { | 3009 if (result->IsFailure()) { |
| 2996 miss.Unuse(); | 3010 miss.Unuse(); |
| (...skipping 14 matching lines...) Expand all Loading... |
| 3011 JSObject* receiver, | 3025 JSObject* receiver, |
| 3012 JSObject* holder, | 3026 JSObject* holder, |
| 3013 Object* value) { | 3027 Object* value) { |
| 3014 // ----------- S t a t e ------------- | 3028 // ----------- S t a t e ------------- |
| 3015 // -- eax : key | 3029 // -- eax : key |
| 3016 // -- edx : receiver | 3030 // -- edx : receiver |
| 3017 // -- esp[0] : return address | 3031 // -- esp[0] : return address |
| 3018 // ----------------------------------- | 3032 // ----------------------------------- |
| 3019 Label miss; | 3033 Label miss; |
| 3020 | 3034 |
| 3021 Counters* counters = masm()->isolate()->counters(); | 3035 Counters* counters = isolate()->counters(); |
| 3022 __ IncrementCounter(counters->keyed_load_constant_function(), 1); | 3036 __ IncrementCounter(counters->keyed_load_constant_function(), 1); |
| 3023 | 3037 |
| 3024 // Check that the name has not changed. | 3038 // Check that the name has not changed. |
| 3025 __ cmp(Operand(eax), Immediate(Handle<String>(name))); | 3039 __ cmp(Operand(eax), Immediate(Handle<String>(name))); |
| 3026 __ j(not_equal, &miss, not_taken); | 3040 __ j(not_equal, &miss, not_taken); |
| 3027 | 3041 |
| 3028 GenerateLoadConstant(receiver, holder, edx, ebx, ecx, edi, | 3042 GenerateLoadConstant(receiver, holder, edx, ebx, ecx, edi, |
| 3029 value, name, &miss); | 3043 value, name, &miss); |
| 3030 __ bind(&miss); | 3044 __ bind(&miss); |
| 3031 __ DecrementCounter(counters->keyed_load_constant_function(), 1); | 3045 __ DecrementCounter(counters->keyed_load_constant_function(), 1); |
| 3032 GenerateLoadMiss(masm(), Code::KEYED_LOAD_IC); | 3046 GenerateLoadMiss(masm(), Code::KEYED_LOAD_IC); |
| 3033 | 3047 |
| 3034 // Return the generated code. | 3048 // Return the generated code. |
| 3035 return GetCode(CONSTANT_FUNCTION, name); | 3049 return GetCode(CONSTANT_FUNCTION, name); |
| 3036 } | 3050 } |
| 3037 | 3051 |
| 3038 | 3052 |
| 3039 MaybeObject* KeyedLoadStubCompiler::CompileLoadInterceptor(JSObject* receiver, | 3053 MaybeObject* KeyedLoadStubCompiler::CompileLoadInterceptor(JSObject* receiver, |
| 3040 JSObject* holder, | 3054 JSObject* holder, |
| 3041 String* name) { | 3055 String* name) { |
| 3042 // ----------- S t a t e ------------- | 3056 // ----------- S t a t e ------------- |
| 3043 // -- eax : key | 3057 // -- eax : key |
| 3044 // -- edx : receiver | 3058 // -- edx : receiver |
| 3045 // -- esp[0] : return address | 3059 // -- esp[0] : return address |
| 3046 // ----------------------------------- | 3060 // ----------------------------------- |
| 3047 Label miss; | 3061 Label miss; |
| 3048 | 3062 |
| 3049 Counters* counters = masm()->isolate()->counters(); | 3063 Counters* counters = isolate()->counters(); |
| 3050 __ IncrementCounter(counters->keyed_load_interceptor(), 1); | 3064 __ IncrementCounter(counters->keyed_load_interceptor(), 1); |
| 3051 | 3065 |
| 3052 // Check that the name has not changed. | 3066 // Check that the name has not changed. |
| 3053 __ cmp(Operand(eax), Immediate(Handle<String>(name))); | 3067 __ cmp(Operand(eax), Immediate(Handle<String>(name))); |
| 3054 __ j(not_equal, &miss, not_taken); | 3068 __ j(not_equal, &miss, not_taken); |
| 3055 | 3069 |
| 3056 LookupResult lookup; | 3070 LookupResult lookup; |
| 3057 LookupPostInterceptor(holder, name, &lookup); | 3071 LookupPostInterceptor(holder, name, &lookup); |
| 3058 GenerateLoadInterceptor(receiver, | 3072 GenerateLoadInterceptor(receiver, |
| 3059 holder, | 3073 holder, |
| (...skipping 15 matching lines...) Expand all Loading... |
| 3075 | 3089 |
| 3076 | 3090 |
| 3077 MaybeObject* KeyedLoadStubCompiler::CompileLoadArrayLength(String* name) { | 3091 MaybeObject* KeyedLoadStubCompiler::CompileLoadArrayLength(String* name) { |
| 3078 // ----------- S t a t e ------------- | 3092 // ----------- S t a t e ------------- |
| 3079 // -- eax : key | 3093 // -- eax : key |
| 3080 // -- edx : receiver | 3094 // -- edx : receiver |
| 3081 // -- esp[0] : return address | 3095 // -- esp[0] : return address |
| 3082 // ----------------------------------- | 3096 // ----------------------------------- |
| 3083 Label miss; | 3097 Label miss; |
| 3084 | 3098 |
| 3085 Counters* counters = masm()->isolate()->counters(); | 3099 Counters* counters = isolate()->counters(); |
| 3086 __ IncrementCounter(counters->keyed_load_array_length(), 1); | 3100 __ IncrementCounter(counters->keyed_load_array_length(), 1); |
| 3087 | 3101 |
| 3088 // Check that the name has not changed. | 3102 // Check that the name has not changed. |
| 3089 __ cmp(Operand(eax), Immediate(Handle<String>(name))); | 3103 __ cmp(Operand(eax), Immediate(Handle<String>(name))); |
| 3090 __ j(not_equal, &miss, not_taken); | 3104 __ j(not_equal, &miss, not_taken); |
| 3091 | 3105 |
| 3092 GenerateLoadArrayLength(masm(), edx, ecx, &miss); | 3106 GenerateLoadArrayLength(masm(), edx, ecx, &miss); |
| 3093 __ bind(&miss); | 3107 __ bind(&miss); |
| 3094 __ DecrementCounter(counters->keyed_load_array_length(), 1); | 3108 __ DecrementCounter(counters->keyed_load_array_length(), 1); |
| 3095 GenerateLoadMiss(masm(), Code::KEYED_LOAD_IC); | 3109 GenerateLoadMiss(masm(), Code::KEYED_LOAD_IC); |
| 3096 | 3110 |
| 3097 // Return the generated code. | 3111 // Return the generated code. |
| 3098 return GetCode(CALLBACKS, name); | 3112 return GetCode(CALLBACKS, name); |
| 3099 } | 3113 } |
| 3100 | 3114 |
| 3101 | 3115 |
| 3102 MaybeObject* KeyedLoadStubCompiler::CompileLoadStringLength(String* name) { | 3116 MaybeObject* KeyedLoadStubCompiler::CompileLoadStringLength(String* name) { |
| 3103 // ----------- S t a t e ------------- | 3117 // ----------- S t a t e ------------- |
| 3104 // -- eax : key | 3118 // -- eax : key |
| 3105 // -- edx : receiver | 3119 // -- edx : receiver |
| 3106 // -- esp[0] : return address | 3120 // -- esp[0] : return address |
| 3107 // ----------------------------------- | 3121 // ----------------------------------- |
| 3108 Label miss; | 3122 Label miss; |
| 3109 | 3123 |
| 3110 Counters* counters = masm()->isolate()->counters(); | 3124 Counters* counters = isolate()->counters(); |
| 3111 __ IncrementCounter(counters->keyed_load_string_length(), 1); | 3125 __ IncrementCounter(counters->keyed_load_string_length(), 1); |
| 3112 | 3126 |
| 3113 // Check that the name has not changed. | 3127 // Check that the name has not changed. |
| 3114 __ cmp(Operand(eax), Immediate(Handle<String>(name))); | 3128 __ cmp(Operand(eax), Immediate(Handle<String>(name))); |
| 3115 __ j(not_equal, &miss, not_taken); | 3129 __ j(not_equal, &miss, not_taken); |
| 3116 | 3130 |
| 3117 GenerateLoadStringLength(masm(), edx, ecx, ebx, &miss, true); | 3131 GenerateLoadStringLength(masm(), edx, ecx, ebx, &miss, true); |
| 3118 __ bind(&miss); | 3132 __ bind(&miss); |
| 3119 __ DecrementCounter(counters->keyed_load_string_length(), 1); | 3133 __ DecrementCounter(counters->keyed_load_string_length(), 1); |
| 3120 GenerateLoadMiss(masm(), Code::KEYED_LOAD_IC); | 3134 GenerateLoadMiss(masm(), Code::KEYED_LOAD_IC); |
| 3121 | 3135 |
| 3122 // Return the generated code. | 3136 // Return the generated code. |
| 3123 return GetCode(CALLBACKS, name); | 3137 return GetCode(CALLBACKS, name); |
| 3124 } | 3138 } |
| 3125 | 3139 |
| 3126 | 3140 |
| 3127 MaybeObject* KeyedLoadStubCompiler::CompileLoadFunctionPrototype(String* name) { | 3141 MaybeObject* KeyedLoadStubCompiler::CompileLoadFunctionPrototype(String* name) { |
| 3128 // ----------- S t a t e ------------- | 3142 // ----------- S t a t e ------------- |
| 3129 // -- eax : key | 3143 // -- eax : key |
| 3130 // -- edx : receiver | 3144 // -- edx : receiver |
| 3131 // -- esp[0] : return address | 3145 // -- esp[0] : return address |
| 3132 // ----------------------------------- | 3146 // ----------------------------------- |
| 3133 Label miss; | 3147 Label miss; |
| 3134 | 3148 |
| 3135 Counters* counters = masm()->isolate()->counters(); | 3149 Counters* counters = isolate()->counters(); |
| 3136 __ IncrementCounter(counters->keyed_load_function_prototype(), 1); | 3150 __ IncrementCounter(counters->keyed_load_function_prototype(), 1); |
| 3137 | 3151 |
| 3138 // Check that the name has not changed. | 3152 // Check that the name has not changed. |
| 3139 __ cmp(Operand(eax), Immediate(Handle<String>(name))); | 3153 __ cmp(Operand(eax), Immediate(Handle<String>(name))); |
| 3140 __ j(not_equal, &miss, not_taken); | 3154 __ j(not_equal, &miss, not_taken); |
| 3141 | 3155 |
| 3142 GenerateLoadFunctionPrototype(masm(), edx, ecx, ebx, &miss); | 3156 GenerateLoadFunctionPrototype(masm(), edx, ecx, ebx, &miss); |
| 3143 __ bind(&miss); | 3157 __ bind(&miss); |
| 3144 __ DecrementCounter(counters->keyed_load_function_prototype(), 1); | 3158 __ DecrementCounter(counters->keyed_load_function_prototype(), 1); |
| 3145 GenerateLoadMiss(masm(), Code::KEYED_LOAD_IC); | 3159 GenerateLoadMiss(masm(), Code::KEYED_LOAD_IC); |
| (...skipping 128 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 3274 // depending on the this.x = ...; assignment in the function. | 3288 // depending on the this.x = ...; assignment in the function. |
| 3275 SharedFunctionInfo* shared = function->shared(); | 3289 SharedFunctionInfo* shared = function->shared(); |
| 3276 for (int i = 0; i < shared->this_property_assignments_count(); i++) { | 3290 for (int i = 0; i < shared->this_property_assignments_count(); i++) { |
| 3277 if (shared->IsThisPropertyAssignmentArgument(i)) { | 3291 if (shared->IsThisPropertyAssignmentArgument(i)) { |
| 3278 // Check if the argument assigned to the property is actually passed. | 3292 // Check if the argument assigned to the property is actually passed. |
| 3279 // If argument is not passed the property is set to undefined, | 3293 // If argument is not passed the property is set to undefined, |
| 3280 // otherwise find it on the stack. | 3294 // otherwise find it on the stack. |
| 3281 int arg_number = shared->GetThisPropertyAssignmentArgument(i); | 3295 int arg_number = shared->GetThisPropertyAssignmentArgument(i); |
| 3282 __ mov(ebx, edi); | 3296 __ mov(ebx, edi); |
| 3283 __ cmp(eax, arg_number); | 3297 __ cmp(eax, arg_number); |
| 3284 if (masm()->isolate()->cpu_features()->IsSupported(CMOV)) { | 3298 if (isolate()->cpu_features()->IsSupported(CMOV)) { |
| 3285 CpuFeatures::Scope use_cmov(CMOV); | 3299 CpuFeatures::Scope use_cmov(CMOV); |
| 3286 __ cmov(above, ebx, Operand(ecx, arg_number * -kPointerSize)); | 3300 __ cmov(above, ebx, Operand(ecx, arg_number * -kPointerSize)); |
| 3287 } else { | 3301 } else { |
| 3288 Label not_passed; | 3302 Label not_passed; |
| 3289 __ j(below_equal, ¬_passed); | 3303 __ j(below_equal, ¬_passed); |
| 3290 __ mov(ebx, Operand(ecx, arg_number * -kPointerSize)); | 3304 __ mov(ebx, Operand(ecx, arg_number * -kPointerSize)); |
| 3291 __ bind(¬_passed); | 3305 __ bind(¬_passed); |
| 3292 } | 3306 } |
| 3293 // Store value in the property. | 3307 // Store value in the property. |
| 3294 __ mov(Operand(edx, i * kPointerSize), ebx); | 3308 __ mov(Operand(edx, i * kPointerSize), ebx); |
| (...skipping 14 matching lines...) Expand all Loading... |
| 3309 | 3323 |
| 3310 // Move argc to ebx and retrieve and tag the JSObject to return. | 3324 // Move argc to ebx and retrieve and tag the JSObject to return. |
| 3311 __ mov(ebx, eax); | 3325 __ mov(ebx, eax); |
| 3312 __ pop(eax); | 3326 __ pop(eax); |
| 3313 __ or_(Operand(eax), Immediate(kHeapObjectTag)); | 3327 __ or_(Operand(eax), Immediate(kHeapObjectTag)); |
| 3314 | 3328 |
| 3315 // Remove caller arguments and receiver from the stack and return. | 3329 // Remove caller arguments and receiver from the stack and return. |
| 3316 __ pop(ecx); | 3330 __ pop(ecx); |
| 3317 __ lea(esp, Operand(esp, ebx, times_pointer_size, 1 * kPointerSize)); | 3331 __ lea(esp, Operand(esp, ebx, times_pointer_size, 1 * kPointerSize)); |
| 3318 __ push(ecx); | 3332 __ push(ecx); |
| 3319 Counters* counters = masm()->isolate()->counters(); | 3333 Counters* counters = isolate()->counters(); |
| 3320 __ IncrementCounter(counters->constructed_objects(), 1); | 3334 __ IncrementCounter(counters->constructed_objects(), 1); |
| 3321 __ IncrementCounter(counters->constructed_objects_stub(), 1); | 3335 __ IncrementCounter(counters->constructed_objects_stub(), 1); |
| 3322 __ ret(0); | 3336 __ ret(0); |
| 3323 | 3337 |
| 3324 // Jump to the generic stub in case the specialized code cannot handle the | 3338 // Jump to the generic stub in case the specialized code cannot handle the |
| 3325 // construction. | 3339 // construction. |
| 3326 __ bind(&generic_stub_call); | 3340 __ bind(&generic_stub_call); |
| 3327 Handle<Code> generic_construct_stub = | 3341 Handle<Code> generic_construct_stub = |
| 3328 masm()->isolate()->builtins()->JSConstructStubGeneric(); | 3342 isolate()->builtins()->JSConstructStubGeneric(); |
| 3329 __ jmp(generic_construct_stub, RelocInfo::CODE_TARGET); | 3343 __ jmp(generic_construct_stub, RelocInfo::CODE_TARGET); |
| 3330 | 3344 |
| 3331 // Return the generated code. | 3345 // Return the generated code. |
| 3332 return GetCode(); | 3346 return GetCode(); |
| 3333 } | 3347 } |
| 3334 | 3348 |
| 3335 | 3349 |
| 3336 MaybeObject* ExternalArrayStubCompiler::CompileKeyedLoadStub( | 3350 MaybeObject* ExternalArrayStubCompiler::CompileKeyedLoadStub( |
| 3337 JSObject*receiver, ExternalArrayType array_type, Code::Flags flags) { | 3351 JSObject*receiver, ExternalArrayType array_type, Code::Flags flags) { |
| 3338 // ----------- S t a t e ------------- | 3352 // ----------- S t a t e ------------- |
| (...skipping 119 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 3458 | 3472 |
| 3459 // If we fail allocation of the HeapNumber, we still have a value on | 3473 // If we fail allocation of the HeapNumber, we still have a value on |
| 3460 // top of the FPU stack. Remove it. | 3474 // top of the FPU stack. Remove it. |
| 3461 __ bind(&failed_allocation); | 3475 __ bind(&failed_allocation); |
| 3462 __ ffree(); | 3476 __ ffree(); |
| 3463 __ fincstp(); | 3477 __ fincstp(); |
| 3464 // Fall through to slow case. | 3478 // Fall through to slow case. |
| 3465 | 3479 |
| 3466 // Slow case: Jump to runtime. | 3480 // Slow case: Jump to runtime. |
| 3467 __ bind(&slow); | 3481 __ bind(&slow); |
| 3468 Counters* counters = masm()->isolate()->counters(); | 3482 Counters* counters = isolate()->counters(); |
| 3469 __ IncrementCounter(counters->keyed_load_external_array_slow(), 1); | 3483 __ IncrementCounter(counters->keyed_load_external_array_slow(), 1); |
| 3470 // ----------- S t a t e ------------- | 3484 // ----------- S t a t e ------------- |
| 3471 // -- eax : key | 3485 // -- eax : key |
| 3472 // -- edx : receiver | 3486 // -- edx : receiver |
| 3473 // -- esp[0] : return address | 3487 // -- esp[0] : return address |
| 3474 // ----------------------------------- | 3488 // ----------------------------------- |
| 3475 | 3489 |
| 3476 __ pop(ebx); | 3490 __ pop(ebx); |
| 3477 __ push(edx); // receiver | 3491 __ push(edx); // receiver |
| 3478 __ push(eax); // name | 3492 __ push(eax); // name |
| (...skipping 114 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 3593 __ fstp_s(Operand(edi, ebx, times_4, 0)); | 3607 __ fstp_s(Operand(edi, ebx, times_4, 0)); |
| 3594 __ ret(0); | 3608 __ ret(0); |
| 3595 } else { | 3609 } else { |
| 3596 // Perform float-to-int conversion with truncation (round-to-zero) | 3610 // Perform float-to-int conversion with truncation (round-to-zero) |
| 3597 // behavior. | 3611 // behavior. |
| 3598 | 3612 |
| 3599 // For the moment we make the slow call to the runtime on | 3613 // For the moment we make the slow call to the runtime on |
| 3600 // processors that don't support SSE2. The code in IntegerConvert | 3614 // processors that don't support SSE2. The code in IntegerConvert |
| 3601 // (code-stubs-ia32.cc) is roughly what is needed here though the | 3615 // (code-stubs-ia32.cc) is roughly what is needed here though the |
| 3602 // conversion failure case does not need to be handled. | 3616 // conversion failure case does not need to be handled. |
| 3603 if (masm()->isolate()->cpu_features()->IsSupported(SSE2)) { | 3617 if (isolate()->cpu_features()->IsSupported(SSE2)) { |
| 3604 if (array_type != kExternalIntArray && | 3618 if (array_type != kExternalIntArray && |
| 3605 array_type != kExternalUnsignedIntArray) { | 3619 array_type != kExternalUnsignedIntArray) { |
| 3606 ASSERT(masm()->isolate()->cpu_features()->IsSupported(SSE2)); | 3620 ASSERT(isolate()->cpu_features()->IsSupported(SSE2)); |
| 3607 CpuFeatures::Scope scope(SSE2); | 3621 CpuFeatures::Scope scope(SSE2); |
| 3608 __ cvttsd2si(ecx, FieldOperand(eax, HeapNumber::kValueOffset)); | 3622 __ cvttsd2si(ecx, FieldOperand(eax, HeapNumber::kValueOffset)); |
| 3609 // ecx: untagged integer value | 3623 // ecx: untagged integer value |
| 3610 switch (array_type) { | 3624 switch (array_type) { |
| 3611 case kExternalPixelArray: | 3625 case kExternalPixelArray: |
| 3612 { // Clamp the value to [0..255]. | 3626 { // Clamp the value to [0..255]. |
| 3613 NearLabel done; | 3627 NearLabel done; |
| 3614 __ test(ecx, Immediate(0xFFFFFF00)); | 3628 __ test(ecx, Immediate(0xFFFFFF00)); |
| 3615 __ j(zero, &done); | 3629 __ j(zero, &done); |
| 3616 __ setcc(negative, ecx); // 1 if negative, 0 if positive. | 3630 __ setcc(negative, ecx); // 1 if negative, 0 if positive. |
| 3617 __ dec_b(ecx); // 0 if negative, 255 if positive. | 3631 __ dec_b(ecx); // 0 if negative, 255 if positive. |
| 3618 __ bind(&done); | 3632 __ bind(&done); |
| 3619 } | 3633 } |
| 3620 __ mov_b(Operand(edi, ebx, times_1, 0), ecx); | 3634 __ mov_b(Operand(edi, ebx, times_1, 0), ecx); |
| 3621 case kExternalByteArray: | 3635 case kExternalByteArray: |
| 3622 case kExternalUnsignedByteArray: | 3636 case kExternalUnsignedByteArray: |
| 3623 __ mov_b(Operand(edi, ebx, times_1, 0), ecx); | 3637 __ mov_b(Operand(edi, ebx, times_1, 0), ecx); |
| 3624 break; | 3638 break; |
| 3625 case kExternalShortArray: | 3639 case kExternalShortArray: |
| 3626 case kExternalUnsignedShortArray: | 3640 case kExternalUnsignedShortArray: |
| 3627 __ mov_w(Operand(edi, ebx, times_2, 0), ecx); | 3641 __ mov_w(Operand(edi, ebx, times_2, 0), ecx); |
| 3628 break; | 3642 break; |
| 3629 default: | 3643 default: |
| 3630 UNREACHABLE(); | 3644 UNREACHABLE(); |
| 3631 break; | 3645 break; |
| 3632 } | 3646 } |
| 3633 } else { | 3647 } else { |
| 3634 if (masm()->isolate()->cpu_features()->IsSupported(SSE3)) { | 3648 if (isolate()->cpu_features()->IsSupported(SSE3)) { |
| 3635 CpuFeatures::Scope scope(SSE3); | 3649 CpuFeatures::Scope scope(SSE3); |
| 3636 // fisttp stores values as signed integers. To represent the | 3650 // fisttp stores values as signed integers. To represent the |
| 3637 // entire range of int and unsigned int arrays, store as a | 3651 // entire range of int and unsigned int arrays, store as a |
| 3638 // 64-bit int and discard the high 32 bits. | 3652 // 64-bit int and discard the high 32 bits. |
| 3639 // If the value is NaN or +/-infinity, the result is 0x80000000, | 3653 // If the value is NaN or +/-infinity, the result is 0x80000000, |
| 3640 // which is automatically zero when taken mod 2^n, n < 32. | 3654 // which is automatically zero when taken mod 2^n, n < 32. |
| 3641 __ fld_d(FieldOperand(eax, HeapNumber::kValueOffset)); | 3655 __ fld_d(FieldOperand(eax, HeapNumber::kValueOffset)); |
| 3642 __ sub(Operand(esp), Immediate(2 * kPointerSize)); | 3656 __ sub(Operand(esp), Immediate(2 * kPointerSize)); |
| 3643 __ fisttp_d(Operand(esp, 0)); | 3657 __ fisttp_d(Operand(esp, 0)); |
| 3644 __ pop(ecx); | 3658 __ pop(ecx); |
| 3645 __ add(Operand(esp), Immediate(kPointerSize)); | 3659 __ add(Operand(esp), Immediate(kPointerSize)); |
| 3646 } else { | 3660 } else { |
| 3647 ASSERT(masm()->isolate()->cpu_features()->IsSupported(SSE2)); | 3661 ASSERT(isolate()->cpu_features()->IsSupported(SSE2)); |
| 3648 CpuFeatures::Scope scope(SSE2); | 3662 CpuFeatures::Scope scope(SSE2); |
| 3649 // We can easily implement the correct rounding behavior for the | 3663 // We can easily implement the correct rounding behavior for the |
| 3650 // range [0, 2^31-1]. For the time being, to keep this code simple, | 3664 // range [0, 2^31-1]. For the time being, to keep this code simple, |
| 3651 // make the slow runtime call for values outside this range. | 3665 // make the slow runtime call for values outside this range. |
| 3652 // Note: we could do better for signed int arrays. | 3666 // Note: we could do better for signed int arrays. |
| 3653 __ movd(xmm0, FieldOperand(eax, HeapNumber::kValueOffset)); | 3667 __ movd(xmm0, FieldOperand(eax, HeapNumber::kValueOffset)); |
| 3654 // We will need the key if we have to make the slow runtime call. | 3668 // We will need the key if we have to make the slow runtime call. |
| 3655 __ push(ecx); | 3669 __ push(ecx); |
| 3656 __ LoadPowerOf2(xmm1, ecx, 31); | 3670 __ LoadPowerOf2(xmm1, ecx, 31); |
| 3657 __ pop(ecx); | 3671 __ pop(ecx); |
| (...skipping 32 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 3690 | 3704 |
| 3691 return GetCode(flags); | 3705 return GetCode(flags); |
| 3692 } | 3706 } |
| 3693 | 3707 |
| 3694 | 3708 |
| 3695 #undef __ | 3709 #undef __ |
| 3696 | 3710 |
| 3697 } } // namespace v8::internal | 3711 } } // namespace v8::internal |
| 3698 | 3712 |
| 3699 #endif // V8_TARGET_ARCH_IA32 | 3713 #endif // V8_TARGET_ARCH_IA32 |
| OLD | NEW |