| OLD | NEW | 
|---|
| 1 // Copyright 2012 the V8 project authors. All rights reserved. | 1 // Copyright 2012 the V8 project authors. All rights reserved. | 
| 2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be | 
| 3 // found in the LICENSE file. | 3 // found in the LICENSE file. | 
| 4 | 4 | 
| 5 #if V8_TARGET_ARCH_IA32 | 5 #if V8_TARGET_ARCH_IA32 | 
| 6 | 6 | 
| 7 #include "src/code-stubs.h" | 7 #include "src/code-stubs.h" | 
| 8 #include "src/api-arguments.h" | 8 #include "src/api-arguments.h" | 
| 9 #include "src/base/bits.h" | 9 #include "src/base/bits.h" | 
| 10 #include "src/bootstrapper.h" | 10 #include "src/bootstrapper.h" | 
| (...skipping 2028 matching lines...) Expand 10 before | Expand all | Expand 10 after  Loading... | 
| 2039   __ pop(esi); | 2039   __ pop(esi); | 
| 2040   __ pop(edi); | 2040   __ pop(edi); | 
| 2041   __ add(esp, Immediate(2 * kPointerSize));  // remove markers | 2041   __ add(esp, Immediate(2 * kPointerSize));  // remove markers | 
| 2042 | 2042 | 
| 2043   // Restore frame pointer and return. | 2043   // Restore frame pointer and return. | 
| 2044   __ pop(ebp); | 2044   __ pop(ebp); | 
| 2045   __ ret(0); | 2045   __ ret(0); | 
| 2046 } | 2046 } | 
| 2047 | 2047 | 
| 2048 | 2048 | 
| 2049 void InstanceOfStub::Generate(MacroAssembler* masm) { |  | 
| 2050   Register const object = edx;                       // Object (lhs). |  | 
| 2051   Register const function = eax;                     // Function (rhs). |  | 
| 2052   Register const object_map = ecx;                   // Map of {object}. |  | 
| 2053   Register const function_map = ebx;                 // Map of {function}. |  | 
| 2054   Register const function_prototype = function_map;  // Prototype of {function}. |  | 
| 2055   Register const scratch = edi; |  | 
| 2056 |  | 
| 2057   DCHECK(object.is(InstanceOfDescriptor::LeftRegister())); |  | 
| 2058   DCHECK(function.is(InstanceOfDescriptor::RightRegister())); |  | 
| 2059 |  | 
| 2060   // Check if {object} is a smi. |  | 
| 2061   Label object_is_smi; |  | 
| 2062   __ JumpIfSmi(object, &object_is_smi, Label::kNear); |  | 
| 2063 |  | 
| 2064   // Lookup the {function} and the {object} map in the global instanceof cache. |  | 
| 2065   // Note: This is safe because we clear the global instanceof cache whenever |  | 
| 2066   // we change the prototype of any object. |  | 
| 2067   Label fast_case, slow_case; |  | 
| 2068   __ mov(object_map, FieldOperand(object, HeapObject::kMapOffset)); |  | 
| 2069   __ CompareRoot(function, scratch, Heap::kInstanceofCacheFunctionRootIndex); |  | 
| 2070   __ j(not_equal, &fast_case, Label::kNear); |  | 
| 2071   __ CompareRoot(object_map, scratch, Heap::kInstanceofCacheMapRootIndex); |  | 
| 2072   __ j(not_equal, &fast_case, Label::kNear); |  | 
| 2073   __ LoadRoot(eax, Heap::kInstanceofCacheAnswerRootIndex); |  | 
| 2074   __ ret(0); |  | 
| 2075 |  | 
| 2076   // If {object} is a smi we can safely return false if {function} is a JS |  | 
| 2077   // function, otherwise we have to miss to the runtime and throw an exception. |  | 
| 2078   __ bind(&object_is_smi); |  | 
| 2079   __ JumpIfSmi(function, &slow_case); |  | 
| 2080   __ CmpObjectType(function, JS_FUNCTION_TYPE, function_map); |  | 
| 2081   __ j(not_equal, &slow_case); |  | 
| 2082   __ LoadRoot(eax, Heap::kFalseValueRootIndex); |  | 
| 2083   __ ret(0); |  | 
| 2084 |  | 
| 2085   // Fast-case: The {function} must be a valid JSFunction. |  | 
| 2086   __ bind(&fast_case); |  | 
| 2087   __ JumpIfSmi(function, &slow_case); |  | 
| 2088   __ CmpObjectType(function, JS_FUNCTION_TYPE, function_map); |  | 
| 2089   __ j(not_equal, &slow_case); |  | 
| 2090 |  | 
| 2091   // Go to the runtime if the function is not a constructor. |  | 
| 2092   __ test_b(FieldOperand(function_map, Map::kBitFieldOffset), |  | 
| 2093             Immediate(1 << Map::kIsConstructor)); |  | 
| 2094   __ j(zero, &slow_case); |  | 
| 2095 |  | 
| 2096   // Ensure that {function} has an instance prototype. |  | 
| 2097   __ test_b(FieldOperand(function_map, Map::kBitFieldOffset), |  | 
| 2098             Immediate(1 << Map::kHasNonInstancePrototype)); |  | 
| 2099   __ j(not_zero, &slow_case); |  | 
| 2100 |  | 
| 2101   // Get the "prototype" (or initial map) of the {function}. |  | 
| 2102   __ mov(function_prototype, |  | 
| 2103          FieldOperand(function, JSFunction::kPrototypeOrInitialMapOffset)); |  | 
| 2104   __ AssertNotSmi(function_prototype); |  | 
| 2105 |  | 
| 2106   // Resolve the prototype if the {function} has an initial map.  Afterwards the |  | 
| 2107   // {function_prototype} will be either the JSReceiver prototype object or the |  | 
| 2108   // hole value, which means that no instances of the {function} were created so |  | 
| 2109   // far and hence we should return false. |  | 
| 2110   Label function_prototype_valid; |  | 
| 2111   Register const function_prototype_map = scratch; |  | 
| 2112   __ CmpObjectType(function_prototype, MAP_TYPE, function_prototype_map); |  | 
| 2113   __ j(not_equal, &function_prototype_valid, Label::kNear); |  | 
| 2114   __ mov(function_prototype, |  | 
| 2115          FieldOperand(function_prototype, Map::kPrototypeOffset)); |  | 
| 2116   __ bind(&function_prototype_valid); |  | 
| 2117   __ AssertNotSmi(function_prototype); |  | 
| 2118 |  | 
| 2119   // Update the global instanceof cache with the current {object} map and |  | 
| 2120   // {function}.  The cached answer will be set when it is known below. |  | 
| 2121   __ StoreRoot(function, scratch, Heap::kInstanceofCacheFunctionRootIndex); |  | 
| 2122   __ StoreRoot(object_map, scratch, Heap::kInstanceofCacheMapRootIndex); |  | 
| 2123 |  | 
| 2124   // Loop through the prototype chain looking for the {function} prototype. |  | 
| 2125   // Assume true, and change to false if not found. |  | 
| 2126   Label done, loop, fast_runtime_fallback; |  | 
| 2127   __ mov(eax, isolate()->factory()->true_value()); |  | 
| 2128   __ bind(&loop); |  | 
| 2129 |  | 
| 2130   // Check if the object needs to be access checked. |  | 
| 2131   __ test_b(FieldOperand(object_map, Map::kBitFieldOffset), |  | 
| 2132             Immediate(1 << Map::kIsAccessCheckNeeded)); |  | 
| 2133   __ j(not_zero, &fast_runtime_fallback, Label::kNear); |  | 
| 2134   // Check if the current object is a Proxy. |  | 
| 2135   __ CmpInstanceType(object_map, JS_PROXY_TYPE); |  | 
| 2136   __ j(equal, &fast_runtime_fallback, Label::kNear); |  | 
| 2137 |  | 
| 2138   __ mov(object, FieldOperand(object_map, Map::kPrototypeOffset)); |  | 
| 2139   __ cmp(object, function_prototype); |  | 
| 2140   __ j(equal, &done, Label::kNear); |  | 
| 2141   __ mov(object_map, FieldOperand(object, HeapObject::kMapOffset)); |  | 
| 2142   __ cmp(object, isolate()->factory()->null_value()); |  | 
| 2143   __ j(not_equal, &loop); |  | 
| 2144   __ mov(eax, isolate()->factory()->false_value()); |  | 
| 2145 |  | 
| 2146   __ bind(&done); |  | 
| 2147   __ StoreRoot(eax, scratch, Heap::kInstanceofCacheAnswerRootIndex); |  | 
| 2148   __ ret(0); |  | 
| 2149 |  | 
| 2150   // Found Proxy or access check needed: Call the runtime. |  | 
| 2151   __ bind(&fast_runtime_fallback); |  | 
| 2152   __ PopReturnAddressTo(scratch); |  | 
| 2153   __ Push(object); |  | 
| 2154   __ Push(function_prototype); |  | 
| 2155   __ PushReturnAddressFrom(scratch); |  | 
| 2156   // Invalidate the instanceof cache. |  | 
| 2157   __ Move(eax, Immediate(Smi::FromInt(0))); |  | 
| 2158   __ StoreRoot(eax, scratch, Heap::kInstanceofCacheFunctionRootIndex); |  | 
| 2159   __ TailCallRuntime(Runtime::kHasInPrototypeChain); |  | 
| 2160 |  | 
| 2161   // Slow-case: Call the %InstanceOf runtime function. |  | 
| 2162   __ bind(&slow_case); |  | 
| 2163   __ PopReturnAddressTo(scratch); |  | 
| 2164   __ Push(object); |  | 
| 2165   __ Push(function); |  | 
| 2166   __ PushReturnAddressFrom(scratch); |  | 
| 2167   __ TailCallRuntime(is_es6_instanceof() ? Runtime::kOrdinaryHasInstance |  | 
| 2168                                          : Runtime::kInstanceOf); |  | 
| 2169 } |  | 
| 2170 |  | 
| 2171 |  | 
| 2172 // ------------------------------------------------------------------------- | 2049 // ------------------------------------------------------------------------- | 
| 2173 // StringCharCodeAtGenerator | 2050 // StringCharCodeAtGenerator | 
| 2174 | 2051 | 
| 2175 void StringCharCodeAtGenerator::GenerateFast(MacroAssembler* masm) { | 2052 void StringCharCodeAtGenerator::GenerateFast(MacroAssembler* masm) { | 
| 2176   // If the receiver is a smi trigger the non-string case. | 2053   // If the receiver is a smi trigger the non-string case. | 
| 2177   STATIC_ASSERT(kSmiTag == 0); | 2054   STATIC_ASSERT(kSmiTag == 0); | 
| 2178   if (check_mode_ == RECEIVER_IS_UNKNOWN) { | 2055   if (check_mode_ == RECEIVER_IS_UNKNOWN) { | 
| 2179     __ JumpIfSmi(object_, receiver_not_string_); | 2056     __ JumpIfSmi(object_, receiver_not_string_); | 
| 2180 | 2057 | 
| 2181     // Fetch the instance type of the receiver into result register. | 2058     // Fetch the instance type of the receiver into result register. | 
| (...skipping 3663 matching lines...) Expand 10 before | Expand all | Expand 10 after  Loading... | 
| 5845                            kStackUnwindSpace, nullptr, return_value_operand, | 5722                            kStackUnwindSpace, nullptr, return_value_operand, | 
| 5846                            NULL); | 5723                            NULL); | 
| 5847 } | 5724 } | 
| 5848 | 5725 | 
| 5849 #undef __ | 5726 #undef __ | 
| 5850 | 5727 | 
| 5851 }  // namespace internal | 5728 }  // namespace internal | 
| 5852 }  // namespace v8 | 5729 }  // namespace v8 | 
| 5853 | 5730 | 
| 5854 #endif  // V8_TARGET_ARCH_IA32 | 5731 #endif  // V8_TARGET_ARCH_IA32 | 
| OLD | NEW | 
|---|