| 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 48 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 59 __ cmp(name, Operand::StaticArray(offset, times_2, key_offset)); | 59 __ cmp(name, Operand::StaticArray(offset, times_2, key_offset)); |
| 60 __ j(not_equal, &miss); | 60 __ j(not_equal, &miss); |
| 61 | 61 |
| 62 // Check that the flags match what we're looking for. | 62 // Check that the flags match what we're looking for. |
| 63 __ mov(offset, FieldOperand(extra, Code::kFlagsOffset)); | 63 __ mov(offset, FieldOperand(extra, Code::kFlagsOffset)); |
| 64 __ and_(offset, ~Code::kFlagsNotUsedInLookup); | 64 __ and_(offset, ~Code::kFlagsNotUsedInLookup); |
| 65 __ cmp(offset, flags); | 65 __ cmp(offset, flags); |
| 66 __ j(not_equal, &miss); | 66 __ j(not_equal, &miss); |
| 67 | 67 |
| 68 // Jump to the first instruction in the code stub. | 68 // Jump to the first instruction in the code stub. |
| 69 __ add(Operand(extra), Immediate(Code::kHeaderSize - kHeapObjectTag)); | 69 __ add(extra, Immediate(Code::kHeaderSize - kHeapObjectTag)); |
| 70 __ jmp(Operand(extra)); | 70 __ jmp(extra); |
| 71 | 71 |
| 72 __ bind(&miss); | 72 __ bind(&miss); |
| 73 } else { | 73 } else { |
| 74 // Save the offset on the stack. | 74 // Save the offset on the stack. |
| 75 __ push(offset); | 75 __ push(offset); |
| 76 | 76 |
| 77 // Check that the key in the entry matches the name. | 77 // Check that the key in the entry matches the name. |
| 78 __ cmp(name, Operand::StaticArray(offset, times_2, key_offset)); | 78 __ cmp(name, Operand::StaticArray(offset, times_2, key_offset)); |
| 79 __ j(not_equal, &miss); | 79 __ j(not_equal, &miss); |
| 80 | 80 |
| 81 // Get the code entry from the cache. | 81 // Get the code entry from the cache. |
| 82 __ mov(offset, Operand::StaticArray(offset, times_2, value_offset)); | 82 __ mov(offset, Operand::StaticArray(offset, times_2, value_offset)); |
| 83 | 83 |
| 84 // Check that the flags match what we're looking for. | 84 // Check that the flags match what we're looking for. |
| 85 __ mov(offset, FieldOperand(offset, Code::kFlagsOffset)); | 85 __ mov(offset, FieldOperand(offset, Code::kFlagsOffset)); |
| 86 __ and_(offset, ~Code::kFlagsNotUsedInLookup); | 86 __ and_(offset, ~Code::kFlagsNotUsedInLookup); |
| 87 __ cmp(offset, flags); | 87 __ cmp(offset, flags); |
| 88 __ j(not_equal, &miss); | 88 __ j(not_equal, &miss); |
| 89 | 89 |
| 90 // Restore offset and re-load code entry from cache. | 90 // Restore offset and re-load code entry from cache. |
| 91 __ pop(offset); | 91 __ pop(offset); |
| 92 __ mov(offset, Operand::StaticArray(offset, times_2, value_offset)); | 92 __ mov(offset, Operand::StaticArray(offset, times_2, value_offset)); |
| 93 | 93 |
| 94 // Jump to the first instruction in the code stub. | 94 // Jump to the first instruction in the code stub. |
| 95 __ add(Operand(offset), Immediate(Code::kHeaderSize - kHeapObjectTag)); | 95 __ add(offset, Immediate(Code::kHeaderSize - kHeapObjectTag)); |
| 96 __ jmp(Operand(offset)); | 96 __ jmp(offset); |
| 97 | 97 |
| 98 // Pop at miss. | 98 // Pop at miss. |
| 99 __ bind(&miss); | 99 __ bind(&miss); |
| 100 __ pop(offset); | 100 __ pop(offset); |
| 101 } | 101 } |
| 102 } | 102 } |
| 103 | 103 |
| 104 | 104 |
| 105 // Helper function used to check that the dictionary doesn't contain | 105 // Helper function used to check that the dictionary doesn't contain |
| 106 // the property. This function may return false negatives, so miss_label | 106 // the property. This function may return false negatives, so miss_label |
| (...skipping 90 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 197 __ and_(scratch, (kPrimaryTableSize - 1) << kHeapObjectTagSize); | 197 __ and_(scratch, (kPrimaryTableSize - 1) << kHeapObjectTagSize); |
| 198 | 198 |
| 199 // Probe the primary table. | 199 // Probe the primary table. |
| 200 ProbeTable(isolate, masm, flags, kPrimary, name, scratch, extra); | 200 ProbeTable(isolate, masm, flags, kPrimary, name, scratch, extra); |
| 201 | 201 |
| 202 // Primary miss: Compute hash for secondary probe. | 202 // Primary miss: Compute hash for secondary probe. |
| 203 __ mov(scratch, FieldOperand(name, String::kHashFieldOffset)); | 203 __ mov(scratch, FieldOperand(name, String::kHashFieldOffset)); |
| 204 __ add(scratch, FieldOperand(receiver, HeapObject::kMapOffset)); | 204 __ add(scratch, FieldOperand(receiver, HeapObject::kMapOffset)); |
| 205 __ xor_(scratch, flags); | 205 __ xor_(scratch, flags); |
| 206 __ and_(scratch, (kPrimaryTableSize - 1) << kHeapObjectTagSize); | 206 __ and_(scratch, (kPrimaryTableSize - 1) << kHeapObjectTagSize); |
| 207 __ sub(scratch, Operand(name)); | 207 __ sub(scratch, name); |
| 208 __ add(Operand(scratch), Immediate(flags)); | 208 __ add(scratch, Immediate(flags)); |
| 209 __ and_(scratch, (kSecondaryTableSize - 1) << kHeapObjectTagSize); | 209 __ and_(scratch, (kSecondaryTableSize - 1) << kHeapObjectTagSize); |
| 210 | 210 |
| 211 // Probe the secondary table. | 211 // Probe the secondary table. |
| 212 ProbeTable(isolate, masm, flags, kSecondary, name, scratch, extra); | 212 ProbeTable(isolate, masm, flags, kSecondary, name, scratch, extra); |
| 213 | 213 |
| 214 // Cache miss: Fall-through and let caller handle the miss by | 214 // Cache miss: Fall-through and let caller handle the miss by |
| 215 // entering the runtime system. | 215 // entering the runtime system. |
| 216 __ bind(&miss); | 216 __ bind(&miss); |
| 217 } | 217 } |
| 218 | 218 |
| (...skipping 92 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 311 } | 311 } |
| 312 } | 312 } |
| 313 | 313 |
| 314 | 314 |
| 315 void StubCompiler::GenerateLoadFunctionPrototype(MacroAssembler* masm, | 315 void StubCompiler::GenerateLoadFunctionPrototype(MacroAssembler* masm, |
| 316 Register receiver, | 316 Register receiver, |
| 317 Register scratch1, | 317 Register scratch1, |
| 318 Register scratch2, | 318 Register scratch2, |
| 319 Label* miss_label) { | 319 Label* miss_label) { |
| 320 __ TryGetFunctionPrototype(receiver, scratch1, scratch2, miss_label); | 320 __ TryGetFunctionPrototype(receiver, scratch1, scratch2, miss_label); |
| 321 __ mov(eax, Operand(scratch1)); | 321 __ mov(eax, scratch1); |
| 322 __ ret(0); | 322 __ ret(0); |
| 323 } | 323 } |
| 324 | 324 |
| 325 | 325 |
| 326 // Load a fast property out of a holder object (src). In-object properties | 326 // Load a fast property out of a holder object (src). In-object properties |
| 327 // are loaded directly otherwise the property is loaded from the properties | 327 // are loaded directly otherwise the property is loaded from the properties |
| 328 // fixed array. | 328 // fixed array. |
| 329 void StubCompiler::GenerateFastPropertyLoad(MacroAssembler* masm, | 329 void StubCompiler::GenerateFastPropertyLoad(MacroAssembler* masm, |
| 330 Register dst, Register src, | 330 Register dst, Register src, |
| 331 JSObject* holder, int index) { | 331 JSObject* holder, int index) { |
| (...skipping 67 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 399 static void FreeSpaceForFastApiCall(MacroAssembler* masm, Register scratch) { | 399 static void FreeSpaceForFastApiCall(MacroAssembler* masm, Register scratch) { |
| 400 // ----------- S t a t e ------------- | 400 // ----------- S t a t e ------------- |
| 401 // -- esp[0] : return address. | 401 // -- esp[0] : return address. |
| 402 // -- esp[4] : last fast api call extra argument. | 402 // -- esp[4] : last fast api call extra argument. |
| 403 // -- ... | 403 // -- ... |
| 404 // -- esp[kFastApiCallArguments * 4] : first fast api call extra argument. | 404 // -- esp[kFastApiCallArguments * 4] : first fast api call extra argument. |
| 405 // -- esp[kFastApiCallArguments * 4 + 4] : last argument in the internal | 405 // -- esp[kFastApiCallArguments * 4 + 4] : last argument in the internal |
| 406 // frame. | 406 // frame. |
| 407 // ----------------------------------- | 407 // ----------------------------------- |
| 408 __ pop(scratch); | 408 __ pop(scratch); |
| 409 __ add(Operand(esp), Immediate(kPointerSize * kFastApiCallArguments)); | 409 __ add(esp, Immediate(kPointerSize * kFastApiCallArguments)); |
| 410 __ push(scratch); | 410 __ push(scratch); |
| 411 } | 411 } |
| 412 | 412 |
| 413 | 413 |
| 414 // Generates call to API function. | 414 // Generates call to API function. |
| 415 static MaybeObject* GenerateFastApiCall(MacroAssembler* masm, | 415 static MaybeObject* GenerateFastApiCall(MacroAssembler* masm, |
| 416 const CallOptimization& optimization, | 416 const CallOptimization& optimization, |
| 417 int argc) { | 417 int argc) { |
| 418 // ----------- S t a t e ------------- | 418 // ----------- S t a t e ------------- |
| 419 // -- esp[0] : return address | 419 // -- esp[0] : return address |
| (...skipping 35 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 455 | 455 |
| 456 const int kApiArgc = 1; // API function gets reference to the v8::Arguments. | 456 const int kApiArgc = 1; // API function gets reference to the v8::Arguments. |
| 457 | 457 |
| 458 // Allocate the v8::Arguments structure in the arguments' space since | 458 // Allocate the v8::Arguments structure in the arguments' space since |
| 459 // it's not controlled by GC. | 459 // it's not controlled by GC. |
| 460 const int kApiStackSpace = 4; | 460 const int kApiStackSpace = 4; |
| 461 | 461 |
| 462 __ PrepareCallApiFunction(kApiArgc + kApiStackSpace); | 462 __ PrepareCallApiFunction(kApiArgc + kApiStackSpace); |
| 463 | 463 |
| 464 __ mov(ApiParameterOperand(1), eax); // v8::Arguments::implicit_args_. | 464 __ mov(ApiParameterOperand(1), eax); // v8::Arguments::implicit_args_. |
| 465 __ add(Operand(eax), Immediate(argc * kPointerSize)); | 465 __ add(eax, Immediate(argc * kPointerSize)); |
| 466 __ mov(ApiParameterOperand(2), eax); // v8::Arguments::values_. | 466 __ mov(ApiParameterOperand(2), eax); // v8::Arguments::values_. |
| 467 __ Set(ApiParameterOperand(3), Immediate(argc)); // v8::Arguments::length_. | 467 __ Set(ApiParameterOperand(3), Immediate(argc)); // v8::Arguments::length_. |
| 468 // v8::Arguments::is_construct_call_. | 468 // v8::Arguments::is_construct_call_. |
| 469 __ Set(ApiParameterOperand(4), Immediate(0)); | 469 __ Set(ApiParameterOperand(4), Immediate(0)); |
| 470 | 470 |
| 471 // v8::InvocationCallback's argument. | 471 // v8::InvocationCallback's argument. |
| 472 __ lea(eax, ApiParameterOperand(1)); | 472 __ lea(eax, ApiParameterOperand(1)); |
| 473 __ mov(ApiParameterOperand(0), eax); | 473 __ mov(ApiParameterOperand(0), eax); |
| 474 | 474 |
| 475 // Emitting a stub call may try to allocate (if the code is not | 475 // Emitting a stub call may try to allocate (if the code is not |
| (...skipping 306 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 782 // object and the number of in-object properties is not going to change. | 782 // object and the number of in-object properties is not going to change. |
| 783 index -= object->map()->inobject_properties(); | 783 index -= object->map()->inobject_properties(); |
| 784 | 784 |
| 785 if (index < 0) { | 785 if (index < 0) { |
| 786 // Set the property straight into the object. | 786 // Set the property straight into the object. |
| 787 int offset = object->map()->instance_size() + (index * kPointerSize); | 787 int offset = object->map()->instance_size() + (index * kPointerSize); |
| 788 __ mov(FieldOperand(receiver_reg, offset), eax); | 788 __ mov(FieldOperand(receiver_reg, offset), eax); |
| 789 | 789 |
| 790 // Update the write barrier for the array address. | 790 // Update the write barrier for the array address. |
| 791 // Pass the value being stored in the now unused name_reg. | 791 // Pass the value being stored in the now unused name_reg. |
| 792 __ mov(name_reg, Operand(eax)); | 792 __ mov(name_reg, eax); |
| 793 __ RecordWriteField(receiver_reg, | 793 __ RecordWriteField(receiver_reg, |
| 794 offset, | 794 offset, |
| 795 name_reg, | 795 name_reg, |
| 796 scratch, | 796 scratch, |
| 797 kDontSaveFPRegs); | 797 kDontSaveFPRegs); |
| 798 } else { | 798 } else { |
| 799 // Write to the properties array. | 799 // Write to the properties array. |
| 800 int offset = index * kPointerSize + FixedArray::kHeaderSize; | 800 int offset = index * kPointerSize + FixedArray::kHeaderSize; |
| 801 // Get the properties array (optimistically). | 801 // Get the properties array (optimistically). |
| 802 __ mov(scratch, FieldOperand(receiver_reg, JSObject::kPropertiesOffset)); | 802 __ mov(scratch, FieldOperand(receiver_reg, JSObject::kPropertiesOffset)); |
| 803 __ mov(FieldOperand(scratch, offset), eax); | 803 __ mov(FieldOperand(scratch, offset), eax); |
| 804 | 804 |
| 805 // Update the write barrier for the array address. | 805 // Update the write barrier for the array address. |
| 806 // Pass the value being stored in the now unused name_reg. | 806 // Pass the value being stored in the now unused name_reg. |
| 807 __ mov(name_reg, Operand(eax)); | 807 __ mov(name_reg, eax); |
| 808 __ RecordWriteField(scratch, | 808 __ RecordWriteField(scratch, |
| 809 offset, | 809 offset, |
| 810 name_reg, | 810 name_reg, |
| 811 receiver_reg, | 811 receiver_reg, |
| 812 kDontSaveFPRegs); | 812 kDontSaveFPRegs); |
| 813 } | 813 } |
| 814 | 814 |
| 815 // Return the value (register eax). | 815 // Return the value (register eax). |
| 816 __ ret(0); | 816 __ ret(0); |
| 817 } | 817 } |
| (...skipping 118 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 936 set_failure(Failure::cast(negative_lookup)); | 936 set_failure(Failure::cast(negative_lookup)); |
| 937 return reg; | 937 return reg; |
| 938 } | 938 } |
| 939 | 939 |
| 940 __ mov(scratch1, FieldOperand(reg, HeapObject::kMapOffset)); | 940 __ mov(scratch1, FieldOperand(reg, HeapObject::kMapOffset)); |
| 941 reg = holder_reg; // from now the object is in holder_reg | 941 reg = holder_reg; // from now the object is in holder_reg |
| 942 __ mov(reg, FieldOperand(scratch1, Map::kPrototypeOffset)); | 942 __ mov(reg, FieldOperand(scratch1, Map::kPrototypeOffset)); |
| 943 } else if (heap()->InNewSpace(prototype)) { | 943 } else if (heap()->InNewSpace(prototype)) { |
| 944 // Get the map of the current object. | 944 // Get the map of the current object. |
| 945 __ mov(scratch1, FieldOperand(reg, HeapObject::kMapOffset)); | 945 __ mov(scratch1, FieldOperand(reg, HeapObject::kMapOffset)); |
| 946 __ cmp(Operand(scratch1), Immediate(Handle<Map>(current->map()))); | 946 __ cmp(scratch1, Immediate(Handle<Map>(current->map()))); |
| 947 // Branch on the result of the map check. | 947 // Branch on the result of the map check. |
| 948 __ j(not_equal, miss); | 948 __ j(not_equal, miss); |
| 949 // Check access rights to the global object. This has to happen | 949 // Check access rights to the global object. This has to happen |
| 950 // after the map check so that we know that the object is | 950 // after the map check so that we know that the object is |
| 951 // actually a global object. | 951 // actually a global object. |
| 952 if (current->IsJSGlobalProxy()) { | 952 if (current->IsJSGlobalProxy()) { |
| 953 __ CheckAccessGlobalProxy(reg, scratch1, miss); | 953 __ CheckAccessGlobalProxy(reg, scratch1, miss); |
| 954 | 954 |
| 955 // Restore scratch register to be the map of the object. | 955 // Restore scratch register to be the map of the object. |
| 956 // We load the prototype from the map in the scratch register. | 956 // We load the prototype from the map in the scratch register. |
| (...skipping 100 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1057 CheckPrototypes(object, receiver, holder, scratch1, | 1057 CheckPrototypes(object, receiver, holder, scratch1, |
| 1058 scratch2, scratch3, name, miss); | 1058 scratch2, scratch3, name, miss); |
| 1059 | 1059 |
| 1060 Handle<AccessorInfo> callback_handle(callback); | 1060 Handle<AccessorInfo> callback_handle(callback); |
| 1061 | 1061 |
| 1062 // Insert additional parameters into the stack frame above return address. | 1062 // Insert additional parameters into the stack frame above return address. |
| 1063 ASSERT(!scratch3.is(reg)); | 1063 ASSERT(!scratch3.is(reg)); |
| 1064 __ pop(scratch3); // Get return address to place it below. | 1064 __ pop(scratch3); // Get return address to place it below. |
| 1065 | 1065 |
| 1066 __ push(receiver); // receiver | 1066 __ push(receiver); // receiver |
| 1067 __ mov(scratch2, Operand(esp)); | 1067 __ mov(scratch2, esp); |
| 1068 ASSERT(!scratch2.is(reg)); | 1068 ASSERT(!scratch2.is(reg)); |
| 1069 __ push(reg); // holder | 1069 __ push(reg); // holder |
| 1070 // Push data from AccessorInfo. | 1070 // Push data from AccessorInfo. |
| 1071 if (isolate()->heap()->InNewSpace(callback_handle->data())) { | 1071 if (isolate()->heap()->InNewSpace(callback_handle->data())) { |
| 1072 __ mov(scratch1, Immediate(callback_handle)); | 1072 __ mov(scratch1, Immediate(callback_handle)); |
| 1073 __ push(FieldOperand(scratch1, AccessorInfo::kDataOffset)); | 1073 __ push(FieldOperand(scratch1, AccessorInfo::kDataOffset)); |
| 1074 } else { | 1074 } else { |
| 1075 __ push(Immediate(Handle<Object>(callback_handle->data()))); | 1075 __ push(Immediate(Handle<Object>(callback_handle->data()))); |
| 1076 } | 1076 } |
| 1077 | 1077 |
| (...skipping 10 matching lines...) Expand all Loading... |
| 1088 Address getter_address = v8::ToCData<Address>(callback->getter()); | 1088 Address getter_address = v8::ToCData<Address>(callback->getter()); |
| 1089 ApiFunction fun(getter_address); | 1089 ApiFunction fun(getter_address); |
| 1090 | 1090 |
| 1091 // 3 elements array for v8::Agruments::values_, handler for name and pointer | 1091 // 3 elements array for v8::Agruments::values_, handler for name and pointer |
| 1092 // to the values (it considered as smi in GC). | 1092 // to the values (it considered as smi in GC). |
| 1093 const int kStackSpace = 5; | 1093 const int kStackSpace = 5; |
| 1094 const int kApiArgc = 2; | 1094 const int kApiArgc = 2; |
| 1095 | 1095 |
| 1096 __ PrepareCallApiFunction(kApiArgc); | 1096 __ PrepareCallApiFunction(kApiArgc); |
| 1097 __ mov(ApiParameterOperand(0), ebx); // name. | 1097 __ mov(ApiParameterOperand(0), ebx); // name. |
| 1098 __ add(Operand(ebx), Immediate(kPointerSize)); | 1098 __ add(ebx, Immediate(kPointerSize)); |
| 1099 __ mov(ApiParameterOperand(1), ebx); // arguments pointer. | 1099 __ mov(ApiParameterOperand(1), ebx); // arguments pointer. |
| 1100 | 1100 |
| 1101 // Emitting a stub call may try to allocate (if the code is not | 1101 // Emitting a stub call may try to allocate (if the code is not |
| 1102 // already generated). Do not allow the assembler to perform a | 1102 // already generated). Do not allow the assembler to perform a |
| 1103 // garbage collection but instead return the allocation failure | 1103 // garbage collection but instead return the allocation failure |
| 1104 // object. | 1104 // object. |
| 1105 return masm()->TryCallApiFunctionAndReturn(&fun, kStackSpace); | 1105 return masm()->TryCallApiFunctionAndReturn(&fun, kStackSpace); |
| 1106 } | 1106 } |
| 1107 | 1107 |
| 1108 | 1108 |
| (...skipping 156 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1265 ExternalReference ref = | 1265 ExternalReference ref = |
| 1266 ExternalReference(IC_Utility(IC::kLoadPropertyWithInterceptorForLoad), | 1266 ExternalReference(IC_Utility(IC::kLoadPropertyWithInterceptorForLoad), |
| 1267 isolate()); | 1267 isolate()); |
| 1268 __ TailCallExternalReference(ref, 5, 1); | 1268 __ TailCallExternalReference(ref, 5, 1); |
| 1269 } | 1269 } |
| 1270 } | 1270 } |
| 1271 | 1271 |
| 1272 | 1272 |
| 1273 void CallStubCompiler::GenerateNameCheck(String* name, Label* miss) { | 1273 void CallStubCompiler::GenerateNameCheck(String* name, Label* miss) { |
| 1274 if (kind_ == Code::KEYED_CALL_IC) { | 1274 if (kind_ == Code::KEYED_CALL_IC) { |
| 1275 __ cmp(Operand(ecx), Immediate(Handle<String>(name))); | 1275 __ cmp(ecx, Immediate(Handle<String>(name))); |
| 1276 __ j(not_equal, miss); | 1276 __ j(not_equal, miss); |
| 1277 } | 1277 } |
| 1278 } | 1278 } |
| 1279 | 1279 |
| 1280 | 1280 |
| 1281 void CallStubCompiler::GenerateGlobalReceiverCheck(JSObject* object, | 1281 void CallStubCompiler::GenerateGlobalReceiverCheck(JSObject* object, |
| 1282 JSObject* holder, | 1282 JSObject* holder, |
| 1283 String* name, | 1283 String* name, |
| 1284 Label* miss) { | 1284 Label* miss) { |
| 1285 ASSERT(holder->IsGlobalObject()); | 1285 ASSERT(holder->IsGlobalObject()); |
| (...skipping 36 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1322 // function, we have to verify that it still is a function. | 1322 // function, we have to verify that it still is a function. |
| 1323 __ JumpIfSmi(edi, miss); | 1323 __ JumpIfSmi(edi, miss); |
| 1324 __ CmpObjectType(edi, JS_FUNCTION_TYPE, ebx); | 1324 __ CmpObjectType(edi, JS_FUNCTION_TYPE, ebx); |
| 1325 __ j(not_equal, miss); | 1325 __ j(not_equal, miss); |
| 1326 | 1326 |
| 1327 // Check the shared function info. Make sure it hasn't changed. | 1327 // Check the shared function info. Make sure it hasn't changed. |
| 1328 __ cmp(FieldOperand(edi, JSFunction::kSharedFunctionInfoOffset), | 1328 __ cmp(FieldOperand(edi, JSFunction::kSharedFunctionInfoOffset), |
| 1329 Immediate(Handle<SharedFunctionInfo>(function->shared()))); | 1329 Immediate(Handle<SharedFunctionInfo>(function->shared()))); |
| 1330 __ j(not_equal, miss); | 1330 __ j(not_equal, miss); |
| 1331 } else { | 1331 } else { |
| 1332 __ cmp(Operand(edi), Immediate(Handle<JSFunction>(function))); | 1332 __ cmp(edi, Immediate(Handle<JSFunction>(function))); |
| 1333 __ j(not_equal, miss); | 1333 __ j(not_equal, miss); |
| 1334 } | 1334 } |
| 1335 } | 1335 } |
| 1336 | 1336 |
| 1337 | 1337 |
| 1338 MaybeObject* CallStubCompiler::GenerateMissBranch() { | 1338 MaybeObject* CallStubCompiler::GenerateMissBranch() { |
| 1339 MaybeObject* maybe_obj = | 1339 MaybeObject* maybe_obj = |
| 1340 isolate()->stub_cache()->ComputeCallMiss(arguments().immediate(), | 1340 isolate()->stub_cache()->ComputeCallMiss(arguments().immediate(), |
| 1341 kind_, | 1341 kind_, |
| 1342 extra_ic_state_); | 1342 extra_ic_state_); |
| (...skipping 110 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1453 Immediate(factory()->fixed_array_map())); | 1453 Immediate(factory()->fixed_array_map())); |
| 1454 __ j(not_equal, &call_builtin); | 1454 __ j(not_equal, &call_builtin); |
| 1455 | 1455 |
| 1456 if (argc == 1) { // Otherwise fall through to call builtin. | 1456 if (argc == 1) { // Otherwise fall through to call builtin. |
| 1457 Label attempt_to_grow_elements, with_write_barrier; | 1457 Label attempt_to_grow_elements, with_write_barrier; |
| 1458 | 1458 |
| 1459 // Get the array's length into eax and calculate new length. | 1459 // Get the array's length into eax and calculate new length. |
| 1460 __ mov(eax, FieldOperand(edx, JSArray::kLengthOffset)); | 1460 __ mov(eax, FieldOperand(edx, JSArray::kLengthOffset)); |
| 1461 STATIC_ASSERT(kSmiTagSize == 1); | 1461 STATIC_ASSERT(kSmiTagSize == 1); |
| 1462 STATIC_ASSERT(kSmiTag == 0); | 1462 STATIC_ASSERT(kSmiTag == 0); |
| 1463 __ add(Operand(eax), Immediate(Smi::FromInt(argc))); | 1463 __ add(eax, Immediate(Smi::FromInt(argc))); |
| 1464 | 1464 |
| 1465 // Get the element's length into ecx. | 1465 // Get the element's length into ecx. |
| 1466 __ mov(ecx, FieldOperand(ebx, FixedArray::kLengthOffset)); | 1466 __ mov(ecx, FieldOperand(ebx, FixedArray::kLengthOffset)); |
| 1467 | 1467 |
| 1468 // Check if we could survive without allocation. | 1468 // Check if we could survive without allocation. |
| 1469 __ cmp(eax, Operand(ecx)); | 1469 __ cmp(eax, ecx); |
| 1470 __ j(greater, &attempt_to_grow_elements); | 1470 __ j(greater, &attempt_to_grow_elements); |
| 1471 | 1471 |
| 1472 // Check if value is a smi. | 1472 // Check if value is a smi. |
| 1473 __ mov(ecx, Operand(esp, argc * kPointerSize)); | 1473 __ mov(ecx, Operand(esp, argc * kPointerSize)); |
| 1474 __ JumpIfNotSmi(ecx, &with_write_barrier); | 1474 __ JumpIfNotSmi(ecx, &with_write_barrier); |
| 1475 | 1475 |
| 1476 // Save new length. | 1476 // Save new length. |
| 1477 __ mov(FieldOperand(edx, JSArray::kLengthOffset), eax); | 1477 __ mov(FieldOperand(edx, JSArray::kLengthOffset), eax); |
| 1478 | 1478 |
| 1479 // Push the element. | 1479 // Push the element. |
| (...skipping 51 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1531 ExternalReference::new_space_allocation_limit_address(isolate()); | 1531 ExternalReference::new_space_allocation_limit_address(isolate()); |
| 1532 | 1532 |
| 1533 const int kAllocationDelta = 4; | 1533 const int kAllocationDelta = 4; |
| 1534 // Load top. | 1534 // Load top. |
| 1535 __ mov(ecx, Operand::StaticVariable(new_space_allocation_top)); | 1535 __ mov(ecx, Operand::StaticVariable(new_space_allocation_top)); |
| 1536 | 1536 |
| 1537 // Check if it's the end of elements. | 1537 // Check if it's the end of elements. |
| 1538 __ lea(edx, FieldOperand(ebx, | 1538 __ lea(edx, FieldOperand(ebx, |
| 1539 eax, times_half_pointer_size, | 1539 eax, times_half_pointer_size, |
| 1540 FixedArray::kHeaderSize - argc * kPointerSize)); | 1540 FixedArray::kHeaderSize - argc * kPointerSize)); |
| 1541 __ cmp(edx, Operand(ecx)); | 1541 __ cmp(edx, ecx); |
| 1542 __ j(not_equal, &call_builtin); | 1542 __ j(not_equal, &call_builtin); |
| 1543 __ add(Operand(ecx), Immediate(kAllocationDelta * kPointerSize)); | 1543 __ add(ecx, Immediate(kAllocationDelta * kPointerSize)); |
| 1544 __ cmp(ecx, Operand::StaticVariable(new_space_allocation_limit)); | 1544 __ cmp(ecx, Operand::StaticVariable(new_space_allocation_limit)); |
| 1545 __ j(above, &call_builtin); | 1545 __ j(above, &call_builtin); |
| 1546 | 1546 |
| 1547 // We fit and could grow elements. | 1547 // We fit and could grow elements. |
| 1548 __ mov(Operand::StaticVariable(new_space_allocation_top), ecx); | 1548 __ mov(Operand::StaticVariable(new_space_allocation_top), ecx); |
| 1549 | 1549 |
| 1550 // Push the argument... | 1550 // Push the argument... |
| 1551 __ mov(Operand(edx, 0), edi); | 1551 __ mov(Operand(edx, 0), edi); |
| 1552 // ... and fill the rest with holes. | 1552 // ... and fill the rest with holes. |
| 1553 for (int i = 1; i < kAllocationDelta; i++) { | 1553 for (int i = 1; i < kAllocationDelta; i++) { |
| (...skipping 75 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1629 // Get the elements array of the object. | 1629 // Get the elements array of the object. |
| 1630 __ mov(ebx, FieldOperand(edx, JSArray::kElementsOffset)); | 1630 __ mov(ebx, FieldOperand(edx, JSArray::kElementsOffset)); |
| 1631 | 1631 |
| 1632 // Check that the elements are in fast mode and writable. | 1632 // Check that the elements are in fast mode and writable. |
| 1633 __ cmp(FieldOperand(ebx, HeapObject::kMapOffset), | 1633 __ cmp(FieldOperand(ebx, HeapObject::kMapOffset), |
| 1634 Immediate(factory()->fixed_array_map())); | 1634 Immediate(factory()->fixed_array_map())); |
| 1635 __ j(not_equal, &call_builtin); | 1635 __ j(not_equal, &call_builtin); |
| 1636 | 1636 |
| 1637 // Get the array's length into ecx and calculate new length. | 1637 // Get the array's length into ecx and calculate new length. |
| 1638 __ mov(ecx, FieldOperand(edx, JSArray::kLengthOffset)); | 1638 __ mov(ecx, FieldOperand(edx, JSArray::kLengthOffset)); |
| 1639 __ sub(Operand(ecx), Immediate(Smi::FromInt(1))); | 1639 __ sub(ecx, Immediate(Smi::FromInt(1))); |
| 1640 __ j(negative, &return_undefined); | 1640 __ j(negative, &return_undefined); |
| 1641 | 1641 |
| 1642 // Get the last element. | 1642 // Get the last element. |
| 1643 STATIC_ASSERT(kSmiTagSize == 1); | 1643 STATIC_ASSERT(kSmiTagSize == 1); |
| 1644 STATIC_ASSERT(kSmiTag == 0); | 1644 STATIC_ASSERT(kSmiTag == 0); |
| 1645 __ mov(eax, FieldOperand(ebx, | 1645 __ mov(eax, FieldOperand(ebx, |
| 1646 ecx, times_half_pointer_size, | 1646 ecx, times_half_pointer_size, |
| 1647 FixedArray::kHeaderSize)); | 1647 FixedArray::kHeaderSize)); |
| 1648 __ cmp(Operand(eax), Immediate(factory()->the_hole_value())); | 1648 __ cmp(eax, Immediate(factory()->the_hole_value())); |
| 1649 __ j(equal, &call_builtin); | 1649 __ j(equal, &call_builtin); |
| 1650 | 1650 |
| 1651 // Set the array's length. | 1651 // Set the array's length. |
| 1652 __ mov(FieldOperand(edx, JSArray::kLengthOffset), ecx); | 1652 __ mov(FieldOperand(edx, JSArray::kLengthOffset), ecx); |
| 1653 | 1653 |
| 1654 // Fill with the hole. | 1654 // Fill with the hole. |
| 1655 __ mov(FieldOperand(ebx, | 1655 __ mov(FieldOperand(ebx, |
| 1656 ecx, times_half_pointer_size, | 1656 ecx, times_half_pointer_size, |
| 1657 FixedArray::kHeaderSize), | 1657 FixedArray::kHeaderSize), |
| 1658 Immediate(factory()->the_hole_value())); | 1658 Immediate(factory()->the_hole_value())); |
| (...skipping 443 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2102 Label not_smi; | 2102 Label not_smi; |
| 2103 STATIC_ASSERT(kSmiTag == 0); | 2103 STATIC_ASSERT(kSmiTag == 0); |
| 2104 __ JumpIfNotSmi(eax, ¬_smi); | 2104 __ JumpIfNotSmi(eax, ¬_smi); |
| 2105 | 2105 |
| 2106 // Set ebx to 1...1 (== -1) if the argument is negative, or to 0...0 | 2106 // Set ebx to 1...1 (== -1) if the argument is negative, or to 0...0 |
| 2107 // otherwise. | 2107 // otherwise. |
| 2108 __ mov(ebx, eax); | 2108 __ mov(ebx, eax); |
| 2109 __ sar(ebx, kBitsPerInt - 1); | 2109 __ sar(ebx, kBitsPerInt - 1); |
| 2110 | 2110 |
| 2111 // Do bitwise not or do nothing depending on ebx. | 2111 // Do bitwise not or do nothing depending on ebx. |
| 2112 __ xor_(eax, Operand(ebx)); | 2112 __ xor_(eax, ebx); |
| 2113 | 2113 |
| 2114 // Add 1 or do nothing depending on ebx. | 2114 // Add 1 or do nothing depending on ebx. |
| 2115 __ sub(eax, Operand(ebx)); | 2115 __ sub(eax, ebx); |
| 2116 | 2116 |
| 2117 // If the result is still negative, go to the slow case. | 2117 // If the result is still negative, go to the slow case. |
| 2118 // This only happens for the most negative smi. | 2118 // This only happens for the most negative smi. |
| 2119 Label slow; | 2119 Label slow; |
| 2120 __ j(negative, &slow); | 2120 __ j(negative, &slow); |
| 2121 | 2121 |
| 2122 // Smi case done. | 2122 // Smi case done. |
| 2123 __ ret(2 * kPointerSize); | 2123 __ ret(2 * kPointerSize); |
| 2124 | 2124 |
| 2125 // Check if the argument is a heap number and load its exponent and | 2125 // Check if the argument is a heap number and load its exponent and |
| (...skipping 62 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2188 | 2188 |
| 2189 // Check that the receiver isn't a smi. | 2189 // Check that the receiver isn't a smi. |
| 2190 __ JumpIfSmi(edx, &miss_before_stack_reserved); | 2190 __ JumpIfSmi(edx, &miss_before_stack_reserved); |
| 2191 | 2191 |
| 2192 Counters* counters = isolate()->counters(); | 2192 Counters* counters = isolate()->counters(); |
| 2193 __ IncrementCounter(counters->call_const(), 1); | 2193 __ IncrementCounter(counters->call_const(), 1); |
| 2194 __ IncrementCounter(counters->call_const_fast_api(), 1); | 2194 __ IncrementCounter(counters->call_const_fast_api(), 1); |
| 2195 | 2195 |
| 2196 // Allocate space for v8::Arguments implicit values. Must be initialized | 2196 // Allocate space for v8::Arguments implicit values. Must be initialized |
| 2197 // before calling any runtime function. | 2197 // before calling any runtime function. |
| 2198 __ sub(Operand(esp), Immediate(kFastApiCallArguments * kPointerSize)); | 2198 __ sub(esp, Immediate(kFastApiCallArguments * kPointerSize)); |
| 2199 | 2199 |
| 2200 // Check that the maps haven't changed and find a Holder as a side effect. | 2200 // Check that the maps haven't changed and find a Holder as a side effect. |
| 2201 CheckPrototypes(JSObject::cast(object), edx, holder, | 2201 CheckPrototypes(JSObject::cast(object), edx, holder, |
| 2202 ebx, eax, edi, name, depth, &miss); | 2202 ebx, eax, edi, name, depth, &miss); |
| 2203 | 2203 |
| 2204 // Move the return address on top of the stack. | 2204 // Move the return address on top of the stack. |
| 2205 __ mov(eax, Operand(esp, 3 * kPointerSize)); | 2205 __ mov(eax, Operand(esp, 3 * kPointerSize)); |
| 2206 __ mov(Operand(esp, 0 * kPointerSize), eax); | 2206 __ mov(Operand(esp, 0 * kPointerSize), eax); |
| 2207 | 2207 |
| 2208 // esp[2 * kPointerSize] is uninitialized, esp[3 * kPointerSize] contains | 2208 // esp[2 * kPointerSize] is uninitialized, esp[3 * kPointerSize] contains |
| 2209 // duplicate of return address and will be overwritten. | 2209 // duplicate of return address and will be overwritten. |
| 2210 MaybeObject* result = GenerateFastApiCall(masm(), optimization, argc); | 2210 MaybeObject* result = GenerateFastApiCall(masm(), optimization, argc); |
| 2211 if (result->IsFailure()) return result; | 2211 if (result->IsFailure()) return result; |
| 2212 | 2212 |
| 2213 __ bind(&miss); | 2213 __ bind(&miss); |
| 2214 __ add(Operand(esp), Immediate(kFastApiCallArguments * kPointerSize)); | 2214 __ add(esp, Immediate(kFastApiCallArguments * kPointerSize)); |
| 2215 | 2215 |
| 2216 __ bind(&miss_before_stack_reserved); | 2216 __ bind(&miss_before_stack_reserved); |
| 2217 MaybeObject* maybe_result = GenerateMissBranch(); | 2217 MaybeObject* maybe_result = GenerateMissBranch(); |
| 2218 if (maybe_result->IsFailure()) return maybe_result; | 2218 if (maybe_result->IsFailure()) return maybe_result; |
| 2219 | 2219 |
| 2220 // Return the generated code. | 2220 // Return the generated code. |
| 2221 return GetCode(function); | 2221 return GetCode(function); |
| 2222 } | 2222 } |
| 2223 | 2223 |
| 2224 | 2224 |
| (...skipping 479 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2704 // -- ecx : key | 2704 // -- ecx : key |
| 2705 // -- edx : receiver | 2705 // -- edx : receiver |
| 2706 // -- esp[0] : return address | 2706 // -- esp[0] : return address |
| 2707 // ----------------------------------- | 2707 // ----------------------------------- |
| 2708 Label miss; | 2708 Label miss; |
| 2709 | 2709 |
| 2710 Counters* counters = isolate()->counters(); | 2710 Counters* counters = isolate()->counters(); |
| 2711 __ IncrementCounter(counters->keyed_store_field(), 1); | 2711 __ IncrementCounter(counters->keyed_store_field(), 1); |
| 2712 | 2712 |
| 2713 // Check that the name has not changed. | 2713 // Check that the name has not changed. |
| 2714 __ cmp(Operand(ecx), Immediate(Handle<String>(name))); | 2714 __ cmp(ecx, Immediate(Handle<String>(name))); |
| 2715 __ j(not_equal, &miss); | 2715 __ j(not_equal, &miss); |
| 2716 | 2716 |
| 2717 // Generate store field code. Trashes the name register. | 2717 // Generate store field code. Trashes the name register. |
| 2718 GenerateStoreField(masm(), | 2718 GenerateStoreField(masm(), |
| 2719 object, | 2719 object, |
| 2720 index, | 2720 index, |
| 2721 transition, | 2721 transition, |
| 2722 edx, ecx, ebx, | 2722 edx, ecx, ebx, |
| 2723 &miss); | 2723 &miss); |
| 2724 | 2724 |
| (...skipping 271 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2996 // -- eax : key | 2996 // -- eax : key |
| 2997 // -- edx : receiver | 2997 // -- edx : receiver |
| 2998 // -- esp[0] : return address | 2998 // -- esp[0] : return address |
| 2999 // ----------------------------------- | 2999 // ----------------------------------- |
| 3000 Label miss; | 3000 Label miss; |
| 3001 | 3001 |
| 3002 Counters* counters = isolate()->counters(); | 3002 Counters* counters = isolate()->counters(); |
| 3003 __ IncrementCounter(counters->keyed_load_field(), 1); | 3003 __ IncrementCounter(counters->keyed_load_field(), 1); |
| 3004 | 3004 |
| 3005 // Check that the name has not changed. | 3005 // Check that the name has not changed. |
| 3006 __ cmp(Operand(eax), Immediate(Handle<String>(name))); | 3006 __ cmp(eax, Immediate(Handle<String>(name))); |
| 3007 __ j(not_equal, &miss); | 3007 __ j(not_equal, &miss); |
| 3008 | 3008 |
| 3009 GenerateLoadField(receiver, holder, edx, ebx, ecx, edi, index, name, &miss); | 3009 GenerateLoadField(receiver, holder, edx, ebx, ecx, edi, index, name, &miss); |
| 3010 | 3010 |
| 3011 __ bind(&miss); | 3011 __ bind(&miss); |
| 3012 __ DecrementCounter(counters->keyed_load_field(), 1); | 3012 __ DecrementCounter(counters->keyed_load_field(), 1); |
| 3013 GenerateLoadMiss(masm(), Code::KEYED_LOAD_IC); | 3013 GenerateLoadMiss(masm(), Code::KEYED_LOAD_IC); |
| 3014 | 3014 |
| 3015 // Return the generated code. | 3015 // Return the generated code. |
| 3016 return GetCode(FIELD, name); | 3016 return GetCode(FIELD, name); |
| 3017 } | 3017 } |
| 3018 | 3018 |
| 3019 | 3019 |
| 3020 MaybeObject* KeyedLoadStubCompiler::CompileLoadCallback( | 3020 MaybeObject* KeyedLoadStubCompiler::CompileLoadCallback( |
| 3021 String* name, | 3021 String* name, |
| 3022 JSObject* receiver, | 3022 JSObject* receiver, |
| 3023 JSObject* holder, | 3023 JSObject* holder, |
| 3024 AccessorInfo* callback) { | 3024 AccessorInfo* callback) { |
| 3025 // ----------- S t a t e ------------- | 3025 // ----------- S t a t e ------------- |
| 3026 // -- eax : key | 3026 // -- eax : key |
| 3027 // -- edx : receiver | 3027 // -- edx : receiver |
| 3028 // -- esp[0] : return address | 3028 // -- esp[0] : return address |
| 3029 // ----------------------------------- | 3029 // ----------------------------------- |
| 3030 Label miss; | 3030 Label miss; |
| 3031 | 3031 |
| 3032 Counters* counters = isolate()->counters(); | 3032 Counters* counters = isolate()->counters(); |
| 3033 __ IncrementCounter(counters->keyed_load_callback(), 1); | 3033 __ IncrementCounter(counters->keyed_load_callback(), 1); |
| 3034 | 3034 |
| 3035 // Check that the name has not changed. | 3035 // Check that the name has not changed. |
| 3036 __ cmp(Operand(eax), Immediate(Handle<String>(name))); | 3036 __ cmp(eax, Immediate(Handle<String>(name))); |
| 3037 __ j(not_equal, &miss); | 3037 __ j(not_equal, &miss); |
| 3038 | 3038 |
| 3039 MaybeObject* result = GenerateLoadCallback(receiver, holder, edx, eax, ebx, | 3039 MaybeObject* result = GenerateLoadCallback(receiver, holder, edx, eax, ebx, |
| 3040 ecx, edi, callback, name, &miss); | 3040 ecx, edi, callback, name, &miss); |
| 3041 if (result->IsFailure()) { | 3041 if (result->IsFailure()) { |
| 3042 miss.Unuse(); | 3042 miss.Unuse(); |
| 3043 return result; | 3043 return result; |
| 3044 } | 3044 } |
| 3045 | 3045 |
| 3046 __ bind(&miss); | 3046 __ bind(&miss); |
| (...skipping 14 matching lines...) Expand all Loading... |
| 3061 // -- eax : key | 3061 // -- eax : key |
| 3062 // -- edx : receiver | 3062 // -- edx : receiver |
| 3063 // -- esp[0] : return address | 3063 // -- esp[0] : return address |
| 3064 // ----------------------------------- | 3064 // ----------------------------------- |
| 3065 Label miss; | 3065 Label miss; |
| 3066 | 3066 |
| 3067 Counters* counters = isolate()->counters(); | 3067 Counters* counters = isolate()->counters(); |
| 3068 __ IncrementCounter(counters->keyed_load_constant_function(), 1); | 3068 __ IncrementCounter(counters->keyed_load_constant_function(), 1); |
| 3069 | 3069 |
| 3070 // Check that the name has not changed. | 3070 // Check that the name has not changed. |
| 3071 __ cmp(Operand(eax), Immediate(Handle<String>(name))); | 3071 __ cmp(eax, Immediate(Handle<String>(name))); |
| 3072 __ j(not_equal, &miss); | 3072 __ j(not_equal, &miss); |
| 3073 | 3073 |
| 3074 GenerateLoadConstant(receiver, holder, edx, ebx, ecx, edi, | 3074 GenerateLoadConstant(receiver, holder, edx, ebx, ecx, edi, |
| 3075 value, name, &miss); | 3075 value, name, &miss); |
| 3076 __ bind(&miss); | 3076 __ bind(&miss); |
| 3077 __ DecrementCounter(counters->keyed_load_constant_function(), 1); | 3077 __ DecrementCounter(counters->keyed_load_constant_function(), 1); |
| 3078 GenerateLoadMiss(masm(), Code::KEYED_LOAD_IC); | 3078 GenerateLoadMiss(masm(), Code::KEYED_LOAD_IC); |
| 3079 | 3079 |
| 3080 // Return the generated code. | 3080 // Return the generated code. |
| 3081 return GetCode(CONSTANT_FUNCTION, name); | 3081 return GetCode(CONSTANT_FUNCTION, name); |
| 3082 } | 3082 } |
| 3083 | 3083 |
| 3084 | 3084 |
| 3085 MaybeObject* KeyedLoadStubCompiler::CompileLoadInterceptor(JSObject* receiver, | 3085 MaybeObject* KeyedLoadStubCompiler::CompileLoadInterceptor(JSObject* receiver, |
| 3086 JSObject* holder, | 3086 JSObject* holder, |
| 3087 String* name) { | 3087 String* name) { |
| 3088 // ----------- S t a t e ------------- | 3088 // ----------- S t a t e ------------- |
| 3089 // -- eax : key | 3089 // -- eax : key |
| 3090 // -- edx : receiver | 3090 // -- edx : receiver |
| 3091 // -- esp[0] : return address | 3091 // -- esp[0] : return address |
| 3092 // ----------------------------------- | 3092 // ----------------------------------- |
| 3093 Label miss; | 3093 Label miss; |
| 3094 | 3094 |
| 3095 Counters* counters = isolate()->counters(); | 3095 Counters* counters = isolate()->counters(); |
| 3096 __ IncrementCounter(counters->keyed_load_interceptor(), 1); | 3096 __ IncrementCounter(counters->keyed_load_interceptor(), 1); |
| 3097 | 3097 |
| 3098 // Check that the name has not changed. | 3098 // Check that the name has not changed. |
| 3099 __ cmp(Operand(eax), Immediate(Handle<String>(name))); | 3099 __ cmp(eax, Immediate(Handle<String>(name))); |
| 3100 __ j(not_equal, &miss); | 3100 __ j(not_equal, &miss); |
| 3101 | 3101 |
| 3102 LookupResult lookup; | 3102 LookupResult lookup; |
| 3103 LookupPostInterceptor(holder, name, &lookup); | 3103 LookupPostInterceptor(holder, name, &lookup); |
| 3104 GenerateLoadInterceptor(receiver, | 3104 GenerateLoadInterceptor(receiver, |
| 3105 holder, | 3105 holder, |
| 3106 &lookup, | 3106 &lookup, |
| 3107 edx, | 3107 edx, |
| 3108 eax, | 3108 eax, |
| 3109 ecx, | 3109 ecx, |
| (...skipping 15 matching lines...) Expand all Loading... |
| 3125 // -- eax : key | 3125 // -- eax : key |
| 3126 // -- edx : receiver | 3126 // -- edx : receiver |
| 3127 // -- esp[0] : return address | 3127 // -- esp[0] : return address |
| 3128 // ----------------------------------- | 3128 // ----------------------------------- |
| 3129 Label miss; | 3129 Label miss; |
| 3130 | 3130 |
| 3131 Counters* counters = isolate()->counters(); | 3131 Counters* counters = isolate()->counters(); |
| 3132 __ IncrementCounter(counters->keyed_load_array_length(), 1); | 3132 __ IncrementCounter(counters->keyed_load_array_length(), 1); |
| 3133 | 3133 |
| 3134 // Check that the name has not changed. | 3134 // Check that the name has not changed. |
| 3135 __ cmp(Operand(eax), Immediate(Handle<String>(name))); | 3135 __ cmp(eax, Immediate(Handle<String>(name))); |
| 3136 __ j(not_equal, &miss); | 3136 __ j(not_equal, &miss); |
| 3137 | 3137 |
| 3138 GenerateLoadArrayLength(masm(), edx, ecx, &miss); | 3138 GenerateLoadArrayLength(masm(), edx, ecx, &miss); |
| 3139 __ bind(&miss); | 3139 __ bind(&miss); |
| 3140 __ DecrementCounter(counters->keyed_load_array_length(), 1); | 3140 __ DecrementCounter(counters->keyed_load_array_length(), 1); |
| 3141 GenerateLoadMiss(masm(), Code::KEYED_LOAD_IC); | 3141 GenerateLoadMiss(masm(), Code::KEYED_LOAD_IC); |
| 3142 | 3142 |
| 3143 // Return the generated code. | 3143 // Return the generated code. |
| 3144 return GetCode(CALLBACKS, name); | 3144 return GetCode(CALLBACKS, name); |
| 3145 } | 3145 } |
| 3146 | 3146 |
| 3147 | 3147 |
| 3148 MaybeObject* KeyedLoadStubCompiler::CompileLoadStringLength(String* name) { | 3148 MaybeObject* KeyedLoadStubCompiler::CompileLoadStringLength(String* name) { |
| 3149 // ----------- S t a t e ------------- | 3149 // ----------- S t a t e ------------- |
| 3150 // -- eax : key | 3150 // -- eax : key |
| 3151 // -- edx : receiver | 3151 // -- edx : receiver |
| 3152 // -- esp[0] : return address | 3152 // -- esp[0] : return address |
| 3153 // ----------------------------------- | 3153 // ----------------------------------- |
| 3154 Label miss; | 3154 Label miss; |
| 3155 | 3155 |
| 3156 Counters* counters = isolate()->counters(); | 3156 Counters* counters = isolate()->counters(); |
| 3157 __ IncrementCounter(counters->keyed_load_string_length(), 1); | 3157 __ IncrementCounter(counters->keyed_load_string_length(), 1); |
| 3158 | 3158 |
| 3159 // Check that the name has not changed. | 3159 // Check that the name has not changed. |
| 3160 __ cmp(Operand(eax), Immediate(Handle<String>(name))); | 3160 __ cmp(eax, Immediate(Handle<String>(name))); |
| 3161 __ j(not_equal, &miss); | 3161 __ j(not_equal, &miss); |
| 3162 | 3162 |
| 3163 GenerateLoadStringLength(masm(), edx, ecx, ebx, &miss, true); | 3163 GenerateLoadStringLength(masm(), edx, ecx, ebx, &miss, true); |
| 3164 __ bind(&miss); | 3164 __ bind(&miss); |
| 3165 __ DecrementCounter(counters->keyed_load_string_length(), 1); | 3165 __ DecrementCounter(counters->keyed_load_string_length(), 1); |
| 3166 GenerateLoadMiss(masm(), Code::KEYED_LOAD_IC); | 3166 GenerateLoadMiss(masm(), Code::KEYED_LOAD_IC); |
| 3167 | 3167 |
| 3168 // Return the generated code. | 3168 // Return the generated code. |
| 3169 return GetCode(CALLBACKS, name); | 3169 return GetCode(CALLBACKS, name); |
| 3170 } | 3170 } |
| 3171 | 3171 |
| 3172 | 3172 |
| 3173 MaybeObject* KeyedLoadStubCompiler::CompileLoadFunctionPrototype(String* name) { | 3173 MaybeObject* KeyedLoadStubCompiler::CompileLoadFunctionPrototype(String* name) { |
| 3174 // ----------- S t a t e ------------- | 3174 // ----------- S t a t e ------------- |
| 3175 // -- eax : key | 3175 // -- eax : key |
| 3176 // -- edx : receiver | 3176 // -- edx : receiver |
| 3177 // -- esp[0] : return address | 3177 // -- esp[0] : return address |
| 3178 // ----------------------------------- | 3178 // ----------------------------------- |
| 3179 Label miss; | 3179 Label miss; |
| 3180 | 3180 |
| 3181 Counters* counters = isolate()->counters(); | 3181 Counters* counters = isolate()->counters(); |
| 3182 __ IncrementCounter(counters->keyed_load_function_prototype(), 1); | 3182 __ IncrementCounter(counters->keyed_load_function_prototype(), 1); |
| 3183 | 3183 |
| 3184 // Check that the name has not changed. | 3184 // Check that the name has not changed. |
| 3185 __ cmp(Operand(eax), Immediate(Handle<String>(name))); | 3185 __ cmp(eax, Immediate(Handle<String>(name))); |
| 3186 __ j(not_equal, &miss); | 3186 __ j(not_equal, &miss); |
| 3187 | 3187 |
| 3188 GenerateLoadFunctionPrototype(masm(), edx, ecx, ebx, &miss); | 3188 GenerateLoadFunctionPrototype(masm(), edx, ecx, ebx, &miss); |
| 3189 __ bind(&miss); | 3189 __ bind(&miss); |
| 3190 __ DecrementCounter(counters->keyed_load_function_prototype(), 1); | 3190 __ DecrementCounter(counters->keyed_load_function_prototype(), 1); |
| 3191 GenerateLoadMiss(masm(), Code::KEYED_LOAD_IC); | 3191 GenerateLoadMiss(masm(), Code::KEYED_LOAD_IC); |
| 3192 | 3192 |
| 3193 // Return the generated code. | 3193 // Return the generated code. |
| 3194 return GetCode(CALLBACKS, name); | 3194 return GetCode(CALLBACKS, name); |
| 3195 } | 3195 } |
| (...skipping 157 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 3353 ASSERT(function->has_initial_map()); | 3353 ASSERT(function->has_initial_map()); |
| 3354 for (int i = shared->this_property_assignments_count(); | 3354 for (int i = shared->this_property_assignments_count(); |
| 3355 i < function->initial_map()->inobject_properties(); | 3355 i < function->initial_map()->inobject_properties(); |
| 3356 i++) { | 3356 i++) { |
| 3357 __ mov(Operand(edx, i * kPointerSize), edi); | 3357 __ mov(Operand(edx, i * kPointerSize), edi); |
| 3358 } | 3358 } |
| 3359 | 3359 |
| 3360 // Move argc to ebx and retrieve and tag the JSObject to return. | 3360 // Move argc to ebx and retrieve and tag the JSObject to return. |
| 3361 __ mov(ebx, eax); | 3361 __ mov(ebx, eax); |
| 3362 __ pop(eax); | 3362 __ pop(eax); |
| 3363 __ or_(Operand(eax), Immediate(kHeapObjectTag)); | 3363 __ or_(eax, Immediate(kHeapObjectTag)); |
| 3364 | 3364 |
| 3365 // Remove caller arguments and receiver from the stack and return. | 3365 // Remove caller arguments and receiver from the stack and return. |
| 3366 __ pop(ecx); | 3366 __ pop(ecx); |
| 3367 __ lea(esp, Operand(esp, ebx, times_pointer_size, 1 * kPointerSize)); | 3367 __ lea(esp, Operand(esp, ebx, times_pointer_size, 1 * kPointerSize)); |
| 3368 __ push(ecx); | 3368 __ push(ecx); |
| 3369 Counters* counters = isolate()->counters(); | 3369 Counters* counters = isolate()->counters(); |
| 3370 __ IncrementCounter(counters->constructed_objects(), 1); | 3370 __ IncrementCounter(counters->constructed_objects(), 1); |
| 3371 __ IncrementCounter(counters->constructed_objects_stub(), 1); | 3371 __ IncrementCounter(counters->constructed_objects_stub(), 1); |
| 3372 __ ret(0); | 3372 __ ret(0); |
| 3373 | 3373 |
| (...skipping 360 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 3734 } | 3734 } |
| 3735 } else { | 3735 } else { |
| 3736 if (CpuFeatures::IsSupported(SSE3)) { | 3736 if (CpuFeatures::IsSupported(SSE3)) { |
| 3737 CpuFeatures::Scope scope(SSE3); | 3737 CpuFeatures::Scope scope(SSE3); |
| 3738 // fisttp stores values as signed integers. To represent the | 3738 // fisttp stores values as signed integers. To represent the |
| 3739 // entire range of int and unsigned int arrays, store as a | 3739 // entire range of int and unsigned int arrays, store as a |
| 3740 // 64-bit int and discard the high 32 bits. | 3740 // 64-bit int and discard the high 32 bits. |
| 3741 // If the value is NaN or +/-infinity, the result is 0x80000000, | 3741 // If the value is NaN or +/-infinity, the result is 0x80000000, |
| 3742 // which is automatically zero when taken mod 2^n, n < 32. | 3742 // which is automatically zero when taken mod 2^n, n < 32. |
| 3743 __ fld_d(FieldOperand(eax, HeapNumber::kValueOffset)); | 3743 __ fld_d(FieldOperand(eax, HeapNumber::kValueOffset)); |
| 3744 __ sub(Operand(esp), Immediate(2 * kPointerSize)); | 3744 __ sub(esp, Immediate(2 * kPointerSize)); |
| 3745 __ fisttp_d(Operand(esp, 0)); | 3745 __ fisttp_d(Operand(esp, 0)); |
| 3746 __ pop(ebx); | 3746 __ pop(ebx); |
| 3747 __ add(Operand(esp), Immediate(kPointerSize)); | 3747 __ add(esp, Immediate(kPointerSize)); |
| 3748 } else { | 3748 } else { |
| 3749 ASSERT(CpuFeatures::IsSupported(SSE2)); | 3749 ASSERT(CpuFeatures::IsSupported(SSE2)); |
| 3750 CpuFeatures::Scope scope(SSE2); | 3750 CpuFeatures::Scope scope(SSE2); |
| 3751 // We can easily implement the correct rounding behavior for the | 3751 // We can easily implement the correct rounding behavior for the |
| 3752 // range [0, 2^31-1]. For the time being, to keep this code simple, | 3752 // range [0, 2^31-1]. For the time being, to keep this code simple, |
| 3753 // make the slow runtime call for values outside this range. | 3753 // make the slow runtime call for values outside this range. |
| 3754 // Note: we could do better for signed int arrays. | 3754 // Note: we could do better for signed int arrays. |
| 3755 __ movd(xmm0, FieldOperand(eax, HeapNumber::kValueOffset)); | 3755 __ movd(xmm0, FieldOperand(eax, HeapNumber::kValueOffset)); |
| 3756 // We will need the key if we have to make the slow runtime call. | 3756 // We will need the key if we have to make the slow runtime call. |
| 3757 __ push(ebx); | 3757 __ push(ebx); |
| (...skipping 188 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 3946 ASSERT(elements_kind == FAST_ELEMENTS); | 3946 ASSERT(elements_kind == FAST_ELEMENTS); |
| 3947 // Do the store and update the write barrier. | 3947 // Do the store and update the write barrier. |
| 3948 // ecx is a smi, use times_half_pointer_size instead of | 3948 // ecx is a smi, use times_half_pointer_size instead of |
| 3949 // times_pointer_size | 3949 // times_pointer_size |
| 3950 __ lea(ecx, FieldOperand(edi, | 3950 __ lea(ecx, FieldOperand(edi, |
| 3951 ecx, | 3951 ecx, |
| 3952 times_half_pointer_size, | 3952 times_half_pointer_size, |
| 3953 FixedArray::kHeaderSize)); | 3953 FixedArray::kHeaderSize)); |
| 3954 __ mov(Operand(ecx, 0), eax); | 3954 __ mov(Operand(ecx, 0), eax); |
| 3955 // Make sure to preserve the value in register eax. | 3955 // Make sure to preserve the value in register eax. |
| 3956 __ mov(edx, Operand(eax)); | 3956 __ mov(edx, eax); |
| 3957 __ RecordWrite(edi, ecx, edx, kDontSaveFPRegs); | 3957 __ RecordWrite(edi, ecx, edx, kDontSaveFPRegs); |
| 3958 } | 3958 } |
| 3959 | 3959 |
| 3960 // Done. | 3960 // Done. |
| 3961 __ ret(0); | 3961 __ ret(0); |
| 3962 | 3962 |
| 3963 // Handle store cache miss, replacing the ic with the generic stub. | 3963 // Handle store cache miss, replacing the ic with the generic stub. |
| 3964 __ bind(&miss_force_generic); | 3964 __ bind(&miss_force_generic); |
| 3965 Handle<Code> ic_force_generic = | 3965 Handle<Code> ic_force_generic = |
| 3966 masm->isolate()->builtins()->KeyedStoreIC_MissForceGeneric(); | 3966 masm->isolate()->builtins()->KeyedStoreIC_MissForceGeneric(); |
| (...skipping 46 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 4013 masm->isolate()->builtins()->KeyedStoreIC_MissForceGeneric(); | 4013 masm->isolate()->builtins()->KeyedStoreIC_MissForceGeneric(); |
| 4014 __ jmp(ic_force_generic, RelocInfo::CODE_TARGET); | 4014 __ jmp(ic_force_generic, RelocInfo::CODE_TARGET); |
| 4015 } | 4015 } |
| 4016 | 4016 |
| 4017 | 4017 |
| 4018 #undef __ | 4018 #undef __ |
| 4019 | 4019 |
| 4020 } } // namespace v8::internal | 4020 } } // namespace v8::internal |
| 4021 | 4021 |
| 4022 #endif // V8_TARGET_ARCH_IA32 | 4022 #endif // V8_TARGET_ARCH_IA32 |
| OLD | NEW |