| 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 39 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 50 ExternalReference value_offset(isolate->stub_cache()->value_reference(table)); | 50 ExternalReference value_offset(isolate->stub_cache()->value_reference(table)); |
| 51 | 51 |
| 52 Label miss; | 52 Label miss; |
| 53 | 53 |
| 54 if (extra.is_valid()) { | 54 if (extra.is_valid()) { |
| 55 // Get the code entry from the cache. | 55 // Get the code entry from the cache. |
| 56 __ mov(extra, Operand::StaticArray(offset, times_2, value_offset)); | 56 __ mov(extra, Operand::StaticArray(offset, times_2, value_offset)); |
| 57 | 57 |
| 58 // Check that the key in the entry matches the name. | 58 // Check that the key in the entry matches the name. |
| 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, not_taken); | 60 __ j(not_equal, &miss, Label::kFar, not_taken); |
| 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(Operand(extra), Immediate(Code::kHeaderSize - kHeapObjectTag)); |
| 70 __ jmp(Operand(extra)); | 70 __ jmp(Operand(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, not_taken); | 79 __ j(not_equal, &miss, Label::kFar, not_taken); |
| 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 |
| (...skipping 29 matching lines...) Expand all Loading... |
| 119 __ IncrementCounter(counters->negative_lookups_miss(), 1); | 119 __ IncrementCounter(counters->negative_lookups_miss(), 1); |
| 120 | 120 |
| 121 __ mov(r0, FieldOperand(receiver, HeapObject::kMapOffset)); | 121 __ mov(r0, FieldOperand(receiver, HeapObject::kMapOffset)); |
| 122 | 122 |
| 123 const int kInterceptorOrAccessCheckNeededMask = | 123 const int kInterceptorOrAccessCheckNeededMask = |
| 124 (1 << Map::kHasNamedInterceptor) | (1 << Map::kIsAccessCheckNeeded); | 124 (1 << Map::kHasNamedInterceptor) | (1 << Map::kIsAccessCheckNeeded); |
| 125 | 125 |
| 126 // Bail out if the receiver has a named interceptor or requires access checks. | 126 // Bail out if the receiver has a named interceptor or requires access checks. |
| 127 __ test_b(FieldOperand(r0, Map::kBitFieldOffset), | 127 __ test_b(FieldOperand(r0, Map::kBitFieldOffset), |
| 128 kInterceptorOrAccessCheckNeededMask); | 128 kInterceptorOrAccessCheckNeededMask); |
| 129 __ j(not_zero, miss_label, not_taken); | 129 __ j(not_zero, miss_label, Label::kFar, not_taken); |
| 130 | 130 |
| 131 // Check that receiver is a JSObject. | 131 // Check that receiver is a JSObject. |
| 132 __ CmpInstanceType(r0, FIRST_JS_OBJECT_TYPE); | 132 __ CmpInstanceType(r0, FIRST_JS_OBJECT_TYPE); |
| 133 __ j(below, miss_label, not_taken); | 133 __ j(below, miss_label, Label::kFar, not_taken); |
| 134 | 134 |
| 135 // Load properties array. | 135 // Load properties array. |
| 136 Register properties = r0; | 136 Register properties = r0; |
| 137 __ mov(properties, FieldOperand(receiver, JSObject::kPropertiesOffset)); | 137 __ mov(properties, FieldOperand(receiver, JSObject::kPropertiesOffset)); |
| 138 | 138 |
| 139 // Check that the properties array is a dictionary. | 139 // Check that the properties array is a dictionary. |
| 140 __ cmp(FieldOperand(properties, HeapObject::kMapOffset), | 140 __ cmp(FieldOperand(properties, HeapObject::kMapOffset), |
| 141 Immediate(masm->isolate()->factory()->hash_table_map())); | 141 Immediate(masm->isolate()->factory()->hash_table_map())); |
| 142 __ j(not_equal, miss_label); | 142 __ j(not_equal, miss_label); |
| 143 | 143 |
| (...skipping 33 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 177 ASSERT(!extra.is(receiver)); | 177 ASSERT(!extra.is(receiver)); |
| 178 ASSERT(!extra.is(name)); | 178 ASSERT(!extra.is(name)); |
| 179 ASSERT(!extra.is(scratch)); | 179 ASSERT(!extra.is(scratch)); |
| 180 | 180 |
| 181 // Check scratch and extra registers are valid, and extra2 is unused. | 181 // Check scratch and extra registers are valid, and extra2 is unused. |
| 182 ASSERT(!scratch.is(no_reg)); | 182 ASSERT(!scratch.is(no_reg)); |
| 183 ASSERT(extra2.is(no_reg)); | 183 ASSERT(extra2.is(no_reg)); |
| 184 | 184 |
| 185 // Check that the receiver isn't a smi. | 185 // Check that the receiver isn't a smi. |
| 186 __ test(receiver, Immediate(kSmiTagMask)); | 186 __ test(receiver, Immediate(kSmiTagMask)); |
| 187 __ j(zero, &miss, not_taken); | 187 __ j(zero, &miss, Label::kFar, not_taken); |
| 188 | 188 |
| 189 // Get the map of the receiver and compute the hash. | 189 // Get the map of the receiver and compute the hash. |
| 190 __ mov(scratch, FieldOperand(name, String::kHashFieldOffset)); | 190 __ mov(scratch, FieldOperand(name, String::kHashFieldOffset)); |
| 191 __ add(scratch, FieldOperand(receiver, HeapObject::kMapOffset)); | 191 __ add(scratch, FieldOperand(receiver, HeapObject::kMapOffset)); |
| 192 __ xor_(scratch, flags); | 192 __ xor_(scratch, flags); |
| 193 __ and_(scratch, (kPrimaryTableSize - 1) << kHeapObjectTagSize); | 193 __ and_(scratch, (kPrimaryTableSize - 1) << kHeapObjectTagSize); |
| 194 | 194 |
| 195 // Probe the primary table. | 195 // Probe the primary table. |
| 196 ProbeTable(isolate, masm, flags, kPrimary, name, scratch, extra); | 196 ProbeTable(isolate, masm, flags, kPrimary, name, scratch, extra); |
| 197 | 197 |
| (...skipping 40 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 238 __ mov(prototype, FieldOperand(prototype, Map::kPrototypeOffset)); | 238 __ mov(prototype, FieldOperand(prototype, Map::kPrototypeOffset)); |
| 239 } | 239 } |
| 240 | 240 |
| 241 | 241 |
| 242 void StubCompiler::GenerateLoadArrayLength(MacroAssembler* masm, | 242 void StubCompiler::GenerateLoadArrayLength(MacroAssembler* masm, |
| 243 Register receiver, | 243 Register receiver, |
| 244 Register scratch, | 244 Register scratch, |
| 245 Label* miss_label) { | 245 Label* miss_label) { |
| 246 // Check that the receiver isn't a smi. | 246 // Check that the receiver isn't a smi. |
| 247 __ test(receiver, Immediate(kSmiTagMask)); | 247 __ test(receiver, Immediate(kSmiTagMask)); |
| 248 __ j(zero, miss_label, not_taken); | 248 __ j(zero, miss_label, Label::kFar, not_taken); |
| 249 | 249 |
| 250 // Check that the object is a JS array. | 250 // Check that the object is a JS array. |
| 251 __ CmpObjectType(receiver, JS_ARRAY_TYPE, scratch); | 251 __ CmpObjectType(receiver, JS_ARRAY_TYPE, scratch); |
| 252 __ j(not_equal, miss_label, not_taken); | 252 __ j(not_equal, miss_label, Label::kFar, not_taken); |
| 253 | 253 |
| 254 // Load length directly from the JS array. | 254 // Load length directly from the JS array. |
| 255 __ mov(eax, FieldOperand(receiver, JSArray::kLengthOffset)); | 255 __ mov(eax, FieldOperand(receiver, JSArray::kLengthOffset)); |
| 256 __ ret(0); | 256 __ ret(0); |
| 257 } | 257 } |
| 258 | 258 |
| 259 | 259 |
| 260 // Generate code to check if an object is a string. If the object is | 260 // Generate code to check if an object is a string. If the object is |
| 261 // a string, the map's instance type is left in the scratch register. | 261 // a string, the map's instance type is left in the scratch register. |
| 262 static void GenerateStringCheck(MacroAssembler* masm, | 262 static void GenerateStringCheck(MacroAssembler* masm, |
| 263 Register receiver, | 263 Register receiver, |
| 264 Register scratch, | 264 Register scratch, |
| 265 Label* smi, | 265 Label* smi, |
| 266 Label* non_string_object) { | 266 Label* non_string_object) { |
| 267 // Check that the object isn't a smi. | 267 // Check that the object isn't a smi. |
| 268 __ test(receiver, Immediate(kSmiTagMask)); | 268 __ test(receiver, Immediate(kSmiTagMask)); |
| 269 __ j(zero, smi, not_taken); | 269 __ j(zero, smi, Label::kFar, not_taken); |
| 270 | 270 |
| 271 // Check that the object is a string. | 271 // Check that the object is a string. |
| 272 __ mov(scratch, FieldOperand(receiver, HeapObject::kMapOffset)); | 272 __ mov(scratch, FieldOperand(receiver, HeapObject::kMapOffset)); |
| 273 __ movzx_b(scratch, FieldOperand(scratch, Map::kInstanceTypeOffset)); | 273 __ movzx_b(scratch, FieldOperand(scratch, Map::kInstanceTypeOffset)); |
| 274 ASSERT(kNotStringTag != 0); | 274 ASSERT(kNotStringTag != 0); |
| 275 __ test(scratch, Immediate(kNotStringTag)); | 275 __ test(scratch, Immediate(kNotStringTag)); |
| 276 __ j(not_zero, non_string_object, not_taken); | 276 __ j(not_zero, non_string_object, Label::kFar, not_taken); |
| 277 } | 277 } |
| 278 | 278 |
| 279 | 279 |
| 280 void StubCompiler::GenerateLoadStringLength(MacroAssembler* masm, | 280 void StubCompiler::GenerateLoadStringLength(MacroAssembler* masm, |
| 281 Register receiver, | 281 Register receiver, |
| 282 Register scratch1, | 282 Register scratch1, |
| 283 Register scratch2, | 283 Register scratch2, |
| 284 Label* miss, | 284 Label* miss, |
| 285 bool support_wrappers) { | 285 bool support_wrappers) { |
| 286 Label check_wrapper; | 286 Label check_wrapper; |
| 287 | 287 |
| 288 // Check if the object is a string leaving the instance type in the | 288 // Check if the object is a string leaving the instance type in the |
| 289 // scratch register. | 289 // scratch register. |
| 290 GenerateStringCheck(masm, receiver, scratch1, miss, | 290 GenerateStringCheck(masm, receiver, scratch1, miss, |
| 291 support_wrappers ? &check_wrapper : miss); | 291 support_wrappers ? &check_wrapper : miss); |
| 292 | 292 |
| 293 // Load length from the string and convert to a smi. | 293 // Load length from the string and convert to a smi. |
| 294 __ mov(eax, FieldOperand(receiver, String::kLengthOffset)); | 294 __ mov(eax, FieldOperand(receiver, String::kLengthOffset)); |
| 295 __ ret(0); | 295 __ ret(0); |
| 296 | 296 |
| 297 if (support_wrappers) { | 297 if (support_wrappers) { |
| 298 // Check if the object is a JSValue wrapper. | 298 // Check if the object is a JSValue wrapper. |
| 299 __ bind(&check_wrapper); | 299 __ bind(&check_wrapper); |
| 300 __ cmp(scratch1, JS_VALUE_TYPE); | 300 __ cmp(scratch1, JS_VALUE_TYPE); |
| 301 __ j(not_equal, miss, not_taken); | 301 __ j(not_equal, miss, Label::kFar, not_taken); |
| 302 | 302 |
| 303 // Check if the wrapped value is a string and load the length | 303 // Check if the wrapped value is a string and load the length |
| 304 // directly if it is. | 304 // directly if it is. |
| 305 __ mov(scratch2, FieldOperand(receiver, JSValue::kValueOffset)); | 305 __ mov(scratch2, FieldOperand(receiver, JSValue::kValueOffset)); |
| 306 GenerateStringCheck(masm, scratch2, scratch1, miss, miss); | 306 GenerateStringCheck(masm, scratch2, scratch1, miss, miss); |
| 307 __ mov(eax, FieldOperand(scratch2, String::kLengthOffset)); | 307 __ mov(eax, FieldOperand(scratch2, String::kLengthOffset)); |
| 308 __ ret(0); | 308 __ ret(0); |
| 309 } | 309 } |
| 310 } | 310 } |
| 311 | 311 |
| (...skipping 184 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 496 Register receiver, | 496 Register receiver, |
| 497 Register scratch1, | 497 Register scratch1, |
| 498 Register scratch2, | 498 Register scratch2, |
| 499 Register scratch3, | 499 Register scratch3, |
| 500 Label* miss) { | 500 Label* miss) { |
| 501 ASSERT(holder->HasNamedInterceptor()); | 501 ASSERT(holder->HasNamedInterceptor()); |
| 502 ASSERT(!holder->GetNamedInterceptor()->getter()->IsUndefined()); | 502 ASSERT(!holder->GetNamedInterceptor()->getter()->IsUndefined()); |
| 503 | 503 |
| 504 // Check that the receiver isn't a smi. | 504 // Check that the receiver isn't a smi. |
| 505 __ test(receiver, Immediate(kSmiTagMask)); | 505 __ test(receiver, Immediate(kSmiTagMask)); |
| 506 __ j(zero, miss, not_taken); | 506 __ j(zero, miss, Label::kFar, not_taken); |
| 507 | 507 |
| 508 CallOptimization optimization(lookup); | 508 CallOptimization optimization(lookup); |
| 509 | 509 |
| 510 if (optimization.is_constant_call()) { | 510 if (optimization.is_constant_call()) { |
| 511 return CompileCacheable(masm, | 511 return CompileCacheable(masm, |
| 512 object, | 512 object, |
| 513 receiver, | 513 receiver, |
| 514 scratch1, | 514 scratch1, |
| 515 scratch2, | 515 scratch2, |
| 516 scratch3, | 516 scratch3, |
| (...skipping 196 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 713 void StubCompiler::GenerateStoreField(MacroAssembler* masm, | 713 void StubCompiler::GenerateStoreField(MacroAssembler* masm, |
| 714 JSObject* object, | 714 JSObject* object, |
| 715 int index, | 715 int index, |
| 716 Map* transition, | 716 Map* transition, |
| 717 Register receiver_reg, | 717 Register receiver_reg, |
| 718 Register name_reg, | 718 Register name_reg, |
| 719 Register scratch, | 719 Register scratch, |
| 720 Label* miss_label) { | 720 Label* miss_label) { |
| 721 // Check that the object isn't a smi. | 721 // Check that the object isn't a smi. |
| 722 __ test(receiver_reg, Immediate(kSmiTagMask)); | 722 __ test(receiver_reg, Immediate(kSmiTagMask)); |
| 723 __ j(zero, miss_label, not_taken); | 723 __ j(zero, miss_label, Label::kFar, not_taken); |
| 724 | 724 |
| 725 // Check that the map of the object hasn't changed. | 725 // Check that the map of the object hasn't changed. |
| 726 __ cmp(FieldOperand(receiver_reg, HeapObject::kMapOffset), | 726 __ cmp(FieldOperand(receiver_reg, HeapObject::kMapOffset), |
| 727 Immediate(Handle<Map>(object->map()))); | 727 Immediate(Handle<Map>(object->map()))); |
| 728 __ j(not_equal, miss_label, not_taken); | 728 __ j(not_equal, miss_label, Label::kFar, not_taken); |
| 729 | 729 |
| 730 // Perform global security token check if needed. | 730 // Perform global security token check if needed. |
| 731 if (object->IsJSGlobalProxy()) { | 731 if (object->IsJSGlobalProxy()) { |
| 732 __ CheckAccessGlobalProxy(receiver_reg, scratch, miss_label); | 732 __ CheckAccessGlobalProxy(receiver_reg, scratch, miss_label); |
| 733 } | 733 } |
| 734 | 734 |
| 735 // Stub never generated for non-global objects that require access | 735 // Stub never generated for non-global objects that require access |
| 736 // checks. | 736 // checks. |
| 737 ASSERT(object->IsJSGlobalProxy() || !object->IsAccessCheckNeeded()); | 737 ASSERT(object->IsJSGlobalProxy() || !object->IsAccessCheckNeeded()); |
| 738 | 738 |
| (...skipping 69 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 808 JSGlobalPropertyCell* cell = JSGlobalPropertyCell::cast(probe); | 808 JSGlobalPropertyCell* cell = JSGlobalPropertyCell::cast(probe); |
| 809 ASSERT(cell->value()->IsTheHole()); | 809 ASSERT(cell->value()->IsTheHole()); |
| 810 if (Serializer::enabled()) { | 810 if (Serializer::enabled()) { |
| 811 __ mov(scratch, Immediate(Handle<Object>(cell))); | 811 __ mov(scratch, Immediate(Handle<Object>(cell))); |
| 812 __ cmp(FieldOperand(scratch, JSGlobalPropertyCell::kValueOffset), | 812 __ cmp(FieldOperand(scratch, JSGlobalPropertyCell::kValueOffset), |
| 813 Immediate(masm->isolate()->factory()->the_hole_value())); | 813 Immediate(masm->isolate()->factory()->the_hole_value())); |
| 814 } else { | 814 } else { |
| 815 __ cmp(Operand::Cell(Handle<JSGlobalPropertyCell>(cell)), | 815 __ cmp(Operand::Cell(Handle<JSGlobalPropertyCell>(cell)), |
| 816 Immediate(masm->isolate()->factory()->the_hole_value())); | 816 Immediate(masm->isolate()->factory()->the_hole_value())); |
| 817 } | 817 } |
| 818 __ j(not_equal, miss, not_taken); | 818 __ j(not_equal, miss, Label::kFar, not_taken); |
| 819 return cell; | 819 return cell; |
| 820 } | 820 } |
| 821 | 821 |
| 822 | 822 |
| 823 // Calls GenerateCheckPropertyCell for each global object in the prototype chain | 823 // Calls GenerateCheckPropertyCell for each global object in the prototype chain |
| 824 // from object to (but not including) holder. | 824 // from object to (but not including) holder. |
| 825 MUST_USE_RESULT static MaybeObject* GenerateCheckPropertyCells( | 825 MUST_USE_RESULT static MaybeObject* GenerateCheckPropertyCells( |
| 826 MacroAssembler* masm, | 826 MacroAssembler* masm, |
| 827 JSObject* object, | 827 JSObject* object, |
| 828 JSObject* holder, | 828 JSObject* holder, |
| (...skipping 79 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 908 scratch1, | 908 scratch1, |
| 909 scratch2); | 909 scratch2); |
| 910 __ mov(scratch1, FieldOperand(reg, HeapObject::kMapOffset)); | 910 __ mov(scratch1, FieldOperand(reg, HeapObject::kMapOffset)); |
| 911 reg = holder_reg; // from now the object is in holder_reg | 911 reg = holder_reg; // from now the object is in holder_reg |
| 912 __ mov(reg, FieldOperand(scratch1, Map::kPrototypeOffset)); | 912 __ mov(reg, FieldOperand(scratch1, Map::kPrototypeOffset)); |
| 913 } else if (heap()->InNewSpace(prototype)) { | 913 } else if (heap()->InNewSpace(prototype)) { |
| 914 // Get the map of the current object. | 914 // Get the map of the current object. |
| 915 __ mov(scratch1, FieldOperand(reg, HeapObject::kMapOffset)); | 915 __ mov(scratch1, FieldOperand(reg, HeapObject::kMapOffset)); |
| 916 __ cmp(Operand(scratch1), Immediate(Handle<Map>(current->map()))); | 916 __ cmp(Operand(scratch1), Immediate(Handle<Map>(current->map()))); |
| 917 // Branch on the result of the map check. | 917 // Branch on the result of the map check. |
| 918 __ j(not_equal, miss, not_taken); | 918 __ j(not_equal, miss, Label::kFar, not_taken); |
| 919 // Check access rights to the global object. This has to happen | 919 // Check access rights to the global object. This has to happen |
| 920 // after the map check so that we know that the object is | 920 // after the map check so that we know that the object is |
| 921 // actually a global object. | 921 // actually a global object. |
| 922 if (current->IsJSGlobalProxy()) { | 922 if (current->IsJSGlobalProxy()) { |
| 923 __ CheckAccessGlobalProxy(reg, scratch1, miss); | 923 __ CheckAccessGlobalProxy(reg, scratch1, miss); |
| 924 | 924 |
| 925 // Restore scratch register to be the map of the object. | 925 // Restore scratch register to be the map of the object. |
| 926 // We load the prototype from the map in the scratch register. | 926 // We load the prototype from the map in the scratch register. |
| 927 __ mov(scratch1, FieldOperand(reg, HeapObject::kMapOffset)); | 927 __ mov(scratch1, FieldOperand(reg, HeapObject::kMapOffset)); |
| 928 } | 928 } |
| 929 // The prototype is in new space; we cannot store a reference | 929 // The prototype is in new space; we cannot store a reference |
| 930 // to it in the code. Load it from the map. | 930 // to it in the code. Load it from the map. |
| 931 reg = holder_reg; // from now the object is in holder_reg | 931 reg = holder_reg; // from now the object is in holder_reg |
| 932 __ mov(reg, FieldOperand(scratch1, Map::kPrototypeOffset)); | 932 __ mov(reg, FieldOperand(scratch1, Map::kPrototypeOffset)); |
| 933 } else { | 933 } else { |
| 934 // Check the map of the current object. | 934 // Check the map of the current object. |
| 935 __ cmp(FieldOperand(reg, HeapObject::kMapOffset), | 935 __ cmp(FieldOperand(reg, HeapObject::kMapOffset), |
| 936 Immediate(Handle<Map>(current->map()))); | 936 Immediate(Handle<Map>(current->map()))); |
| 937 // Branch on the result of the map check. | 937 // Branch on the result of the map check. |
| 938 __ j(not_equal, miss, not_taken); | 938 __ j(not_equal, miss, Label::kFar, not_taken); |
| 939 // Check access rights to the global object. This has to happen | 939 // Check access rights to the global object. This has to happen |
| 940 // after the map check so that we know that the object is | 940 // after the map check so that we know that the object is |
| 941 // actually a global object. | 941 // actually a global object. |
| 942 if (current->IsJSGlobalProxy()) { | 942 if (current->IsJSGlobalProxy()) { |
| 943 __ CheckAccessGlobalProxy(reg, scratch1, miss); | 943 __ CheckAccessGlobalProxy(reg, scratch1, miss); |
| 944 } | 944 } |
| 945 // The prototype is in old space; load it directly. | 945 // The prototype is in old space; load it directly. |
| 946 reg = holder_reg; // from now the object is in holder_reg | 946 reg = holder_reg; // from now the object is in holder_reg |
| 947 __ mov(reg, Handle<JSObject>(prototype)); | 947 __ mov(reg, Handle<JSObject>(prototype)); |
| 948 } | 948 } |
| 949 | 949 |
| 950 if (save_at_depth == depth) { | 950 if (save_at_depth == depth) { |
| 951 __ mov(Operand(esp, kPointerSize), reg); | 951 __ mov(Operand(esp, kPointerSize), reg); |
| 952 } | 952 } |
| 953 | 953 |
| 954 // Go to the next object in the prototype chain. | 954 // Go to the next object in the prototype chain. |
| 955 current = prototype; | 955 current = prototype; |
| 956 } | 956 } |
| 957 ASSERT(current == holder); | 957 ASSERT(current == holder); |
| 958 | 958 |
| 959 // Log the check depth. | 959 // Log the check depth. |
| 960 LOG(isolate(), IntEvent("check-maps-depth", depth + 1)); | 960 LOG(isolate(), IntEvent("check-maps-depth", depth + 1)); |
| 961 | 961 |
| 962 // Check the holder map. | 962 // Check the holder map. |
| 963 __ cmp(FieldOperand(reg, HeapObject::kMapOffset), | 963 __ cmp(FieldOperand(reg, HeapObject::kMapOffset), |
| 964 Immediate(Handle<Map>(holder->map()))); | 964 Immediate(Handle<Map>(holder->map()))); |
| 965 __ j(not_equal, miss, not_taken); | 965 __ j(not_equal, miss, Label::kFar, not_taken); |
| 966 | 966 |
| 967 // Perform security check for access to the global object. | 967 // Perform security check for access to the global object. |
| 968 ASSERT(holder->IsJSGlobalProxy() || !holder->IsAccessCheckNeeded()); | 968 ASSERT(holder->IsJSGlobalProxy() || !holder->IsAccessCheckNeeded()); |
| 969 if (holder->IsJSGlobalProxy()) { | 969 if (holder->IsJSGlobalProxy()) { |
| 970 __ CheckAccessGlobalProxy(reg, scratch1, miss); | 970 __ CheckAccessGlobalProxy(reg, scratch1, miss); |
| 971 }; | 971 }; |
| 972 | 972 |
| 973 // If we've skipped any global objects, it's not enough to verify | 973 // If we've skipped any global objects, it's not enough to verify |
| 974 // that their maps haven't changed. We also need to check that the | 974 // that their maps haven't changed. We also need to check that the |
| 975 // property cell for the property is still empty. | 975 // property cell for the property is still empty. |
| (...skipping 14 matching lines...) Expand all Loading... |
| 990 JSObject* holder, | 990 JSObject* holder, |
| 991 Register receiver, | 991 Register receiver, |
| 992 Register scratch1, | 992 Register scratch1, |
| 993 Register scratch2, | 993 Register scratch2, |
| 994 Register scratch3, | 994 Register scratch3, |
| 995 int index, | 995 int index, |
| 996 String* name, | 996 String* name, |
| 997 Label* miss) { | 997 Label* miss) { |
| 998 // Check that the receiver isn't a smi. | 998 // Check that the receiver isn't a smi. |
| 999 __ test(receiver, Immediate(kSmiTagMask)); | 999 __ test(receiver, Immediate(kSmiTagMask)); |
| 1000 __ j(zero, miss, not_taken); | 1000 __ j(zero, miss, Label::kFar, not_taken); |
| 1001 | 1001 |
| 1002 // Check the prototype chain. | 1002 // Check the prototype chain. |
| 1003 Register reg = | 1003 Register reg = |
| 1004 CheckPrototypes(object, receiver, holder, | 1004 CheckPrototypes(object, receiver, holder, |
| 1005 scratch1, scratch2, scratch3, name, miss); | 1005 scratch1, scratch2, scratch3, name, miss); |
| 1006 | 1006 |
| 1007 // Get the value from the properties. | 1007 // Get the value from the properties. |
| 1008 GenerateFastPropertyLoad(masm(), eax, reg, holder, index); | 1008 GenerateFastPropertyLoad(masm(), eax, reg, holder, index); |
| 1009 __ ret(0); | 1009 __ ret(0); |
| 1010 } | 1010 } |
| 1011 | 1011 |
| 1012 | 1012 |
| 1013 MaybeObject* StubCompiler::GenerateLoadCallback(JSObject* object, | 1013 MaybeObject* StubCompiler::GenerateLoadCallback(JSObject* object, |
| 1014 JSObject* holder, | 1014 JSObject* holder, |
| 1015 Register receiver, | 1015 Register receiver, |
| 1016 Register name_reg, | 1016 Register name_reg, |
| 1017 Register scratch1, | 1017 Register scratch1, |
| 1018 Register scratch2, | 1018 Register scratch2, |
| 1019 Register scratch3, | 1019 Register scratch3, |
| 1020 AccessorInfo* callback, | 1020 AccessorInfo* callback, |
| 1021 String* name, | 1021 String* name, |
| 1022 Label* miss) { | 1022 Label* miss) { |
| 1023 // Check that the receiver isn't a smi. | 1023 // Check that the receiver isn't a smi. |
| 1024 __ test(receiver, Immediate(kSmiTagMask)); | 1024 __ test(receiver, Immediate(kSmiTagMask)); |
| 1025 __ j(zero, miss, not_taken); | 1025 __ j(zero, miss, Label::kFar, not_taken); |
| 1026 | 1026 |
| 1027 // Check that the maps haven't changed. | 1027 // Check that the maps haven't changed. |
| 1028 Register reg = | 1028 Register reg = |
| 1029 CheckPrototypes(object, receiver, holder, scratch1, | 1029 CheckPrototypes(object, receiver, holder, scratch1, |
| 1030 scratch2, scratch3, name, miss); | 1030 scratch2, scratch3, name, miss); |
| 1031 | 1031 |
| 1032 Handle<AccessorInfo> callback_handle(callback); | 1032 Handle<AccessorInfo> callback_handle(callback); |
| 1033 | 1033 |
| 1034 // Insert additional parameters into the stack frame above return address. | 1034 // Insert additional parameters into the stack frame above return address. |
| 1035 ASSERT(!scratch3.is(reg)); | 1035 ASSERT(!scratch3.is(reg)); |
| (...skipping 46 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1082 JSObject* holder, | 1082 JSObject* holder, |
| 1083 Register receiver, | 1083 Register receiver, |
| 1084 Register scratch1, | 1084 Register scratch1, |
| 1085 Register scratch2, | 1085 Register scratch2, |
| 1086 Register scratch3, | 1086 Register scratch3, |
| 1087 Object* value, | 1087 Object* value, |
| 1088 String* name, | 1088 String* name, |
| 1089 Label* miss) { | 1089 Label* miss) { |
| 1090 // Check that the receiver isn't a smi. | 1090 // Check that the receiver isn't a smi. |
| 1091 __ test(receiver, Immediate(kSmiTagMask)); | 1091 __ test(receiver, Immediate(kSmiTagMask)); |
| 1092 __ j(zero, miss, not_taken); | 1092 __ j(zero, miss, Label::kFar, not_taken); |
| 1093 | 1093 |
| 1094 // Check that the maps haven't changed. | 1094 // Check that the maps haven't changed. |
| 1095 CheckPrototypes(object, receiver, holder, | 1095 CheckPrototypes(object, receiver, holder, |
| 1096 scratch1, scratch2, scratch3, name, miss); | 1096 scratch1, scratch2, scratch3, name, miss); |
| 1097 | 1097 |
| 1098 // Return the constant value. | 1098 // Return the constant value. |
| 1099 __ mov(eax, Handle<Object>(value)); | 1099 __ mov(eax, Handle<Object>(value)); |
| 1100 __ ret(0); | 1100 __ ret(0); |
| 1101 } | 1101 } |
| 1102 | 1102 |
| 1103 | 1103 |
| 1104 void StubCompiler::GenerateLoadInterceptor(JSObject* object, | 1104 void StubCompiler::GenerateLoadInterceptor(JSObject* object, |
| 1105 JSObject* interceptor_holder, | 1105 JSObject* interceptor_holder, |
| 1106 LookupResult* lookup, | 1106 LookupResult* lookup, |
| 1107 Register receiver, | 1107 Register receiver, |
| 1108 Register name_reg, | 1108 Register name_reg, |
| 1109 Register scratch1, | 1109 Register scratch1, |
| 1110 Register scratch2, | 1110 Register scratch2, |
| 1111 Register scratch3, | 1111 Register scratch3, |
| 1112 String* name, | 1112 String* name, |
| 1113 Label* miss) { | 1113 Label* miss) { |
| 1114 ASSERT(interceptor_holder->HasNamedInterceptor()); | 1114 ASSERT(interceptor_holder->HasNamedInterceptor()); |
| 1115 ASSERT(!interceptor_holder->GetNamedInterceptor()->getter()->IsUndefined()); | 1115 ASSERT(!interceptor_holder->GetNamedInterceptor()->getter()->IsUndefined()); |
| 1116 | 1116 |
| 1117 // Check that the receiver isn't a smi. | 1117 // Check that the receiver isn't a smi. |
| 1118 __ test(receiver, Immediate(kSmiTagMask)); | 1118 __ test(receiver, Immediate(kSmiTagMask)); |
| 1119 __ j(zero, miss, not_taken); | 1119 __ j(zero, miss, Label::kFar, not_taken); |
| 1120 | 1120 |
| 1121 // So far the most popular follow ups for interceptor loads are FIELD | 1121 // So far the most popular follow ups for interceptor loads are FIELD |
| 1122 // and CALLBACKS, so inline only them, other cases may be added | 1122 // and CALLBACKS, so inline only them, other cases may be added |
| 1123 // later. | 1123 // later. |
| 1124 bool compile_followup_inline = false; | 1124 bool compile_followup_inline = false; |
| 1125 if (lookup->IsProperty() && lookup->IsCacheable()) { | 1125 if (lookup->IsProperty() && lookup->IsCacheable()) { |
| 1126 if (lookup->type() == FIELD) { | 1126 if (lookup->type() == FIELD) { |
| 1127 compile_followup_inline = true; | 1127 compile_followup_inline = true; |
| 1128 } else if (lookup->type() == CALLBACKS && | 1128 } else if (lookup->type() == CALLBACKS && |
| 1129 lookup->GetCallbackObject()->IsAccessorInfo() && | 1129 lookup->GetCallbackObject()->IsAccessorInfo() && |
| (...skipping 108 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1238 ExternalReference(IC_Utility(IC::kLoadPropertyWithInterceptorForLoad), | 1238 ExternalReference(IC_Utility(IC::kLoadPropertyWithInterceptorForLoad), |
| 1239 isolate()); | 1239 isolate()); |
| 1240 __ TailCallExternalReference(ref, 5, 1); | 1240 __ TailCallExternalReference(ref, 5, 1); |
| 1241 } | 1241 } |
| 1242 } | 1242 } |
| 1243 | 1243 |
| 1244 | 1244 |
| 1245 void CallStubCompiler::GenerateNameCheck(String* name, Label* miss) { | 1245 void CallStubCompiler::GenerateNameCheck(String* name, Label* miss) { |
| 1246 if (kind_ == Code::KEYED_CALL_IC) { | 1246 if (kind_ == Code::KEYED_CALL_IC) { |
| 1247 __ cmp(Operand(ecx), Immediate(Handle<String>(name))); | 1247 __ cmp(Operand(ecx), Immediate(Handle<String>(name))); |
| 1248 __ j(not_equal, miss, not_taken); | 1248 __ j(not_equal, miss, Label::kFar, not_taken); |
| 1249 } | 1249 } |
| 1250 } | 1250 } |
| 1251 | 1251 |
| 1252 | 1252 |
| 1253 void CallStubCompiler::GenerateGlobalReceiverCheck(JSObject* object, | 1253 void CallStubCompiler::GenerateGlobalReceiverCheck(JSObject* object, |
| 1254 JSObject* holder, | 1254 JSObject* holder, |
| 1255 String* name, | 1255 String* name, |
| 1256 Label* miss) { | 1256 Label* miss) { |
| 1257 ASSERT(holder->IsGlobalObject()); | 1257 ASSERT(holder->IsGlobalObject()); |
| 1258 | 1258 |
| 1259 // Get the number of arguments. | 1259 // Get the number of arguments. |
| 1260 const int argc = arguments().immediate(); | 1260 const int argc = arguments().immediate(); |
| 1261 | 1261 |
| 1262 // Get the receiver from the stack. | 1262 // Get the receiver from the stack. |
| 1263 __ mov(edx, Operand(esp, (argc + 1) * kPointerSize)); | 1263 __ mov(edx, Operand(esp, (argc + 1) * kPointerSize)); |
| 1264 | 1264 |
| 1265 // If the object is the holder then we know that it's a global | 1265 // If the object is the holder then we know that it's a global |
| 1266 // object which can only happen for contextual calls. In this case, | 1266 // object which can only happen for contextual calls. In this case, |
| 1267 // the receiver cannot be a smi. | 1267 // the receiver cannot be a smi. |
| 1268 if (object != holder) { | 1268 if (object != holder) { |
| 1269 __ test(edx, Immediate(kSmiTagMask)); | 1269 __ test(edx, Immediate(kSmiTagMask)); |
| 1270 __ j(zero, miss, not_taken); | 1270 __ j(zero, miss, Label::kFar, not_taken); |
| 1271 } | 1271 } |
| 1272 | 1272 |
| 1273 // Check that the maps haven't changed. | 1273 // Check that the maps haven't changed. |
| 1274 CheckPrototypes(object, edx, holder, ebx, eax, edi, name, miss); | 1274 CheckPrototypes(object, edx, holder, ebx, eax, edi, name, miss); |
| 1275 } | 1275 } |
| 1276 | 1276 |
| 1277 | 1277 |
| 1278 void CallStubCompiler::GenerateLoadFunctionFromCell(JSGlobalPropertyCell* cell, | 1278 void CallStubCompiler::GenerateLoadFunctionFromCell(JSGlobalPropertyCell* cell, |
| 1279 JSFunction* function, | 1279 JSFunction* function, |
| 1280 Label* miss) { | 1280 Label* miss) { |
| 1281 // Get the value from the cell. | 1281 // Get the value from the cell. |
| 1282 if (Serializer::enabled()) { | 1282 if (Serializer::enabled()) { |
| 1283 __ mov(edi, Immediate(Handle<JSGlobalPropertyCell>(cell))); | 1283 __ mov(edi, Immediate(Handle<JSGlobalPropertyCell>(cell))); |
| 1284 __ mov(edi, FieldOperand(edi, JSGlobalPropertyCell::kValueOffset)); | 1284 __ mov(edi, FieldOperand(edi, JSGlobalPropertyCell::kValueOffset)); |
| 1285 } else { | 1285 } else { |
| 1286 __ mov(edi, Operand::Cell(Handle<JSGlobalPropertyCell>(cell))); | 1286 __ mov(edi, Operand::Cell(Handle<JSGlobalPropertyCell>(cell))); |
| 1287 } | 1287 } |
| 1288 | 1288 |
| 1289 // Check that the cell contains the same function. | 1289 // Check that the cell contains the same function. |
| 1290 if (isolate()->heap()->InNewSpace(function)) { | 1290 if (isolate()->heap()->InNewSpace(function)) { |
| 1291 // We can't embed a pointer to a function in new space so we have | 1291 // We can't embed a pointer to a function in new space so we have |
| 1292 // to verify that the shared function info is unchanged. This has | 1292 // to verify that the shared function info is unchanged. This has |
| 1293 // the nice side effect that multiple closures based on the same | 1293 // the nice side effect that multiple closures based on the same |
| 1294 // function can all use this call IC. Before we load through the | 1294 // function can all use this call IC. Before we load through the |
| 1295 // function, we have to verify that it still is a function. | 1295 // function, we have to verify that it still is a function. |
| 1296 __ test(edi, Immediate(kSmiTagMask)); | 1296 __ test(edi, Immediate(kSmiTagMask)); |
| 1297 __ j(zero, miss, not_taken); | 1297 __ j(zero, miss, Label::kFar, not_taken); |
| 1298 __ CmpObjectType(edi, JS_FUNCTION_TYPE, ebx); | 1298 __ CmpObjectType(edi, JS_FUNCTION_TYPE, ebx); |
| 1299 __ j(not_equal, miss, not_taken); | 1299 __ j(not_equal, miss, Label::kFar, not_taken); |
| 1300 | 1300 |
| 1301 // Check the shared function info. Make sure it hasn't changed. | 1301 // Check the shared function info. Make sure it hasn't changed. |
| 1302 __ cmp(FieldOperand(edi, JSFunction::kSharedFunctionInfoOffset), | 1302 __ cmp(FieldOperand(edi, JSFunction::kSharedFunctionInfoOffset), |
| 1303 Immediate(Handle<SharedFunctionInfo>(function->shared()))); | 1303 Immediate(Handle<SharedFunctionInfo>(function->shared()))); |
| 1304 __ j(not_equal, miss, not_taken); | 1304 __ j(not_equal, miss, Label::kFar, not_taken); |
| 1305 } else { | 1305 } else { |
| 1306 __ cmp(Operand(edi), Immediate(Handle<JSFunction>(function))); | 1306 __ cmp(Operand(edi), Immediate(Handle<JSFunction>(function))); |
| 1307 __ j(not_equal, miss, not_taken); | 1307 __ j(not_equal, miss, Label::kFar, not_taken); |
| 1308 } | 1308 } |
| 1309 } | 1309 } |
| 1310 | 1310 |
| 1311 | 1311 |
| 1312 MaybeObject* CallStubCompiler::GenerateMissBranch() { | 1312 MaybeObject* CallStubCompiler::GenerateMissBranch() { |
| 1313 MaybeObject* maybe_obj = | 1313 MaybeObject* maybe_obj = |
| 1314 isolate()->stub_cache()->ComputeCallMiss(arguments().immediate(), | 1314 isolate()->stub_cache()->ComputeCallMiss(arguments().immediate(), |
| 1315 kind_); | 1315 kind_); |
| 1316 Object* obj; | 1316 Object* obj; |
| 1317 if (!maybe_obj->ToObject(&obj)) return maybe_obj; | 1317 if (!maybe_obj->ToObject(&obj)) return maybe_obj; |
| (...skipping 17 matching lines...) Expand all Loading... |
| 1335 Label miss; | 1335 Label miss; |
| 1336 | 1336 |
| 1337 GenerateNameCheck(name, &miss); | 1337 GenerateNameCheck(name, &miss); |
| 1338 | 1338 |
| 1339 // Get the receiver from the stack. | 1339 // Get the receiver from the stack. |
| 1340 const int argc = arguments().immediate(); | 1340 const int argc = arguments().immediate(); |
| 1341 __ mov(edx, Operand(esp, (argc + 1) * kPointerSize)); | 1341 __ mov(edx, Operand(esp, (argc + 1) * kPointerSize)); |
| 1342 | 1342 |
| 1343 // Check that the receiver isn't a smi. | 1343 // Check that the receiver isn't a smi. |
| 1344 __ test(edx, Immediate(kSmiTagMask)); | 1344 __ test(edx, Immediate(kSmiTagMask)); |
| 1345 __ j(zero, &miss, not_taken); | 1345 __ j(zero, &miss, Label::kFar, not_taken); |
| 1346 | 1346 |
| 1347 // Do the right check and compute the holder register. | 1347 // Do the right check and compute the holder register. |
| 1348 Register reg = CheckPrototypes(object, edx, holder, ebx, eax, edi, | 1348 Register reg = CheckPrototypes(object, edx, holder, ebx, eax, edi, |
| 1349 name, &miss); | 1349 name, &miss); |
| 1350 | 1350 |
| 1351 GenerateFastPropertyLoad(masm(), edi, reg, holder, index); | 1351 GenerateFastPropertyLoad(masm(), edi, reg, holder, index); |
| 1352 | 1352 |
| 1353 // Check that the function really is a function. | 1353 // Check that the function really is a function. |
| 1354 __ test(edi, Immediate(kSmiTagMask)); | 1354 __ test(edi, Immediate(kSmiTagMask)); |
| 1355 __ j(zero, &miss, not_taken); | 1355 __ j(zero, &miss, Label::kFar, not_taken); |
| 1356 __ CmpObjectType(edi, JS_FUNCTION_TYPE, ebx); | 1356 __ CmpObjectType(edi, JS_FUNCTION_TYPE, ebx); |
| 1357 __ j(not_equal, &miss, not_taken); | 1357 __ j(not_equal, &miss, Label::kFar, not_taken); |
| 1358 | 1358 |
| 1359 // Patch the receiver on the stack with the global proxy if | 1359 // Patch the receiver on the stack with the global proxy if |
| 1360 // necessary. | 1360 // necessary. |
| 1361 if (object->IsGlobalObject()) { | 1361 if (object->IsGlobalObject()) { |
| 1362 __ mov(edx, FieldOperand(edx, GlobalObject::kGlobalReceiverOffset)); | 1362 __ mov(edx, FieldOperand(edx, GlobalObject::kGlobalReceiverOffset)); |
| 1363 __ mov(Operand(esp, (argc + 1) * kPointerSize), edx); | 1363 __ mov(Operand(esp, (argc + 1) * kPointerSize), edx); |
| 1364 } | 1364 } |
| 1365 | 1365 |
| 1366 // Invoke the function. | 1366 // Invoke the function. |
| 1367 __ InvokeFunction(edi, arguments(), JUMP_FUNCTION); | 1367 __ InvokeFunction(edi, arguments(), JUMP_FUNCTION); |
| (...skipping 744 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2112 Label miss, miss_before_stack_reserved; | 2112 Label miss, miss_before_stack_reserved; |
| 2113 | 2113 |
| 2114 GenerateNameCheck(name, &miss_before_stack_reserved); | 2114 GenerateNameCheck(name, &miss_before_stack_reserved); |
| 2115 | 2115 |
| 2116 // Get the receiver from the stack. | 2116 // Get the receiver from the stack. |
| 2117 const int argc = arguments().immediate(); | 2117 const int argc = arguments().immediate(); |
| 2118 __ mov(edx, Operand(esp, (argc + 1) * kPointerSize)); | 2118 __ mov(edx, Operand(esp, (argc + 1) * kPointerSize)); |
| 2119 | 2119 |
| 2120 // Check that the receiver isn't a smi. | 2120 // Check that the receiver isn't a smi. |
| 2121 __ test(edx, Immediate(kSmiTagMask)); | 2121 __ test(edx, Immediate(kSmiTagMask)); |
| 2122 __ j(zero, &miss_before_stack_reserved, not_taken); | 2122 __ j(zero, &miss_before_stack_reserved, Label::kFar, not_taken); |
| 2123 | 2123 |
| 2124 Counters* counters = isolate()->counters(); | 2124 Counters* counters = isolate()->counters(); |
| 2125 __ IncrementCounter(counters->call_const(), 1); | 2125 __ IncrementCounter(counters->call_const(), 1); |
| 2126 __ IncrementCounter(counters->call_const_fast_api(), 1); | 2126 __ IncrementCounter(counters->call_const_fast_api(), 1); |
| 2127 | 2127 |
| 2128 // Allocate space for v8::Arguments implicit values. Must be initialized | 2128 // Allocate space for v8::Arguments implicit values. Must be initialized |
| 2129 // before calling any runtime function. | 2129 // before calling any runtime function. |
| 2130 __ sub(Operand(esp), Immediate(kFastApiCallArguments * kPointerSize)); | 2130 __ sub(Operand(esp), Immediate(kFastApiCallArguments * kPointerSize)); |
| 2131 | 2131 |
| 2132 // Check that the maps haven't changed and find a Holder as a side effect. | 2132 // Check that the maps haven't changed and find a Holder as a side effect. |
| (...skipping 47 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2180 | 2180 |
| 2181 GenerateNameCheck(name, &miss); | 2181 GenerateNameCheck(name, &miss); |
| 2182 | 2182 |
| 2183 // Get the receiver from the stack. | 2183 // Get the receiver from the stack. |
| 2184 const int argc = arguments().immediate(); | 2184 const int argc = arguments().immediate(); |
| 2185 __ mov(edx, Operand(esp, (argc + 1) * kPointerSize)); | 2185 __ mov(edx, Operand(esp, (argc + 1) * kPointerSize)); |
| 2186 | 2186 |
| 2187 // Check that the receiver isn't a smi. | 2187 // Check that the receiver isn't a smi. |
| 2188 if (check != NUMBER_CHECK) { | 2188 if (check != NUMBER_CHECK) { |
| 2189 __ test(edx, Immediate(kSmiTagMask)); | 2189 __ test(edx, Immediate(kSmiTagMask)); |
| 2190 __ j(zero, &miss, not_taken); | 2190 __ j(zero, &miss, Label::kFar, not_taken); |
| 2191 } | 2191 } |
| 2192 | 2192 |
| 2193 // Make sure that it's okay not to patch the on stack receiver | 2193 // Make sure that it's okay not to patch the on stack receiver |
| 2194 // unless we're doing a receiver map check. | 2194 // unless we're doing a receiver map check. |
| 2195 ASSERT(!object->IsGlobalObject() || check == RECEIVER_MAP_CHECK); | 2195 ASSERT(!object->IsGlobalObject() || check == RECEIVER_MAP_CHECK); |
| 2196 | 2196 |
| 2197 SharedFunctionInfo* function_info = function->shared(); | 2197 SharedFunctionInfo* function_info = function->shared(); |
| 2198 switch (check) { | 2198 switch (check) { |
| 2199 case RECEIVER_MAP_CHECK: | 2199 case RECEIVER_MAP_CHECK: |
| 2200 __ IncrementCounter(isolate()->counters()->call_const(), 1); | 2200 __ IncrementCounter(isolate()->counters()->call_const(), 1); |
| (...skipping 11 matching lines...) Expand all Loading... |
| 2212 break; | 2212 break; |
| 2213 | 2213 |
| 2214 case STRING_CHECK: | 2214 case STRING_CHECK: |
| 2215 if (!function->IsBuiltin() && !function_info->strict_mode()) { | 2215 if (!function->IsBuiltin() && !function_info->strict_mode()) { |
| 2216 // Calling non-strict non-builtins with a value as the receiver | 2216 // Calling non-strict non-builtins with a value as the receiver |
| 2217 // requires boxing. | 2217 // requires boxing. |
| 2218 __ jmp(&miss); | 2218 __ jmp(&miss); |
| 2219 } else { | 2219 } else { |
| 2220 // Check that the object is a string or a symbol. | 2220 // Check that the object is a string or a symbol. |
| 2221 __ CmpObjectType(edx, FIRST_NONSTRING_TYPE, eax); | 2221 __ CmpObjectType(edx, FIRST_NONSTRING_TYPE, eax); |
| 2222 __ j(above_equal, &miss, not_taken); | 2222 __ j(above_equal, &miss, Label::kFar, not_taken); |
| 2223 // Check that the maps starting from the prototype haven't changed. | 2223 // Check that the maps starting from the prototype haven't changed. |
| 2224 GenerateDirectLoadGlobalFunctionPrototype( | 2224 GenerateDirectLoadGlobalFunctionPrototype( |
| 2225 masm(), Context::STRING_FUNCTION_INDEX, eax, &miss); | 2225 masm(), Context::STRING_FUNCTION_INDEX, eax, &miss); |
| 2226 CheckPrototypes(JSObject::cast(object->GetPrototype()), eax, holder, | 2226 CheckPrototypes(JSObject::cast(object->GetPrototype()), eax, holder, |
| 2227 ebx, edx, edi, name, &miss); | 2227 ebx, edx, edi, name, &miss); |
| 2228 } | 2228 } |
| 2229 break; | 2229 break; |
| 2230 | 2230 |
| 2231 case NUMBER_CHECK: { | 2231 case NUMBER_CHECK: { |
| 2232 if (!function->IsBuiltin() && !function_info->strict_mode()) { | 2232 if (!function->IsBuiltin() && !function_info->strict_mode()) { |
| 2233 // Calling non-strict non-builtins with a value as the receiver | 2233 // Calling non-strict non-builtins with a value as the receiver |
| 2234 // requires boxing. | 2234 // requires boxing. |
| 2235 __ jmp(&miss); | 2235 __ jmp(&miss); |
| 2236 } else { | 2236 } else { |
| 2237 Label fast; | 2237 Label fast; |
| 2238 // Check that the object is a smi or a heap number. | 2238 // Check that the object is a smi or a heap number. |
| 2239 __ test(edx, Immediate(kSmiTagMask)); | 2239 __ test(edx, Immediate(kSmiTagMask)); |
| 2240 __ j(zero, &fast, taken); | 2240 __ j(zero, &fast, Label::kFar, taken); |
| 2241 __ CmpObjectType(edx, HEAP_NUMBER_TYPE, eax); | 2241 __ CmpObjectType(edx, HEAP_NUMBER_TYPE, eax); |
| 2242 __ j(not_equal, &miss, not_taken); | 2242 __ j(not_equal, &miss, Label::kFar, not_taken); |
| 2243 __ bind(&fast); | 2243 __ bind(&fast); |
| 2244 // Check that the maps starting from the prototype haven't changed. | 2244 // Check that the maps starting from the prototype haven't changed. |
| 2245 GenerateDirectLoadGlobalFunctionPrototype( | 2245 GenerateDirectLoadGlobalFunctionPrototype( |
| 2246 masm(), Context::NUMBER_FUNCTION_INDEX, eax, &miss); | 2246 masm(), Context::NUMBER_FUNCTION_INDEX, eax, &miss); |
| 2247 CheckPrototypes(JSObject::cast(object->GetPrototype()), eax, holder, | 2247 CheckPrototypes(JSObject::cast(object->GetPrototype()), eax, holder, |
| 2248 ebx, edx, edi, name, &miss); | 2248 ebx, edx, edi, name, &miss); |
| 2249 } | 2249 } |
| 2250 break; | 2250 break; |
| 2251 } | 2251 } |
| 2252 | 2252 |
| 2253 case BOOLEAN_CHECK: { | 2253 case BOOLEAN_CHECK: { |
| 2254 if (!function->IsBuiltin() && !function_info->strict_mode()) { | 2254 if (!function->IsBuiltin() && !function_info->strict_mode()) { |
| 2255 // Calling non-strict non-builtins with a value as the receiver | 2255 // Calling non-strict non-builtins with a value as the receiver |
| 2256 // requires boxing. | 2256 // requires boxing. |
| 2257 __ jmp(&miss); | 2257 __ jmp(&miss); |
| 2258 } else { | 2258 } else { |
| 2259 Label fast; | 2259 Label fast; |
| 2260 // Check that the object is a boolean. | 2260 // Check that the object is a boolean. |
| 2261 __ cmp(edx, factory()->true_value()); | 2261 __ cmp(edx, factory()->true_value()); |
| 2262 __ j(equal, &fast, taken); | 2262 __ j(equal, &fast, Label::kFar, taken); |
| 2263 __ cmp(edx, factory()->false_value()); | 2263 __ cmp(edx, factory()->false_value()); |
| 2264 __ j(not_equal, &miss, not_taken); | 2264 __ j(not_equal, &miss, Label::kFar, not_taken); |
| 2265 __ bind(&fast); | 2265 __ bind(&fast); |
| 2266 // Check that the maps starting from the prototype haven't changed. | 2266 // Check that the maps starting from the prototype haven't changed. |
| 2267 GenerateDirectLoadGlobalFunctionPrototype( | 2267 GenerateDirectLoadGlobalFunctionPrototype( |
| 2268 masm(), Context::BOOLEAN_FUNCTION_INDEX, eax, &miss); | 2268 masm(), Context::BOOLEAN_FUNCTION_INDEX, eax, &miss); |
| 2269 CheckPrototypes(JSObject::cast(object->GetPrototype()), eax, holder, | 2269 CheckPrototypes(JSObject::cast(object->GetPrototype()), eax, holder, |
| 2270 ebx, edx, edi, name, &miss); | 2270 ebx, edx, edi, name, &miss); |
| 2271 } | 2271 } |
| 2272 break; | 2272 break; |
| 2273 } | 2273 } |
| 2274 | 2274 |
| (...skipping 47 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2322 edi, | 2322 edi, |
| 2323 eax, | 2323 eax, |
| 2324 &miss); | 2324 &miss); |
| 2325 if (result->IsFailure()) return result; | 2325 if (result->IsFailure()) return result; |
| 2326 | 2326 |
| 2327 // Restore receiver. | 2327 // Restore receiver. |
| 2328 __ mov(edx, Operand(esp, (argc + 1) * kPointerSize)); | 2328 __ mov(edx, Operand(esp, (argc + 1) * kPointerSize)); |
| 2329 | 2329 |
| 2330 // Check that the function really is a function. | 2330 // Check that the function really is a function. |
| 2331 __ test(eax, Immediate(kSmiTagMask)); | 2331 __ test(eax, Immediate(kSmiTagMask)); |
| 2332 __ j(zero, &miss, not_taken); | 2332 __ j(zero, &miss, Label::kFar, not_taken); |
| 2333 __ CmpObjectType(eax, JS_FUNCTION_TYPE, ebx); | 2333 __ CmpObjectType(eax, JS_FUNCTION_TYPE, ebx); |
| 2334 __ j(not_equal, &miss, not_taken); | 2334 __ j(not_equal, &miss, Label::kFar, not_taken); |
| 2335 | 2335 |
| 2336 // Patch the receiver on the stack with the global proxy if | 2336 // Patch the receiver on the stack with the global proxy if |
| 2337 // necessary. | 2337 // necessary. |
| 2338 if (object->IsGlobalObject()) { | 2338 if (object->IsGlobalObject()) { |
| 2339 __ mov(edx, FieldOperand(edx, GlobalObject::kGlobalReceiverOffset)); | 2339 __ mov(edx, FieldOperand(edx, GlobalObject::kGlobalReceiverOffset)); |
| 2340 __ mov(Operand(esp, (argc + 1) * kPointerSize), edx); | 2340 __ mov(Operand(esp, (argc + 1) * kPointerSize), edx); |
| 2341 } | 2341 } |
| 2342 | 2342 |
| 2343 // Invoke the function. | 2343 // Invoke the function. |
| 2344 __ mov(edi, eax); | 2344 __ mov(edi, eax); |
| (...skipping 116 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2461 // ----------- S t a t e ------------- | 2461 // ----------- S t a t e ------------- |
| 2462 // -- eax : value | 2462 // -- eax : value |
| 2463 // -- ecx : name | 2463 // -- ecx : name |
| 2464 // -- edx : receiver | 2464 // -- edx : receiver |
| 2465 // -- esp[0] : return address | 2465 // -- esp[0] : return address |
| 2466 // ----------------------------------- | 2466 // ----------------------------------- |
| 2467 Label miss; | 2467 Label miss; |
| 2468 | 2468 |
| 2469 // Check that the object isn't a smi. | 2469 // Check that the object isn't a smi. |
| 2470 __ test(edx, Immediate(kSmiTagMask)); | 2470 __ test(edx, Immediate(kSmiTagMask)); |
| 2471 __ j(zero, &miss, not_taken); | 2471 __ j(zero, &miss, Label::kFar, not_taken); |
| 2472 | 2472 |
| 2473 // Check that the map of the object hasn't changed. | 2473 // Check that the map of the object hasn't changed. |
| 2474 __ cmp(FieldOperand(edx, HeapObject::kMapOffset), | 2474 __ cmp(FieldOperand(edx, HeapObject::kMapOffset), |
| 2475 Immediate(Handle<Map>(object->map()))); | 2475 Immediate(Handle<Map>(object->map()))); |
| 2476 __ j(not_equal, &miss, not_taken); | 2476 __ j(not_equal, &miss, Label::kFar, not_taken); |
| 2477 | 2477 |
| 2478 // Perform global security token check if needed. | 2478 // Perform global security token check if needed. |
| 2479 if (object->IsJSGlobalProxy()) { | 2479 if (object->IsJSGlobalProxy()) { |
| 2480 __ CheckAccessGlobalProxy(edx, ebx, &miss); | 2480 __ CheckAccessGlobalProxy(edx, ebx, &miss); |
| 2481 } | 2481 } |
| 2482 | 2482 |
| 2483 // Stub never generated for non-global objects that require access | 2483 // Stub never generated for non-global objects that require access |
| 2484 // checks. | 2484 // checks. |
| 2485 ASSERT(object->IsJSGlobalProxy() || !object->IsAccessCheckNeeded()); | 2485 ASSERT(object->IsJSGlobalProxy() || !object->IsAccessCheckNeeded()); |
| 2486 | 2486 |
| (...skipping 24 matching lines...) Expand all Loading... |
| 2511 // ----------- S t a t e ------------- | 2511 // ----------- S t a t e ------------- |
| 2512 // -- eax : value | 2512 // -- eax : value |
| 2513 // -- ecx : name | 2513 // -- ecx : name |
| 2514 // -- edx : receiver | 2514 // -- edx : receiver |
| 2515 // -- esp[0] : return address | 2515 // -- esp[0] : return address |
| 2516 // ----------------------------------- | 2516 // ----------------------------------- |
| 2517 Label miss; | 2517 Label miss; |
| 2518 | 2518 |
| 2519 // Check that the object isn't a smi. | 2519 // Check that the object isn't a smi. |
| 2520 __ test(edx, Immediate(kSmiTagMask)); | 2520 __ test(edx, Immediate(kSmiTagMask)); |
| 2521 __ j(zero, &miss, not_taken); | 2521 __ j(zero, &miss, Label::kFar, not_taken); |
| 2522 | 2522 |
| 2523 // Check that the map of the object hasn't changed. | 2523 // Check that the map of the object hasn't changed. |
| 2524 __ cmp(FieldOperand(edx, HeapObject::kMapOffset), | 2524 __ cmp(FieldOperand(edx, HeapObject::kMapOffset), |
| 2525 Immediate(Handle<Map>(receiver->map()))); | 2525 Immediate(Handle<Map>(receiver->map()))); |
| 2526 __ j(not_equal, &miss, not_taken); | 2526 __ j(not_equal, &miss, Label::kFar, not_taken); |
| 2527 | 2527 |
| 2528 // Perform global security token check if needed. | 2528 // Perform global security token check if needed. |
| 2529 if (receiver->IsJSGlobalProxy()) { | 2529 if (receiver->IsJSGlobalProxy()) { |
| 2530 __ CheckAccessGlobalProxy(edx, ebx, &miss); | 2530 __ CheckAccessGlobalProxy(edx, ebx, &miss); |
| 2531 } | 2531 } |
| 2532 | 2532 |
| 2533 // Stub never generated for non-global objects that require access | 2533 // Stub never generated for non-global objects that require access |
| 2534 // checks. | 2534 // checks. |
| 2535 ASSERT(receiver->IsJSGlobalProxy() || !receiver->IsAccessCheckNeeded()); | 2535 ASSERT(receiver->IsJSGlobalProxy() || !receiver->IsAccessCheckNeeded()); |
| 2536 | 2536 |
| (...skipping 26 matching lines...) Expand all Loading... |
| 2563 // -- eax : value | 2563 // -- eax : value |
| 2564 // -- ecx : name | 2564 // -- ecx : name |
| 2565 // -- edx : receiver | 2565 // -- edx : receiver |
| 2566 // -- esp[0] : return address | 2566 // -- esp[0] : return address |
| 2567 // ----------------------------------- | 2567 // ----------------------------------- |
| 2568 Label miss; | 2568 Label miss; |
| 2569 | 2569 |
| 2570 // Check that the map of the global has not changed. | 2570 // Check that the map of the global has not changed. |
| 2571 __ cmp(FieldOperand(edx, HeapObject::kMapOffset), | 2571 __ cmp(FieldOperand(edx, HeapObject::kMapOffset), |
| 2572 Immediate(Handle<Map>(object->map()))); | 2572 Immediate(Handle<Map>(object->map()))); |
| 2573 __ j(not_equal, &miss, not_taken); | 2573 __ j(not_equal, &miss, Label::kFar, not_taken); |
| 2574 | 2574 |
| 2575 | 2575 |
| 2576 // Compute the cell operand to use. | 2576 // Compute the cell operand to use. |
| 2577 Operand cell_operand = Operand::Cell(Handle<JSGlobalPropertyCell>(cell)); | 2577 Operand cell_operand = Operand::Cell(Handle<JSGlobalPropertyCell>(cell)); |
| 2578 if (Serializer::enabled()) { | 2578 if (Serializer::enabled()) { |
| 2579 __ mov(ebx, Immediate(Handle<JSGlobalPropertyCell>(cell))); | 2579 __ mov(ebx, Immediate(Handle<JSGlobalPropertyCell>(cell))); |
| 2580 cell_operand = FieldOperand(ebx, JSGlobalPropertyCell::kValueOffset); | 2580 cell_operand = FieldOperand(ebx, JSGlobalPropertyCell::kValueOffset); |
| 2581 } | 2581 } |
| 2582 | 2582 |
| 2583 // Check that the value in the cell is not the hole. If it is, this | 2583 // Check that the value in the cell is not the hole. If it is, this |
| (...skipping 32 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2616 // -- edx : receiver | 2616 // -- edx : receiver |
| 2617 // -- esp[0] : return address | 2617 // -- esp[0] : return address |
| 2618 // ----------------------------------- | 2618 // ----------------------------------- |
| 2619 Label miss; | 2619 Label miss; |
| 2620 | 2620 |
| 2621 Counters* counters = isolate()->counters(); | 2621 Counters* counters = isolate()->counters(); |
| 2622 __ IncrementCounter(counters->keyed_store_field(), 1); | 2622 __ IncrementCounter(counters->keyed_store_field(), 1); |
| 2623 | 2623 |
| 2624 // Check that the name has not changed. | 2624 // Check that the name has not changed. |
| 2625 __ cmp(Operand(ecx), Immediate(Handle<String>(name))); | 2625 __ cmp(Operand(ecx), Immediate(Handle<String>(name))); |
| 2626 __ j(not_equal, &miss, not_taken); | 2626 __ j(not_equal, &miss, Label::kFar, not_taken); |
| 2627 | 2627 |
| 2628 // Generate store field code. Trashes the name register. | 2628 // Generate store field code. Trashes the name register. |
| 2629 GenerateStoreField(masm(), | 2629 GenerateStoreField(masm(), |
| 2630 object, | 2630 object, |
| 2631 index, | 2631 index, |
| 2632 transition, | 2632 transition, |
| 2633 edx, ecx, ebx, | 2633 edx, ecx, ebx, |
| 2634 &miss); | 2634 &miss); |
| 2635 | 2635 |
| 2636 // Handle store cache miss. | 2636 // Handle store cache miss. |
| (...skipping 12 matching lines...) Expand all Loading... |
| 2649 // ----------- S t a t e ------------- | 2649 // ----------- S t a t e ------------- |
| 2650 // -- eax : value | 2650 // -- eax : value |
| 2651 // -- ecx : key | 2651 // -- ecx : key |
| 2652 // -- edx : receiver | 2652 // -- edx : receiver |
| 2653 // -- esp[0] : return address | 2653 // -- esp[0] : return address |
| 2654 // ----------------------------------- | 2654 // ----------------------------------- |
| 2655 Label miss; | 2655 Label miss; |
| 2656 | 2656 |
| 2657 // Check that the receiver isn't a smi. | 2657 // Check that the receiver isn't a smi. |
| 2658 __ test(edx, Immediate(kSmiTagMask)); | 2658 __ test(edx, Immediate(kSmiTagMask)); |
| 2659 __ j(zero, &miss, not_taken); | 2659 __ j(zero, &miss, Label::kFar, not_taken); |
| 2660 | 2660 |
| 2661 // Check that the map matches. | 2661 // Check that the map matches. |
| 2662 __ cmp(FieldOperand(edx, HeapObject::kMapOffset), | 2662 __ cmp(FieldOperand(edx, HeapObject::kMapOffset), |
| 2663 Immediate(Handle<Map>(receiver->map()))); | 2663 Immediate(Handle<Map>(receiver->map()))); |
| 2664 __ j(not_equal, &miss, not_taken); | 2664 __ j(not_equal, &miss, Label::kFar, not_taken); |
| 2665 | 2665 |
| 2666 // Check that the key is a smi. | 2666 // Check that the key is a smi. |
| 2667 __ test(ecx, Immediate(kSmiTagMask)); | 2667 __ test(ecx, Immediate(kSmiTagMask)); |
| 2668 __ j(not_zero, &miss, not_taken); | 2668 __ j(not_zero, &miss, Label::kFar, not_taken); |
| 2669 | 2669 |
| 2670 // Get the elements array and make sure it is a fast element array, not 'cow'. | 2670 // Get the elements array and make sure it is a fast element array, not 'cow'. |
| 2671 __ mov(edi, FieldOperand(edx, JSObject::kElementsOffset)); | 2671 __ mov(edi, FieldOperand(edx, JSObject::kElementsOffset)); |
| 2672 __ cmp(FieldOperand(edi, HeapObject::kMapOffset), | 2672 __ cmp(FieldOperand(edi, HeapObject::kMapOffset), |
| 2673 Immediate(factory()->fixed_array_map())); | 2673 Immediate(factory()->fixed_array_map())); |
| 2674 __ j(not_equal, &miss, not_taken); | 2674 __ j(not_equal, &miss, Label::kFar, not_taken); |
| 2675 | 2675 |
| 2676 // Check that the key is within bounds. | 2676 // Check that the key is within bounds. |
| 2677 if (receiver->IsJSArray()) { | 2677 if (receiver->IsJSArray()) { |
| 2678 __ cmp(ecx, FieldOperand(edx, JSArray::kLengthOffset)); // Compare smis. | 2678 __ cmp(ecx, FieldOperand(edx, JSArray::kLengthOffset)); // Compare smis. |
| 2679 __ j(above_equal, &miss, not_taken); | 2679 __ j(above_equal, &miss, Label::kFar, not_taken); |
| 2680 } else { | 2680 } else { |
| 2681 __ cmp(ecx, FieldOperand(edi, FixedArray::kLengthOffset)); // Compare smis. | 2681 __ cmp(ecx, FieldOperand(edi, FixedArray::kLengthOffset)); // Compare smis. |
| 2682 __ j(above_equal, &miss, not_taken); | 2682 __ j(above_equal, &miss, Label::kFar, not_taken); |
| 2683 } | 2683 } |
| 2684 | 2684 |
| 2685 // Do the store and update the write barrier. Make sure to preserve | 2685 // Do the store and update the write barrier. Make sure to preserve |
| 2686 // the value in register eax. | 2686 // the value in register eax. |
| 2687 __ mov(edx, Operand(eax)); | 2687 __ mov(edx, Operand(eax)); |
| 2688 __ mov(FieldOperand(edi, ecx, times_2, FixedArray::kHeaderSize), eax); | 2688 __ mov(FieldOperand(edi, ecx, times_2, FixedArray::kHeaderSize), eax); |
| 2689 __ RecordWrite(edi, 0, edx, ecx); | 2689 __ RecordWrite(edi, 0, edx, ecx); |
| 2690 | 2690 |
| 2691 // Done. | 2691 // Done. |
| 2692 __ ret(0); | 2692 __ ret(0); |
| (...skipping 13 matching lines...) Expand all Loading... |
| 2706 JSObject* last) { | 2706 JSObject* last) { |
| 2707 // ----------- S t a t e ------------- | 2707 // ----------- S t a t e ------------- |
| 2708 // -- eax : receiver | 2708 // -- eax : receiver |
| 2709 // -- ecx : name | 2709 // -- ecx : name |
| 2710 // -- esp[0] : return address | 2710 // -- esp[0] : return address |
| 2711 // ----------------------------------- | 2711 // ----------------------------------- |
| 2712 Label miss; | 2712 Label miss; |
| 2713 | 2713 |
| 2714 // Check that the receiver isn't a smi. | 2714 // Check that the receiver isn't a smi. |
| 2715 __ test(eax, Immediate(kSmiTagMask)); | 2715 __ test(eax, Immediate(kSmiTagMask)); |
| 2716 __ j(zero, &miss, not_taken); | 2716 __ j(zero, &miss, Label::kFar, not_taken); |
| 2717 | 2717 |
| 2718 ASSERT(last->IsGlobalObject() || last->HasFastProperties()); | 2718 ASSERT(last->IsGlobalObject() || last->HasFastProperties()); |
| 2719 | 2719 |
| 2720 // Check the maps of the full prototype chain. Also check that | 2720 // Check the maps of the full prototype chain. Also check that |
| 2721 // global property cells up to (but not including) the last object | 2721 // global property cells up to (but not including) the last object |
| 2722 // in the prototype chain are empty. | 2722 // in the prototype chain are empty. |
| 2723 CheckPrototypes(object, eax, last, ebx, edx, edi, name, &miss); | 2723 CheckPrototypes(object, eax, last, ebx, edx, edi, name, &miss); |
| 2724 | 2724 |
| 2725 // If the last object in the prototype chain is a global object, | 2725 // If the last object in the prototype chain is a global object, |
| 2726 // check that the global property cell is empty. | 2726 // check that the global property cell is empty. |
| (...skipping 132 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2859 // -- ecx : name | 2859 // -- ecx : name |
| 2860 // -- esp[0] : return address | 2860 // -- esp[0] : return address |
| 2861 // ----------------------------------- | 2861 // ----------------------------------- |
| 2862 Label miss; | 2862 Label miss; |
| 2863 | 2863 |
| 2864 // If the object is the holder then we know that it's a global | 2864 // If the object is the holder then we know that it's a global |
| 2865 // object which can only happen for contextual loads. In this case, | 2865 // object which can only happen for contextual loads. In this case, |
| 2866 // the receiver cannot be a smi. | 2866 // the receiver cannot be a smi. |
| 2867 if (object != holder) { | 2867 if (object != holder) { |
| 2868 __ test(eax, Immediate(kSmiTagMask)); | 2868 __ test(eax, Immediate(kSmiTagMask)); |
| 2869 __ j(zero, &miss, not_taken); | 2869 __ j(zero, &miss, Label::kFar, not_taken); |
| 2870 } | 2870 } |
| 2871 | 2871 |
| 2872 // Check that the maps haven't changed. | 2872 // Check that the maps haven't changed. |
| 2873 CheckPrototypes(object, eax, holder, ebx, edx, edi, name, &miss); | 2873 CheckPrototypes(object, eax, holder, ebx, edx, edi, name, &miss); |
| 2874 | 2874 |
| 2875 // Get the value from the cell. | 2875 // Get the value from the cell. |
| 2876 if (Serializer::enabled()) { | 2876 if (Serializer::enabled()) { |
| 2877 __ mov(ebx, Immediate(Handle<JSGlobalPropertyCell>(cell))); | 2877 __ mov(ebx, Immediate(Handle<JSGlobalPropertyCell>(cell))); |
| 2878 __ mov(ebx, FieldOperand(ebx, JSGlobalPropertyCell::kValueOffset)); | 2878 __ mov(ebx, FieldOperand(ebx, JSGlobalPropertyCell::kValueOffset)); |
| 2879 } else { | 2879 } else { |
| 2880 __ mov(ebx, Operand::Cell(Handle<JSGlobalPropertyCell>(cell))); | 2880 __ mov(ebx, Operand::Cell(Handle<JSGlobalPropertyCell>(cell))); |
| 2881 } | 2881 } |
| 2882 | 2882 |
| 2883 // Check for deleted property if property can actually be deleted. | 2883 // Check for deleted property if property can actually be deleted. |
| 2884 if (!is_dont_delete) { | 2884 if (!is_dont_delete) { |
| 2885 __ cmp(ebx, factory()->the_hole_value()); | 2885 __ cmp(ebx, factory()->the_hole_value()); |
| 2886 __ j(equal, &miss, not_taken); | 2886 __ j(equal, &miss, Label::kFar, not_taken); |
| 2887 } else if (FLAG_debug_code) { | 2887 } else if (FLAG_debug_code) { |
| 2888 __ cmp(ebx, factory()->the_hole_value()); | 2888 __ cmp(ebx, factory()->the_hole_value()); |
| 2889 __ Check(not_equal, "DontDelete cells can't contain the hole"); | 2889 __ Check(not_equal, "DontDelete cells can't contain the hole"); |
| 2890 } | 2890 } |
| 2891 | 2891 |
| 2892 Counters* counters = isolate()->counters(); | 2892 Counters* counters = isolate()->counters(); |
| 2893 __ IncrementCounter(counters->named_load_global_stub(), 1); | 2893 __ IncrementCounter(counters->named_load_global_stub(), 1); |
| 2894 __ mov(eax, ebx); | 2894 __ mov(eax, ebx); |
| 2895 __ ret(0); | 2895 __ ret(0); |
| 2896 | 2896 |
| (...skipping 15 matching lines...) Expand all Loading... |
| 2912 // -- edx : receiver | 2912 // -- edx : receiver |
| 2913 // -- esp[0] : return address | 2913 // -- esp[0] : return address |
| 2914 // ----------------------------------- | 2914 // ----------------------------------- |
| 2915 Label miss; | 2915 Label miss; |
| 2916 | 2916 |
| 2917 Counters* counters = isolate()->counters(); | 2917 Counters* counters = isolate()->counters(); |
| 2918 __ IncrementCounter(counters->keyed_load_field(), 1); | 2918 __ IncrementCounter(counters->keyed_load_field(), 1); |
| 2919 | 2919 |
| 2920 // Check that the name has not changed. | 2920 // Check that the name has not changed. |
| 2921 __ cmp(Operand(eax), Immediate(Handle<String>(name))); | 2921 __ cmp(Operand(eax), Immediate(Handle<String>(name))); |
| 2922 __ j(not_equal, &miss, not_taken); | 2922 __ j(not_equal, &miss, Label::kFar, not_taken); |
| 2923 | 2923 |
| 2924 GenerateLoadField(receiver, holder, edx, ebx, ecx, edi, index, name, &miss); | 2924 GenerateLoadField(receiver, holder, edx, ebx, ecx, edi, index, name, &miss); |
| 2925 | 2925 |
| 2926 __ bind(&miss); | 2926 __ bind(&miss); |
| 2927 __ DecrementCounter(counters->keyed_load_field(), 1); | 2927 __ DecrementCounter(counters->keyed_load_field(), 1); |
| 2928 GenerateLoadMiss(masm(), Code::KEYED_LOAD_IC); | 2928 GenerateLoadMiss(masm(), Code::KEYED_LOAD_IC); |
| 2929 | 2929 |
| 2930 // Return the generated code. | 2930 // Return the generated code. |
| 2931 return GetCode(FIELD, name); | 2931 return GetCode(FIELD, name); |
| 2932 } | 2932 } |
| 2933 | 2933 |
| 2934 | 2934 |
| 2935 MaybeObject* KeyedLoadStubCompiler::CompileLoadCallback( | 2935 MaybeObject* KeyedLoadStubCompiler::CompileLoadCallback( |
| 2936 String* name, | 2936 String* name, |
| 2937 JSObject* receiver, | 2937 JSObject* receiver, |
| 2938 JSObject* holder, | 2938 JSObject* holder, |
| 2939 AccessorInfo* callback) { | 2939 AccessorInfo* callback) { |
| 2940 // ----------- S t a t e ------------- | 2940 // ----------- S t a t e ------------- |
| 2941 // -- eax : key | 2941 // -- eax : key |
| 2942 // -- edx : receiver | 2942 // -- edx : receiver |
| 2943 // -- esp[0] : return address | 2943 // -- esp[0] : return address |
| 2944 // ----------------------------------- | 2944 // ----------------------------------- |
| 2945 Label miss; | 2945 Label miss; |
| 2946 | 2946 |
| 2947 Counters* counters = isolate()->counters(); | 2947 Counters* counters = isolate()->counters(); |
| 2948 __ IncrementCounter(counters->keyed_load_callback(), 1); | 2948 __ IncrementCounter(counters->keyed_load_callback(), 1); |
| 2949 | 2949 |
| 2950 // Check that the name has not changed. | 2950 // Check that the name has not changed. |
| 2951 __ cmp(Operand(eax), Immediate(Handle<String>(name))); | 2951 __ cmp(Operand(eax), Immediate(Handle<String>(name))); |
| 2952 __ j(not_equal, &miss, not_taken); | 2952 __ j(not_equal, &miss, Label::kFar, not_taken); |
| 2953 | 2953 |
| 2954 MaybeObject* result = GenerateLoadCallback(receiver, holder, edx, eax, ebx, | 2954 MaybeObject* result = GenerateLoadCallback(receiver, holder, edx, eax, ebx, |
| 2955 ecx, edi, callback, name, &miss); | 2955 ecx, edi, callback, name, &miss); |
| 2956 if (result->IsFailure()) { | 2956 if (result->IsFailure()) { |
| 2957 miss.Unuse(); | 2957 miss.Unuse(); |
| 2958 return result; | 2958 return result; |
| 2959 } | 2959 } |
| 2960 | 2960 |
| 2961 __ bind(&miss); | 2961 __ bind(&miss); |
| 2962 | 2962 |
| (...skipping 14 matching lines...) Expand all Loading... |
| 2977 // -- edx : receiver | 2977 // -- edx : receiver |
| 2978 // -- esp[0] : return address | 2978 // -- esp[0] : return address |
| 2979 // ----------------------------------- | 2979 // ----------------------------------- |
| 2980 Label miss; | 2980 Label miss; |
| 2981 | 2981 |
| 2982 Counters* counters = isolate()->counters(); | 2982 Counters* counters = isolate()->counters(); |
| 2983 __ IncrementCounter(counters->keyed_load_constant_function(), 1); | 2983 __ IncrementCounter(counters->keyed_load_constant_function(), 1); |
| 2984 | 2984 |
| 2985 // Check that the name has not changed. | 2985 // Check that the name has not changed. |
| 2986 __ cmp(Operand(eax), Immediate(Handle<String>(name))); | 2986 __ cmp(Operand(eax), Immediate(Handle<String>(name))); |
| 2987 __ j(not_equal, &miss, not_taken); | 2987 __ j(not_equal, &miss, Label::kFar, not_taken); |
| 2988 | 2988 |
| 2989 GenerateLoadConstant(receiver, holder, edx, ebx, ecx, edi, | 2989 GenerateLoadConstant(receiver, holder, edx, ebx, ecx, edi, |
| 2990 value, name, &miss); | 2990 value, name, &miss); |
| 2991 __ bind(&miss); | 2991 __ bind(&miss); |
| 2992 __ DecrementCounter(counters->keyed_load_constant_function(), 1); | 2992 __ DecrementCounter(counters->keyed_load_constant_function(), 1); |
| 2993 GenerateLoadMiss(masm(), Code::KEYED_LOAD_IC); | 2993 GenerateLoadMiss(masm(), Code::KEYED_LOAD_IC); |
| 2994 | 2994 |
| 2995 // Return the generated code. | 2995 // Return the generated code. |
| 2996 return GetCode(CONSTANT_FUNCTION, name); | 2996 return GetCode(CONSTANT_FUNCTION, name); |
| 2997 } | 2997 } |
| 2998 | 2998 |
| 2999 | 2999 |
| 3000 MaybeObject* KeyedLoadStubCompiler::CompileLoadInterceptor(JSObject* receiver, | 3000 MaybeObject* KeyedLoadStubCompiler::CompileLoadInterceptor(JSObject* receiver, |
| 3001 JSObject* holder, | 3001 JSObject* holder, |
| 3002 String* name) { | 3002 String* name) { |
| 3003 // ----------- S t a t e ------------- | 3003 // ----------- S t a t e ------------- |
| 3004 // -- eax : key | 3004 // -- eax : key |
| 3005 // -- edx : receiver | 3005 // -- edx : receiver |
| 3006 // -- esp[0] : return address | 3006 // -- esp[0] : return address |
| 3007 // ----------------------------------- | 3007 // ----------------------------------- |
| 3008 Label miss; | 3008 Label miss; |
| 3009 | 3009 |
| 3010 Counters* counters = isolate()->counters(); | 3010 Counters* counters = isolate()->counters(); |
| 3011 __ IncrementCounter(counters->keyed_load_interceptor(), 1); | 3011 __ IncrementCounter(counters->keyed_load_interceptor(), 1); |
| 3012 | 3012 |
| 3013 // Check that the name has not changed. | 3013 // Check that the name has not changed. |
| 3014 __ cmp(Operand(eax), Immediate(Handle<String>(name))); | 3014 __ cmp(Operand(eax), Immediate(Handle<String>(name))); |
| 3015 __ j(not_equal, &miss, not_taken); | 3015 __ j(not_equal, &miss, Label::kFar, not_taken); |
| 3016 | 3016 |
| 3017 LookupResult lookup; | 3017 LookupResult lookup; |
| 3018 LookupPostInterceptor(holder, name, &lookup); | 3018 LookupPostInterceptor(holder, name, &lookup); |
| 3019 GenerateLoadInterceptor(receiver, | 3019 GenerateLoadInterceptor(receiver, |
| 3020 holder, | 3020 holder, |
| 3021 &lookup, | 3021 &lookup, |
| 3022 edx, | 3022 edx, |
| 3023 eax, | 3023 eax, |
| 3024 ecx, | 3024 ecx, |
| 3025 ebx, | 3025 ebx, |
| (...skipping 15 matching lines...) Expand all Loading... |
| 3041 // -- edx : receiver | 3041 // -- edx : receiver |
| 3042 // -- esp[0] : return address | 3042 // -- esp[0] : return address |
| 3043 // ----------------------------------- | 3043 // ----------------------------------- |
| 3044 Label miss; | 3044 Label miss; |
| 3045 | 3045 |
| 3046 Counters* counters = isolate()->counters(); | 3046 Counters* counters = isolate()->counters(); |
| 3047 __ IncrementCounter(counters->keyed_load_array_length(), 1); | 3047 __ IncrementCounter(counters->keyed_load_array_length(), 1); |
| 3048 | 3048 |
| 3049 // Check that the name has not changed. | 3049 // Check that the name has not changed. |
| 3050 __ cmp(Operand(eax), Immediate(Handle<String>(name))); | 3050 __ cmp(Operand(eax), Immediate(Handle<String>(name))); |
| 3051 __ j(not_equal, &miss, not_taken); | 3051 __ j(not_equal, &miss, Label::kFar, not_taken); |
| 3052 | 3052 |
| 3053 GenerateLoadArrayLength(masm(), edx, ecx, &miss); | 3053 GenerateLoadArrayLength(masm(), edx, ecx, &miss); |
| 3054 __ bind(&miss); | 3054 __ bind(&miss); |
| 3055 __ DecrementCounter(counters->keyed_load_array_length(), 1); | 3055 __ DecrementCounter(counters->keyed_load_array_length(), 1); |
| 3056 GenerateLoadMiss(masm(), Code::KEYED_LOAD_IC); | 3056 GenerateLoadMiss(masm(), Code::KEYED_LOAD_IC); |
| 3057 | 3057 |
| 3058 // Return the generated code. | 3058 // Return the generated code. |
| 3059 return GetCode(CALLBACKS, name); | 3059 return GetCode(CALLBACKS, name); |
| 3060 } | 3060 } |
| 3061 | 3061 |
| 3062 | 3062 |
| 3063 MaybeObject* KeyedLoadStubCompiler::CompileLoadStringLength(String* name) { | 3063 MaybeObject* KeyedLoadStubCompiler::CompileLoadStringLength(String* name) { |
| 3064 // ----------- S t a t e ------------- | 3064 // ----------- S t a t e ------------- |
| 3065 // -- eax : key | 3065 // -- eax : key |
| 3066 // -- edx : receiver | 3066 // -- edx : receiver |
| 3067 // -- esp[0] : return address | 3067 // -- esp[0] : return address |
| 3068 // ----------------------------------- | 3068 // ----------------------------------- |
| 3069 Label miss; | 3069 Label miss; |
| 3070 | 3070 |
| 3071 Counters* counters = isolate()->counters(); | 3071 Counters* counters = isolate()->counters(); |
| 3072 __ IncrementCounter(counters->keyed_load_string_length(), 1); | 3072 __ IncrementCounter(counters->keyed_load_string_length(), 1); |
| 3073 | 3073 |
| 3074 // Check that the name has not changed. | 3074 // Check that the name has not changed. |
| 3075 __ cmp(Operand(eax), Immediate(Handle<String>(name))); | 3075 __ cmp(Operand(eax), Immediate(Handle<String>(name))); |
| 3076 __ j(not_equal, &miss, not_taken); | 3076 __ j(not_equal, &miss, Label::kFar, not_taken); |
| 3077 | 3077 |
| 3078 GenerateLoadStringLength(masm(), edx, ecx, ebx, &miss, true); | 3078 GenerateLoadStringLength(masm(), edx, ecx, ebx, &miss, true); |
| 3079 __ bind(&miss); | 3079 __ bind(&miss); |
| 3080 __ DecrementCounter(counters->keyed_load_string_length(), 1); | 3080 __ DecrementCounter(counters->keyed_load_string_length(), 1); |
| 3081 GenerateLoadMiss(masm(), Code::KEYED_LOAD_IC); | 3081 GenerateLoadMiss(masm(), Code::KEYED_LOAD_IC); |
| 3082 | 3082 |
| 3083 // Return the generated code. | 3083 // Return the generated code. |
| 3084 return GetCode(CALLBACKS, name); | 3084 return GetCode(CALLBACKS, name); |
| 3085 } | 3085 } |
| 3086 | 3086 |
| 3087 | 3087 |
| 3088 MaybeObject* KeyedLoadStubCompiler::CompileLoadFunctionPrototype(String* name) { | 3088 MaybeObject* KeyedLoadStubCompiler::CompileLoadFunctionPrototype(String* name) { |
| 3089 // ----------- S t a t e ------------- | 3089 // ----------- S t a t e ------------- |
| 3090 // -- eax : key | 3090 // -- eax : key |
| 3091 // -- edx : receiver | 3091 // -- edx : receiver |
| 3092 // -- esp[0] : return address | 3092 // -- esp[0] : return address |
| 3093 // ----------------------------------- | 3093 // ----------------------------------- |
| 3094 Label miss; | 3094 Label miss; |
| 3095 | 3095 |
| 3096 Counters* counters = isolate()->counters(); | 3096 Counters* counters = isolate()->counters(); |
| 3097 __ IncrementCounter(counters->keyed_load_function_prototype(), 1); | 3097 __ IncrementCounter(counters->keyed_load_function_prototype(), 1); |
| 3098 | 3098 |
| 3099 // Check that the name has not changed. | 3099 // Check that the name has not changed. |
| 3100 __ cmp(Operand(eax), Immediate(Handle<String>(name))); | 3100 __ cmp(Operand(eax), Immediate(Handle<String>(name))); |
| 3101 __ j(not_equal, &miss, not_taken); | 3101 __ j(not_equal, &miss, Label::kFar, not_taken); |
| 3102 | 3102 |
| 3103 GenerateLoadFunctionPrototype(masm(), edx, ecx, ebx, &miss); | 3103 GenerateLoadFunctionPrototype(masm(), edx, ecx, ebx, &miss); |
| 3104 __ bind(&miss); | 3104 __ bind(&miss); |
| 3105 __ DecrementCounter(counters->keyed_load_function_prototype(), 1); | 3105 __ DecrementCounter(counters->keyed_load_function_prototype(), 1); |
| 3106 GenerateLoadMiss(masm(), Code::KEYED_LOAD_IC); | 3106 GenerateLoadMiss(masm(), Code::KEYED_LOAD_IC); |
| 3107 | 3107 |
| 3108 // Return the generated code. | 3108 // Return the generated code. |
| 3109 return GetCode(CALLBACKS, name); | 3109 return GetCode(CALLBACKS, name); |
| 3110 } | 3110 } |
| 3111 | 3111 |
| 3112 | 3112 |
| 3113 MaybeObject* KeyedLoadStubCompiler::CompileLoadSpecialized(JSObject* receiver) { | 3113 MaybeObject* KeyedLoadStubCompiler::CompileLoadSpecialized(JSObject* receiver) { |
| 3114 // ----------- S t a t e ------------- | 3114 // ----------- S t a t e ------------- |
| 3115 // -- eax : key | 3115 // -- eax : key |
| 3116 // -- edx : receiver | 3116 // -- edx : receiver |
| 3117 // -- esp[0] : return address | 3117 // -- esp[0] : return address |
| 3118 // ----------------------------------- | 3118 // ----------------------------------- |
| 3119 Label miss; | 3119 Label miss; |
| 3120 | 3120 |
| 3121 // Check that the receiver isn't a smi. | 3121 // Check that the receiver isn't a smi. |
| 3122 __ test(edx, Immediate(kSmiTagMask)); | 3122 __ test(edx, Immediate(kSmiTagMask)); |
| 3123 __ j(zero, &miss, not_taken); | 3123 __ j(zero, &miss, Label::kFar, not_taken); |
| 3124 | 3124 |
| 3125 // Check that the map matches. | 3125 // Check that the map matches. |
| 3126 __ cmp(FieldOperand(edx, HeapObject::kMapOffset), | 3126 __ cmp(FieldOperand(edx, HeapObject::kMapOffset), |
| 3127 Immediate(Handle<Map>(receiver->map()))); | 3127 Immediate(Handle<Map>(receiver->map()))); |
| 3128 __ j(not_equal, &miss, not_taken); | 3128 __ j(not_equal, &miss, Label::kFar, not_taken); |
| 3129 | 3129 |
| 3130 // Check that the key is a smi. | 3130 // Check that the key is a smi. |
| 3131 __ test(eax, Immediate(kSmiTagMask)); | 3131 __ test(eax, Immediate(kSmiTagMask)); |
| 3132 __ j(not_zero, &miss, not_taken); | 3132 __ j(not_zero, &miss, Label::kFar, not_taken); |
| 3133 | 3133 |
| 3134 // Get the elements array. | 3134 // Get the elements array. |
| 3135 __ mov(ecx, FieldOperand(edx, JSObject::kElementsOffset)); | 3135 __ mov(ecx, FieldOperand(edx, JSObject::kElementsOffset)); |
| 3136 __ AssertFastElements(ecx); | 3136 __ AssertFastElements(ecx); |
| 3137 | 3137 |
| 3138 // Check that the key is within bounds. | 3138 // Check that the key is within bounds. |
| 3139 __ cmp(eax, FieldOperand(ecx, FixedArray::kLengthOffset)); | 3139 __ cmp(eax, FieldOperand(ecx, FixedArray::kLengthOffset)); |
| 3140 __ j(above_equal, &miss, not_taken); | 3140 __ j(above_equal, &miss, Label::kFar, not_taken); |
| 3141 | 3141 |
| 3142 // Load the result and make sure it's not the hole. | 3142 // Load the result and make sure it's not the hole. |
| 3143 __ mov(ebx, Operand(ecx, eax, times_2, | 3143 __ mov(ebx, Operand(ecx, eax, times_2, |
| 3144 FixedArray::kHeaderSize - kHeapObjectTag)); | 3144 FixedArray::kHeaderSize - kHeapObjectTag)); |
| 3145 __ cmp(ebx, factory()->the_hole_value()); | 3145 __ cmp(ebx, factory()->the_hole_value()); |
| 3146 __ j(equal, &miss, not_taken); | 3146 __ j(equal, &miss, Label::kFar, not_taken); |
| 3147 __ mov(eax, ebx); | 3147 __ mov(eax, ebx); |
| 3148 __ ret(0); | 3148 __ ret(0); |
| 3149 | 3149 |
| 3150 __ bind(&miss); | 3150 __ bind(&miss); |
| 3151 GenerateLoadMiss(masm(), Code::KEYED_LOAD_IC); | 3151 GenerateLoadMiss(masm(), Code::KEYED_LOAD_IC); |
| 3152 | 3152 |
| 3153 // Return the generated code. | 3153 // Return the generated code. |
| 3154 return GetCode(NORMAL, NULL); | 3154 return GetCode(NORMAL, NULL); |
| 3155 } | 3155 } |
| 3156 | 3156 |
| 3157 | 3157 |
| 3158 // Specialized stub for constructing objects from functions which only have only | 3158 // Specialized stub for constructing objects from functions which only have only |
| 3159 // simple assignments of the form this.x = ...; in their body. | 3159 // simple assignments of the form this.x = ...; in their body. |
| 3160 MaybeObject* ConstructStubCompiler::CompileConstructStub(JSFunction* function) { | 3160 MaybeObject* ConstructStubCompiler::CompileConstructStub(JSFunction* function) { |
| 3161 // ----------- S t a t e ------------- | 3161 // ----------- S t a t e ------------- |
| 3162 // -- eax : argc | 3162 // -- eax : argc |
| 3163 // -- edi : constructor | 3163 // -- edi : constructor |
| 3164 // -- esp[0] : return address | 3164 // -- esp[0] : return address |
| 3165 // -- esp[4] : last argument | 3165 // -- esp[4] : last argument |
| 3166 // ----------------------------------- | 3166 // ----------------------------------- |
| 3167 Label generic_stub_call; | 3167 Label generic_stub_call; |
| 3168 #ifdef ENABLE_DEBUGGER_SUPPORT | 3168 #ifdef ENABLE_DEBUGGER_SUPPORT |
| 3169 // Check to see whether there are any break points in the function code. If | 3169 // Check to see whether there are any break points in the function code. If |
| 3170 // there are jump to the generic constructor stub which calls the actual | 3170 // there are jump to the generic constructor stub which calls the actual |
| 3171 // code for the function thereby hitting the break points. | 3171 // code for the function thereby hitting the break points. |
| 3172 __ mov(ebx, FieldOperand(edi, JSFunction::kSharedFunctionInfoOffset)); | 3172 __ mov(ebx, FieldOperand(edi, JSFunction::kSharedFunctionInfoOffset)); |
| 3173 __ mov(ebx, FieldOperand(ebx, SharedFunctionInfo::kDebugInfoOffset)); | 3173 __ mov(ebx, FieldOperand(ebx, SharedFunctionInfo::kDebugInfoOffset)); |
| 3174 __ cmp(ebx, factory()->undefined_value()); | 3174 __ cmp(ebx, factory()->undefined_value()); |
| 3175 __ j(not_equal, &generic_stub_call, not_taken); | 3175 __ j(not_equal, &generic_stub_call, Label::kFar, not_taken); |
| 3176 #endif | 3176 #endif |
| 3177 | 3177 |
| 3178 // Load the initial map and verify that it is in fact a map. | 3178 // Load the initial map and verify that it is in fact a map. |
| 3179 __ mov(ebx, FieldOperand(edi, JSFunction::kPrototypeOrInitialMapOffset)); | 3179 __ mov(ebx, FieldOperand(edi, JSFunction::kPrototypeOrInitialMapOffset)); |
| 3180 // Will both indicate a NULL and a Smi. | 3180 // Will both indicate a NULL and a Smi. |
| 3181 __ test(ebx, Immediate(kSmiTagMask)); | 3181 __ test(ebx, Immediate(kSmiTagMask)); |
| 3182 __ j(zero, &generic_stub_call); | 3182 __ j(zero, &generic_stub_call); |
| 3183 __ CmpObjectType(ebx, MAP_TYPE, ecx); | 3183 __ CmpObjectType(ebx, MAP_TYPE, ecx); |
| 3184 __ j(not_equal, &generic_stub_call); | 3184 __ j(not_equal, &generic_stub_call); |
| 3185 | 3185 |
| (...skipping 112 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 3298 JSObject*receiver, ExternalArrayType array_type, Code::Flags flags) { | 3298 JSObject*receiver, ExternalArrayType array_type, Code::Flags flags) { |
| 3299 // ----------- S t a t e ------------- | 3299 // ----------- S t a t e ------------- |
| 3300 // -- eax : key | 3300 // -- eax : key |
| 3301 // -- edx : receiver | 3301 // -- edx : receiver |
| 3302 // -- esp[0] : return address | 3302 // -- esp[0] : return address |
| 3303 // ----------------------------------- | 3303 // ----------------------------------- |
| 3304 Label slow, failed_allocation; | 3304 Label slow, failed_allocation; |
| 3305 | 3305 |
| 3306 // Check that the object isn't a smi. | 3306 // Check that the object isn't a smi. |
| 3307 __ test(edx, Immediate(kSmiTagMask)); | 3307 __ test(edx, Immediate(kSmiTagMask)); |
| 3308 __ j(zero, &slow, not_taken); | 3308 __ j(zero, &slow, Label::kFar, not_taken); |
| 3309 | 3309 |
| 3310 // Check that the key is a smi. | 3310 // Check that the key is a smi. |
| 3311 __ test(eax, Immediate(kSmiTagMask)); | 3311 __ test(eax, Immediate(kSmiTagMask)); |
| 3312 __ j(not_zero, &slow, not_taken); | 3312 __ j(not_zero, &slow, Label::kFar, not_taken); |
| 3313 | 3313 |
| 3314 // Check that the map matches. | 3314 // Check that the map matches. |
| 3315 __ CheckMap(edx, Handle<Map>(receiver->map()), &slow, false); | 3315 __ CheckMap(edx, Handle<Map>(receiver->map()), &slow, false); |
| 3316 __ mov(ebx, FieldOperand(edx, JSObject::kElementsOffset)); | 3316 __ mov(ebx, FieldOperand(edx, JSObject::kElementsOffset)); |
| 3317 | 3317 |
| 3318 // eax: key, known to be a smi. | 3318 // eax: key, known to be a smi. |
| 3319 // edx: receiver, known to be a JSObject. | 3319 // edx: receiver, known to be a JSObject. |
| 3320 // ebx: elements object, known to be an external array. | 3320 // ebx: elements object, known to be an external array. |
| 3321 // Check that the index is in range. | 3321 // Check that the index is in range. |
| 3322 __ mov(ecx, eax); | 3322 __ mov(ecx, eax); |
| (...skipping 171 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 3494 __ j(not_equal, &check_heap_number); | 3494 __ j(not_equal, &check_heap_number); |
| 3495 | 3495 |
| 3496 // smi case | 3496 // smi case |
| 3497 __ mov(ecx, eax); // Preserve the value in eax. Key is no longer needed. | 3497 __ mov(ecx, eax); // Preserve the value in eax. Key is no longer needed. |
| 3498 __ SmiUntag(ecx); | 3498 __ SmiUntag(ecx); |
| 3499 __ mov(edi, FieldOperand(edi, ExternalArray::kExternalPointerOffset)); | 3499 __ mov(edi, FieldOperand(edi, ExternalArray::kExternalPointerOffset)); |
| 3500 // ecx: base pointer of external storage | 3500 // ecx: base pointer of external storage |
| 3501 switch (array_type) { | 3501 switch (array_type) { |
| 3502 case kExternalPixelArray: | 3502 case kExternalPixelArray: |
| 3503 { // Clamp the value to [0..255]. | 3503 { // Clamp the value to [0..255]. |
| 3504 NearLabel done; | 3504 Label done; |
| 3505 __ test(ecx, Immediate(0xFFFFFF00)); | 3505 __ test(ecx, Immediate(0xFFFFFF00)); |
| 3506 __ j(zero, &done); | 3506 __ j(zero, &done, Label::kNear); |
| 3507 __ setcc(negative, ecx); // 1 if negative, 0 if positive. | 3507 __ setcc(negative, ecx); // 1 if negative, 0 if positive. |
| 3508 __ dec_b(ecx); // 0 if negative, 255 if positive. | 3508 __ dec_b(ecx); // 0 if negative, 255 if positive. |
| 3509 __ bind(&done); | 3509 __ bind(&done); |
| 3510 } | 3510 } |
| 3511 __ mov_b(Operand(edi, ebx, times_1, 0), ecx); | 3511 __ mov_b(Operand(edi, ebx, times_1, 0), ecx); |
| 3512 break; | 3512 break; |
| 3513 case kExternalByteArray: | 3513 case kExternalByteArray: |
| 3514 case kExternalUnsignedByteArray: | 3514 case kExternalUnsignedByteArray: |
| 3515 __ mov_b(Operand(edi, ebx, times_1, 0), ecx); | 3515 __ mov_b(Operand(edi, ebx, times_1, 0), ecx); |
| 3516 break; | 3516 break; |
| (...skipping 60 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 3577 if (CpuFeatures::IsSupported(SSE2)) { | 3577 if (CpuFeatures::IsSupported(SSE2)) { |
| 3578 if (array_type != kExternalIntArray && | 3578 if (array_type != kExternalIntArray && |
| 3579 array_type != kExternalUnsignedIntArray) { | 3579 array_type != kExternalUnsignedIntArray) { |
| 3580 ASSERT(CpuFeatures::IsSupported(SSE2)); | 3580 ASSERT(CpuFeatures::IsSupported(SSE2)); |
| 3581 CpuFeatures::Scope scope(SSE2); | 3581 CpuFeatures::Scope scope(SSE2); |
| 3582 __ cvttsd2si(ecx, FieldOperand(eax, HeapNumber::kValueOffset)); | 3582 __ cvttsd2si(ecx, FieldOperand(eax, HeapNumber::kValueOffset)); |
| 3583 // ecx: untagged integer value | 3583 // ecx: untagged integer value |
| 3584 switch (array_type) { | 3584 switch (array_type) { |
| 3585 case kExternalPixelArray: | 3585 case kExternalPixelArray: |
| 3586 { // Clamp the value to [0..255]. | 3586 { // Clamp the value to [0..255]. |
| 3587 NearLabel done; | 3587 Label done; |
| 3588 __ test(ecx, Immediate(0xFFFFFF00)); | 3588 __ test(ecx, Immediate(0xFFFFFF00)); |
| 3589 __ j(zero, &done); | 3589 __ j(zero, &done, Label::kNear); |
| 3590 __ setcc(negative, ecx); // 1 if negative, 0 if positive. | 3590 __ setcc(negative, ecx); // 1 if negative, 0 if positive. |
| 3591 __ dec_b(ecx); // 0 if negative, 255 if positive. | 3591 __ dec_b(ecx); // 0 if negative, 255 if positive. |
| 3592 __ bind(&done); | 3592 __ bind(&done); |
| 3593 } | 3593 } |
| 3594 __ mov_b(Operand(edi, ebx, times_1, 0), ecx); | 3594 __ mov_b(Operand(edi, ebx, times_1, 0), ecx); |
| 3595 break; | 3595 break; |
| 3596 case kExternalByteArray: | 3596 case kExternalByteArray: |
| 3597 case kExternalUnsignedByteArray: | 3597 case kExternalUnsignedByteArray: |
| 3598 __ mov_b(Operand(edi, ebx, times_1, 0), ecx); | 3598 __ mov_b(Operand(edi, ebx, times_1, 0), ecx); |
| 3599 break; | 3599 break; |
| (...skipping 65 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 3665 | 3665 |
| 3666 return GetCode(flags); | 3666 return GetCode(flags); |
| 3667 } | 3667 } |
| 3668 | 3668 |
| 3669 | 3669 |
| 3670 #undef __ | 3670 #undef __ |
| 3671 | 3671 |
| 3672 } } // namespace v8::internal | 3672 } } // namespace v8::internal |
| 3673 | 3673 |
| 3674 #endif // V8_TARGET_ARCH_IA32 | 3674 #endif // V8_TARGET_ARCH_IA32 |
| OLD | NEW |