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 |