| OLD | NEW |
| 1 // Copyright 2006-2009 the V8 project authors. All rights reserved. | 1 // Copyright 2006-2009 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 640 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 651 __ mov(ip, Operand(argc)); | 651 __ mov(ip, Operand(argc)); |
| 652 __ str(ip, MemOperand(r0, 2 * kPointerSize)); | 652 __ str(ip, MemOperand(r0, 2 * kPointerSize)); |
| 653 // v8::Arguments::is_construct_call = 0 | 653 // v8::Arguments::is_construct_call = 0 |
| 654 __ mov(ip, Operand(0)); | 654 __ mov(ip, Operand(0)); |
| 655 __ str(ip, MemOperand(r0, 3 * kPointerSize)); | 655 __ str(ip, MemOperand(r0, 3 * kPointerSize)); |
| 656 | 656 |
| 657 // Emitting a stub call may try to allocate (if the code is not | 657 // Emitting a stub call may try to allocate (if the code is not |
| 658 // already generated). Do not allow the assembler to perform a | 658 // already generated). Do not allow the assembler to perform a |
| 659 // garbage collection but instead return the allocation failure | 659 // garbage collection but instead return the allocation failure |
| 660 // object. | 660 // object. |
| 661 MaybeObject* result = masm->TryCallApiFunctionAndReturn( | 661 const int kStackUnwindSpace = argc + kFastApiCallArguments + 1; |
| 662 &fun, argc + kFastApiCallArguments + 1); | 662 ExternalReference ref = |
| 663 if (result->IsFailure()) { | 663 ExternalReference(&fun, ExternalReference::DIRECT_API_CALL); |
| 664 return result; | 664 return masm->TryCallApiFunctionAndReturn(ref, kStackUnwindSpace); |
| 665 } | |
| 666 return HEAP->undefined_value(); | |
| 667 } | 665 } |
| 668 | 666 |
| 669 class CallInterceptorCompiler BASE_EMBEDDED { | 667 class CallInterceptorCompiler BASE_EMBEDDED { |
| 670 public: | 668 public: |
| 671 CallInterceptorCompiler(StubCompiler* stub_compiler, | 669 CallInterceptorCompiler(StubCompiler* stub_compiler, |
| 672 const ParameterCount& arguments, | 670 const ParameterCount& arguments, |
| 673 Register name) | 671 Register name) |
| 674 : stub_compiler_(stub_compiler), | 672 : stub_compiler_(stub_compiler), |
| 675 arguments_(arguments), | 673 arguments_(arguments), |
| 676 name_(name) {} | 674 name_(name) {} |
| (...skipping 564 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1241 Label* miss) { | 1239 Label* miss) { |
| 1242 // Check that the receiver isn't a smi. | 1240 // Check that the receiver isn't a smi. |
| 1243 __ tst(receiver, Operand(kSmiTagMask)); | 1241 __ tst(receiver, Operand(kSmiTagMask)); |
| 1244 __ b(eq, miss); | 1242 __ b(eq, miss); |
| 1245 | 1243 |
| 1246 // Check that the maps haven't changed. | 1244 // Check that the maps haven't changed. |
| 1247 Register reg = | 1245 Register reg = |
| 1248 CheckPrototypes(object, receiver, holder, scratch1, scratch2, scratch3, | 1246 CheckPrototypes(object, receiver, holder, scratch1, scratch2, scratch3, |
| 1249 name, miss); | 1247 name, miss); |
| 1250 | 1248 |
| 1251 // Push the arguments on the JS stack of the caller. | 1249 // Build AccessorInfo::args_ list on the stack and push property name below |
| 1252 __ push(receiver); // Receiver. | 1250 // the exit frame to make GC aware of them and store pointers to them. |
| 1253 __ mov(scratch3, Operand(Handle<AccessorInfo>(callback))); // callback data | 1251 __ push(receiver); |
| 1254 __ ldr(ip, FieldMemOperand(scratch3, AccessorInfo::kDataOffset)); | 1252 __ mov(scratch2, sp); // scratch2 = AccessorInfo::args_ |
| 1255 __ Push(reg, ip, scratch3, name_reg); | 1253 Handle<AccessorInfo> callback_handle(callback); |
| 1254 if (HEAP->InNewSpace(callback_handle->data())) { |
| 1255 __ Move(scratch3, callback_handle); |
| 1256 __ ldr(scratch3, FieldMemOperand(scratch3, AccessorInfo::kDataOffset)); |
| 1257 } else { |
| 1258 __ Move(scratch3, Handle<Object>(callback_handle->data())); |
| 1259 } |
| 1260 __ Push(reg, scratch3, name_reg); |
| 1261 __ mov(r0, sp); // r0 = Handle<String> |
| 1256 | 1262 |
| 1257 // Do tail-call to the runtime system. | 1263 Address getter_address = v8::ToCData<Address>(callback->getter()); |
| 1258 ExternalReference load_callback_property = | 1264 ApiFunction fun(getter_address); |
| 1259 ExternalReference(IC_Utility(IC::kLoadCallbackProperty)); | |
| 1260 __ TailCallExternalReference(load_callback_property, 5, 1); | |
| 1261 | 1265 |
| 1262 return HEAP->undefined_value(); // Success. | 1266 const int kApiStackSpace = 1; |
| 1267 __ EnterExitFrame(false, kApiStackSpace); |
| 1268 // Create AccessorInfo instance on the stack above the exit frame with |
| 1269 // scratch2 (internal::Object **args_) as the data. |
| 1270 __ str(scratch2, MemOperand(sp, 1 * kPointerSize)); |
| 1271 __ add(r1, sp, Operand(1 * kPointerSize)); // r1 = AccessorInfo& |
| 1272 |
| 1273 // Emitting a stub call may try to allocate (if the code is not |
| 1274 // already generated). Do not allow the assembler to perform a |
| 1275 // garbage collection but instead return the allocation failure |
| 1276 // object. |
| 1277 const int kStackUnwindSpace = 4; |
| 1278 ExternalReference ref = |
| 1279 ExternalReference(&fun, ExternalReference::DIRECT_GETTER_CALL); |
| 1280 return masm()->TryCallApiFunctionAndReturn(ref, kStackUnwindSpace); |
| 1263 } | 1281 } |
| 1264 | 1282 |
| 1265 | 1283 |
| 1266 void StubCompiler::GenerateLoadInterceptor(JSObject* object, | 1284 void StubCompiler::GenerateLoadInterceptor(JSObject* object, |
| 1267 JSObject* interceptor_holder, | 1285 JSObject* interceptor_holder, |
| 1268 LookupResult* lookup, | 1286 LookupResult* lookup, |
| 1269 Register receiver, | 1287 Register receiver, |
| 1270 Register name_reg, | 1288 Register name_reg, |
| 1271 Register scratch1, | 1289 Register scratch1, |
| 1272 Register scratch2, | 1290 Register scratch2, |
| (...skipping 1057 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2330 // Patch the receiver on the stack with the global proxy if | 2348 // Patch the receiver on the stack with the global proxy if |
| 2331 // necessary. | 2349 // necessary. |
| 2332 if (object->IsGlobalObject()) { | 2350 if (object->IsGlobalObject()) { |
| 2333 ASSERT(depth == kInvalidProtoDepth); | 2351 ASSERT(depth == kInvalidProtoDepth); |
| 2334 __ ldr(r3, FieldMemOperand(r1, GlobalObject::kGlobalReceiverOffset)); | 2352 __ ldr(r3, FieldMemOperand(r1, GlobalObject::kGlobalReceiverOffset)); |
| 2335 __ str(r3, MemOperand(sp, argc * kPointerSize)); | 2353 __ str(r3, MemOperand(sp, argc * kPointerSize)); |
| 2336 } | 2354 } |
| 2337 break; | 2355 break; |
| 2338 | 2356 |
| 2339 case STRING_CHECK: | 2357 case STRING_CHECK: |
| 2340 if (!function->IsBuiltin()) { | 2358 if (!function->IsBuiltin() && !function_info->strict_mode()) { |
| 2341 // Calling non-builtins with a value as receiver requires boxing. | 2359 // Calling non-strict non-builtins with a value as the receiver |
| 2360 // requires boxing. |
| 2342 __ jmp(&miss); | 2361 __ jmp(&miss); |
| 2343 } else { | 2362 } else { |
| 2344 // Check that the object is a two-byte string or a symbol. | 2363 // Check that the object is a two-byte string or a symbol. |
| 2345 __ CompareObjectType(r1, r3, r3, FIRST_NONSTRING_TYPE); | 2364 __ CompareObjectType(r1, r3, r3, FIRST_NONSTRING_TYPE); |
| 2346 __ b(hs, &miss); | 2365 __ b(hs, &miss); |
| 2347 // Check that the maps starting from the prototype haven't changed. | 2366 // Check that the maps starting from the prototype haven't changed. |
| 2348 GenerateDirectLoadGlobalFunctionPrototype( | 2367 GenerateDirectLoadGlobalFunctionPrototype( |
| 2349 masm(), Context::STRING_FUNCTION_INDEX, r0, &miss); | 2368 masm(), Context::STRING_FUNCTION_INDEX, r0, &miss); |
| 2350 CheckPrototypes(JSObject::cast(object->GetPrototype()), r0, holder, r3, | 2369 CheckPrototypes(JSObject::cast(object->GetPrototype()), r0, holder, r3, |
| 2351 r1, r4, name, &miss); | 2370 r1, r4, name, &miss); |
| 2352 } | 2371 } |
| 2353 break; | 2372 break; |
| 2354 | 2373 |
| 2355 case NUMBER_CHECK: { | 2374 case NUMBER_CHECK: { |
| 2356 if (!function->IsBuiltin()) { | 2375 if (!function->IsBuiltin() && !function_info->strict_mode()) { |
| 2357 // Calling non-builtins with a value as receiver requires boxing. | 2376 // Calling non-strict non-builtins with a value as the receiver |
| 2377 // requires boxing. |
| 2358 __ jmp(&miss); | 2378 __ jmp(&miss); |
| 2359 } else { | 2379 } else { |
| 2360 Label fast; | 2380 Label fast; |
| 2361 // Check that the object is a smi or a heap number. | 2381 // Check that the object is a smi or a heap number. |
| 2362 __ tst(r1, Operand(kSmiTagMask)); | 2382 __ tst(r1, Operand(kSmiTagMask)); |
| 2363 __ b(eq, &fast); | 2383 __ b(eq, &fast); |
| 2364 __ CompareObjectType(r1, r0, r0, HEAP_NUMBER_TYPE); | 2384 __ CompareObjectType(r1, r0, r0, HEAP_NUMBER_TYPE); |
| 2365 __ b(ne, &miss); | 2385 __ b(ne, &miss); |
| 2366 __ bind(&fast); | 2386 __ bind(&fast); |
| 2367 // Check that the maps starting from the prototype haven't changed. | 2387 // Check that the maps starting from the prototype haven't changed. |
| 2368 GenerateDirectLoadGlobalFunctionPrototype( | 2388 GenerateDirectLoadGlobalFunctionPrototype( |
| 2369 masm(), Context::NUMBER_FUNCTION_INDEX, r0, &miss); | 2389 masm(), Context::NUMBER_FUNCTION_INDEX, r0, &miss); |
| 2370 CheckPrototypes(JSObject::cast(object->GetPrototype()), r0, holder, r3, | 2390 CheckPrototypes(JSObject::cast(object->GetPrototype()), r0, holder, r3, |
| 2371 r1, r4, name, &miss); | 2391 r1, r4, name, &miss); |
| 2372 } | 2392 } |
| 2373 break; | 2393 break; |
| 2374 } | 2394 } |
| 2375 | 2395 |
| 2376 case BOOLEAN_CHECK: { | 2396 case BOOLEAN_CHECK: { |
| 2377 if (!function->IsBuiltin()) { | 2397 if (!function->IsBuiltin() && !function_info->strict_mode()) { |
| 2378 // Calling non-builtins with a value as receiver requires boxing. | 2398 // Calling non-strict non-builtins with a value as the receiver |
| 2399 // requires boxing. |
| 2379 __ jmp(&miss); | 2400 __ jmp(&miss); |
| 2380 } else { | 2401 } else { |
| 2381 Label fast; | 2402 Label fast; |
| 2382 // Check that the object is a boolean. | 2403 // Check that the object is a boolean. |
| 2383 __ LoadRoot(ip, Heap::kTrueValueRootIndex); | 2404 __ LoadRoot(ip, Heap::kTrueValueRootIndex); |
| 2384 __ cmp(r1, ip); | 2405 __ cmp(r1, ip); |
| 2385 __ b(eq, &fast); | 2406 __ b(eq, &fast); |
| 2386 __ LoadRoot(ip, Heap::kFalseValueRootIndex); | 2407 __ LoadRoot(ip, Heap::kFalseValueRootIndex); |
| 2387 __ cmp(r1, ip); | 2408 __ cmp(r1, ip); |
| 2388 __ b(ne, &miss); | 2409 __ b(ne, &miss); |
| (...skipping 261 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2650 if (receiver->IsJSGlobalProxy()) { | 2671 if (receiver->IsJSGlobalProxy()) { |
| 2651 __ CheckAccessGlobalProxy(r1, r3, &miss); | 2672 __ CheckAccessGlobalProxy(r1, r3, &miss); |
| 2652 } | 2673 } |
| 2653 | 2674 |
| 2654 // Stub is never generated for non-global objects that require access | 2675 // Stub is never generated for non-global objects that require access |
| 2655 // checks. | 2676 // checks. |
| 2656 ASSERT(receiver->IsJSGlobalProxy() || !receiver->IsAccessCheckNeeded()); | 2677 ASSERT(receiver->IsJSGlobalProxy() || !receiver->IsAccessCheckNeeded()); |
| 2657 | 2678 |
| 2658 __ Push(r1, r2, r0); // Receiver, name, value. | 2679 __ Push(r1, r2, r0); // Receiver, name, value. |
| 2659 | 2680 |
| 2681 __ mov(r0, Operand(Smi::FromInt(strict_mode_))); |
| 2682 __ push(r0); // strict mode |
| 2683 |
| 2660 // Do tail-call to the runtime system. | 2684 // Do tail-call to the runtime system. |
| 2661 ExternalReference store_ic_property = | 2685 ExternalReference store_ic_property = |
| 2662 ExternalReference(IC_Utility(IC::kStoreInterceptorProperty)); | 2686 ExternalReference(IC_Utility(IC::kStoreInterceptorProperty)); |
| 2663 __ TailCallExternalReference(store_ic_property, 3, 1); | 2687 __ TailCallExternalReference(store_ic_property, 4, 1); |
| 2664 | 2688 |
| 2665 // Handle store cache miss. | 2689 // Handle store cache miss. |
| 2666 __ bind(&miss); | 2690 __ bind(&miss); |
| 2667 Handle<Code> ic(Isolate::Current()->builtins()->builtin( | 2691 Handle<Code> ic(Isolate::Current()->builtins()->builtin( |
| 2668 Builtins::StoreIC_Miss)); | 2692 Builtins::StoreIC_Miss)); |
| 2669 __ Jump(ic, RelocInfo::CODE_TARGET); | 2693 __ Jump(ic, RelocInfo::CODE_TARGET); |
| 2670 | 2694 |
| 2671 // Return the generated code. | 2695 // Return the generated code. |
| 2672 return GetCode(INTERCEPTOR, name); | 2696 return GetCode(INTERCEPTOR, name); |
| 2673 } | 2697 } |
| (...skipping 590 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 3264 __ bind(&miss); | 3288 __ bind(&miss); |
| 3265 Handle<Code> ic( | 3289 Handle<Code> ic( |
| 3266 Isolate::Current()->builtins()->builtin(Builtins::KeyedStoreIC_Miss)); | 3290 Isolate::Current()->builtins()->builtin(Builtins::KeyedStoreIC_Miss)); |
| 3267 __ Jump(ic, RelocInfo::CODE_TARGET); | 3291 __ Jump(ic, RelocInfo::CODE_TARGET); |
| 3268 | 3292 |
| 3269 // Return the generated code. | 3293 // Return the generated code. |
| 3270 return GetCode(NORMAL, NULL); | 3294 return GetCode(NORMAL, NULL); |
| 3271 } | 3295 } |
| 3272 | 3296 |
| 3273 | 3297 |
| 3298 MaybeObject* KeyedStoreStubCompiler::CompileStorePixelArray( |
| 3299 JSObject* receiver) { |
| 3300 // ----------- S t a t e ------------- |
| 3301 // -- r0 : value |
| 3302 // -- r1 : key |
| 3303 // -- r2 : receiver |
| 3304 // -- r3 : scratch |
| 3305 // -- r4 : scratch |
| 3306 // -- r5 : scratch |
| 3307 // -- r6 : scratch |
| 3308 // -- lr : return address |
| 3309 // ----------------------------------- |
| 3310 Label miss; |
| 3311 |
| 3312 // Check that the map matches. |
| 3313 __ CheckMap(r2, r6, Handle<Map>(receiver->map()), &miss, false); |
| 3314 |
| 3315 GenerateFastPixelArrayStore(masm(), |
| 3316 r2, |
| 3317 r1, |
| 3318 r0, |
| 3319 r3, |
| 3320 r4, |
| 3321 r5, |
| 3322 r6, |
| 3323 true, |
| 3324 true, |
| 3325 &miss, |
| 3326 &miss, |
| 3327 NULL, |
| 3328 &miss); |
| 3329 |
| 3330 __ bind(&miss); |
| 3331 Handle<Code> ic(Isolate::Current()->builtins()->builtin( |
| 3332 Builtins::KeyedStoreIC_Miss)); |
| 3333 __ Jump(ic, RelocInfo::CODE_TARGET); |
| 3334 |
| 3335 // Return the generated code. |
| 3336 return GetCode(NORMAL, NULL); |
| 3337 } |
| 3338 |
| 3339 |
| 3274 MaybeObject* ConstructStubCompiler::CompileConstructStub(JSFunction* function) { | 3340 MaybeObject* ConstructStubCompiler::CompileConstructStub(JSFunction* function) { |
| 3275 // ----------- S t a t e ------------- | 3341 // ----------- S t a t e ------------- |
| 3276 // -- r0 : argc | 3342 // -- r0 : argc |
| 3277 // -- r1 : constructor | 3343 // -- r1 : constructor |
| 3278 // -- lr : return address | 3344 // -- lr : return address |
| 3279 // -- [sp] : last argument | 3345 // -- [sp] : last argument |
| 3280 // ----------------------------------- | 3346 // ----------------------------------- |
| 3281 Label generic_stub_call; | 3347 Label generic_stub_call; |
| 3282 | 3348 |
| 3283 // Use r7 for holding undefined which is used in several places below. | 3349 // Use r7 for holding undefined which is used in several places below. |
| (...skipping 716 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 4000 // ---------- S t a t e -------------- | 4066 // ---------- S t a t e -------------- |
| 4001 // -- r0 : value | 4067 // -- r0 : value |
| 4002 // -- r1 : key | 4068 // -- r1 : key |
| 4003 // -- r2 : receiver | 4069 // -- r2 : receiver |
| 4004 // -- lr : return address | 4070 // -- lr : return address |
| 4005 // ----------------------------------- | 4071 // ----------------------------------- |
| 4006 | 4072 |
| 4007 // Push receiver, key and value for runtime call. | 4073 // Push receiver, key and value for runtime call. |
| 4008 __ Push(r2, r1, r0); | 4074 __ Push(r2, r1, r0); |
| 4009 | 4075 |
| 4010 __ TailCallRuntime(Runtime::kSetProperty, 3, 1); | 4076 __ mov(r1, Operand(Smi::FromInt(NONE))); // PropertyAttributes |
| 4077 __ mov(r0, Operand(Smi::FromInt( |
| 4078 Code::ExtractExtraICStateFromFlags(flags) & kStrictMode))); |
| 4079 __ Push(r1, r0); |
| 4080 |
| 4081 __ TailCallRuntime(Runtime::kSetProperty, 5, 1); |
| 4011 | 4082 |
| 4012 return GetCode(flags); | 4083 return GetCode(flags); |
| 4013 } | 4084 } |
| 4014 | 4085 |
| 4015 | 4086 |
| 4016 #undef __ | 4087 #undef __ |
| 4017 | 4088 |
| 4018 } } // namespace v8::internal | 4089 } } // namespace v8::internal |
| 4019 | 4090 |
| 4020 #endif // V8_TARGET_ARCH_ARM | 4091 #endif // V8_TARGET_ARCH_ARM |
| OLD | NEW |