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