~ubuntu-branches/ubuntu/lucid/webkit/lucid-security

« back to all changes in this revision

Viewing changes to JavaScriptCore/jit/JITStubs.cpp

  • Committer: Bazaar Package Importer
  • Author(s): Gustavo Noronha Silva
  • Date: 2010-01-06 21:25:06 UTC
  • mfrom: (1.2.6 upstream) (4.3.7 sid)
  • Revision ID: james.westby@ubuntu.com-20100106212506-gd0czn4zrwf1j19l
* New upstream release
- adds basic Content-Encoding support, thanks to soup
  (Closes: #529271)
- fixes over-advertising content types as supported by
  the media player (Closes: #559420)
* debian/control:
- updated libsoup build requirement (>= 2.28.2)
* debian/libwebkit-1.0-2.symbols:
- updated with new symbols
* debian/copyright:
- updated information since 1.1.17
* Imported patch from https://bugs.webkit.org/show_bug.cgi?id=30623
- I am shipping this patch because I believe it is correct, it is the
  way to go, it fixes a race, and it needs testing.

Show diffs side-by-side

added added

removed removed

Lines of Context:
64
64
 
65
65
namespace JSC {
66
66
 
67
 
#if PLATFORM(DARWIN) || PLATFORM(WIN_OS)
 
67
#if OS(DARWIN) || OS(WINDOWS)
68
68
#define SYMBOL_STRING(name) "_" #name
69
69
#else
70
70
#define SYMBOL_STRING(name) #name
71
71
#endif
72
72
 
73
 
#if PLATFORM(IPHONE)
 
73
#if OS(IPHONE_OS)
74
74
#define THUMB_FUNC_PARAM(name) SYMBOL_STRING(name)
75
75
#else
76
76
#define THUMB_FUNC_PARAM(name)
77
77
#endif
78
78
 
79
 
#if PLATFORM(LINUX) && PLATFORM(X86_64)
 
79
#if OS(LINUX) && CPU(X86_64)
80
80
#define SYMBOL_STRING_RELOCATION(name) #name "@plt"
81
81
#else
82
82
#define SYMBOL_STRING_RELOCATION(name) SYMBOL_STRING(name)
83
83
#endif
84
84
 
85
 
#if PLATFORM(DARWIN)
 
85
#if OS(DARWIN)
86
86
    // Mach-O platform
87
87
#define HIDE_SYMBOL(name) ".private_extern _" #name
88
 
#elif PLATFORM(AIX)
 
88
#elif OS(AIX)
89
89
    // IBM's own file format
90
90
#define HIDE_SYMBOL(name) ".lglobl " #name
91
 
#elif PLATFORM(LINUX) || PLATFORM(FREEBSD) || PLATFORM(OPENBSD) || PLATFORM(SOLARIS) || (PLATFORM(HPUX) && PLATFORM(IA64)) || PLATFORM(SYMBIAN) || PLATFORM(NETBSD)
 
91
#elif   OS(LINUX)               \
 
92
     || OS(FREEBSD)             \
 
93
     || OS(OPENBSD)             \
 
94
     || OS(SOLARIS)             \
 
95
     || (OS(HPUX) && CPU(IA64)) \
 
96
     || OS(SYMBIAN)             \
 
97
     || OS(NETBSD)
92
98
    // ELF platform
93
99
#define HIDE_SYMBOL(name) ".hidden " #name
94
100
#else
97
103
 
98
104
#if USE(JSVALUE32_64)
99
105
 
100
 
#if COMPILER(GCC) && PLATFORM(X86)
 
106
#if COMPILER(GCC) && CPU(X86)
101
107
 
102
108
// These ASSERTs remind you that, if you change the layout of JITStackFrame, you
103
109
// need to change the assembly trampolines below to match.
156
162
    "ret" "\n"
157
163
);
158
164
    
159
 
#elif COMPILER(GCC) && PLATFORM(X86_64)
 
165
#elif COMPILER(GCC) && CPU(X86_64)
160
166
 
161
167
#if USE(JIT_STUB_ARGUMENT_VA_LIST)
162
168
#error "JIT_STUB_ARGUMENT_VA_LIST not supported on x86-64."
226
232
    "ret" "\n"
227
233
);
228
234
 
229
 
#elif COMPILER(GCC) && PLATFORM(ARM_THUMB2)
 
235
#elif COMPILER(GCC) && CPU(ARM_THUMB2)
230
236
 
231
237
#if USE(JIT_STUB_ARGUMENT_VA_LIST)
232
238
#error "JIT_STUB_ARGUMENT_VA_LIST not supported on ARMv7."
292
298
    "bx lr" "\n"
293
299
);
294
300
 
295
 
#elif COMPILER(GCC) && PLATFORM(ARM_TRADITIONAL)
 
301
#elif COMPILER(GCC) && CPU(ARM_TRADITIONAL)
296
302
 
297
303
asm volatile (
298
304
".globl " SYMBOL_STRING(ctiTrampoline) "\n"
390
396
    }
391
397
}
392
398
 
393
 
#endif // COMPILER(GCC) && PLATFORM(X86)
 
399
#endif // COMPILER(GCC) && CPU(X86)
394
400
 
395
401
#else // USE(JSVALUE32_64)
396
402
 
397
 
#if COMPILER(GCC) && PLATFORM(X86)
 
403
#if COMPILER(GCC) && CPU(X86)
398
404
 
399
405
// These ASSERTs remind you that, if you change the layout of JITStackFrame, you
400
406
// need to change the assembly trampolines below to match.
452
458
    "ret" "\n"
453
459
);
454
460
    
455
 
#elif COMPILER(GCC) && PLATFORM(X86_64)
 
461
#elif COMPILER(GCC) && CPU(X86_64)
456
462
 
457
463
#if USE(JIT_STUB_ARGUMENT_VA_LIST)
458
464
#error "JIT_STUB_ARGUMENT_VA_LIST not supported on x86-64."
529
535
    "ret" "\n"
530
536
);
531
537
 
532
 
#elif COMPILER(GCC) && PLATFORM(ARM_THUMB2)
 
538
#elif COMPILER(GCC) && CPU(ARM_THUMB2)
533
539
 
534
540
#if USE(JIT_STUB_ARGUMENT_VA_LIST)
535
541
#error "JIT_STUB_ARGUMENT_VA_LIST not supported on ARMv7."
596
602
    "bx lr" "\n"
597
603
);
598
604
 
599
 
#elif COMPILER(GCC) && PLATFORM(ARM_TRADITIONAL)
 
605
#elif COMPILER(GCC) && CPU(ARM_TRADITIONAL)
600
606
 
601
607
asm volatile (
602
608
".text\n"
696
702
     }
697
703
}
698
704
 
699
 
#endif // COMPILER(GCC) && PLATFORM(X86)
 
705
#endif // COMPILER(GCC) && CPU(X86)
700
706
 
701
707
#endif // USE(JSVALUE32_64)
702
708
 
710
716
{
711
717
    JIT::compileCTIMachineTrampolines(globalData, &m_executablePool, &m_ctiStringLengthTrampoline, &m_ctiVirtualCallLink, &m_ctiVirtualCall, &m_ctiNativeCallThunk);
712
718
 
713
 
#if PLATFORM(ARM_THUMB2)
 
719
#if CPU(ARM_THUMB2)
714
720
    // Unfortunate the arm compiler does not like the use of offsetof on JITStackFrame (since it contains non POD types),
715
721
    // and the OBJECT_OFFSETOF macro does not appear constantish enough for it to be happy with its use in COMPILE_ASSERT
716
722
    // macros.
847
853
        
848
854
        stubInfo->initGetByIdProto(structure, slotBaseObject->structure());
849
855
 
 
856
        ASSERT(!structure->isDictionary());
 
857
        ASSERT(!slotBaseObject->structure()->isDictionary());
850
858
        JIT::compileGetByIdProto(callFrame->scopeChain()->globalData, callFrame, codeBlock, stubInfo, structure, slotBaseObject->structure(), slot.cachedOffset(), returnAddress);
851
859
        return;
852
860
    }
955
963
        } \
956
964
    } while (0)
957
965
 
958
 
#if PLATFORM(ARM_THUMB2)
 
966
#if CPU(ARM_THUMB2)
959
967
 
960
968
#define DEFINE_STUB_FUNCTION(rtype, op) \
961
969
    extern "C" { \
976
984
        ); \
977
985
    rtype JITStubThunked_##op(STUB_ARGS_DECLARATION) \
978
986
 
979
 
#elif PLATFORM(ARM_TRADITIONAL) && COMPILER(GCC)
 
987
#elif CPU(ARM_TRADITIONAL) && COMPILER(GCC)
980
988
 
981
989
#if USE(JSVALUE32_64)
982
990
#define THUNK_RETURN_ADDRESS_OFFSET 64
1031
1039
 
1032
1040
    JSValue v1 = stackFrame.args[0].jsValue();
1033
1041
    JSValue v2 = stackFrame.args[1].jsValue();
1034
 
 
1035
 
    double left;
1036
 
    double right = 0.0;
1037
 
 
1038
 
    bool rightIsNumber = v2.getNumber(right);
1039
 
    if (rightIsNumber && v1.getNumber(left))
 
1042
    CallFrame* callFrame = stackFrame.callFrame;
 
1043
 
 
1044
    if (v1.isString()) {
 
1045
        JSValue result = v2.isString()
 
1046
            ? jsString(callFrame, asString(v1), asString(v2))
 
1047
            : jsString(callFrame, asString(v1), v2.toPrimitiveString(callFrame));
 
1048
        CHECK_FOR_EXCEPTION_AT_END();
 
1049
        return JSValue::encode(result);
 
1050
    }
 
1051
 
 
1052
    double left = 0.0, right;
 
1053
    if (v1.getNumber(left) && v2.getNumber(right))
1040
1054
        return JSValue::encode(jsNumber(stackFrame.globalData, left + right));
1041
 
    
1042
 
    CallFrame* callFrame = stackFrame.callFrame;
1043
 
 
1044
 
    bool leftIsString = v1.isString();
1045
 
    if (leftIsString && v2.isString()) {
1046
 
        RefPtr<UString::Rep> value = concatenate(asString(v1)->value().rep(), asString(v2)->value().rep());
1047
 
        if (UNLIKELY(!value)) {
1048
 
            throwOutOfMemoryError(callFrame);
1049
 
            VM_THROW_EXCEPTION();
1050
 
        }
1051
 
 
1052
 
        return JSValue::encode(jsString(stackFrame.globalData, value.release()));
1053
 
    }
1054
 
 
1055
 
    if (rightIsNumber & leftIsString) {
1056
 
        RefPtr<UString::Rep> value = v2.isInt32() ?
1057
 
            concatenate(asString(v1)->value().rep(), v2.asInt32()) :
1058
 
            concatenate(asString(v1)->value().rep(), right);
1059
 
 
1060
 
        if (UNLIKELY(!value)) {
1061
 
            throwOutOfMemoryError(callFrame);
1062
 
            VM_THROW_EXCEPTION();
1063
 
        }
1064
 
        return JSValue::encode(jsString(stackFrame.globalData, value.release()));
1065
 
    }
1066
1055
 
1067
1056
    // All other cases are pretty uncommon
1068
1057
    JSValue result = jsAddSlowCase(callFrame, v1, v2);
1111
1100
    throwStackOverflowError(oldCallFrame, stackFrame.globalData, ReturnAddressPtr(oldCallFrame->returnPC()), STUB_RETURN_ADDRESS);
1112
1101
}
1113
1102
 
1114
 
DEFINE_STUB_FUNCTION(int, op_loop_if_less)
1115
 
{
1116
 
    STUB_INIT_STACK_FRAME(stackFrame);
1117
 
 
1118
 
    JSValue src1 = stackFrame.args[0].jsValue();
1119
 
    JSValue src2 = stackFrame.args[1].jsValue();
1120
 
    CallFrame* callFrame = stackFrame.callFrame;
1121
 
 
1122
 
    bool result = jsLess(callFrame, src1, src2);
1123
 
    CHECK_FOR_EXCEPTION_AT_END();
1124
 
    return result;
1125
 
}
1126
 
 
1127
1103
DEFINE_STUB_FUNCTION(int, op_loop_if_lesseq)
1128
1104
{
1129
1105
    STUB_INIT_STACK_FRAME(stackFrame);
1397
1373
 
1398
1374
    CHECK_FOR_EXCEPTION();
1399
1375
 
1400
 
    if (!baseValue.isCell() || !slot.isCacheable() || asCell(baseValue)->structure()->isUncacheableDictionary()) {
 
1376
    if (!baseValue.isCell() || !slot.isCacheable() || asCell(baseValue)->structure()->isDictionary()) {
1401
1377
        ctiPatchCallByReturnAddress(callFrame->codeBlock(), STUB_RETURN_ADDRESS, FunctionPtr(cti_op_get_by_id_proto_fail));
1402
1378
        return JSValue::encode(result);
1403
1379
    }
1412
1388
    if (slot.slotBase() == baseValue)
1413
1389
        ctiPatchCallByReturnAddress(codeBlock, STUB_RETURN_ADDRESS, FunctionPtr(cti_op_get_by_id_proto_fail));
1414
1390
    else if (slot.slotBase() == asCell(baseValue)->structure()->prototypeForLookup(callFrame)) {
 
1391
        ASSERT(!asCell(baseValue)->structure()->isDictionary());
1415
1392
        // Since we're accessing a prototype in a loop, it's a good bet that it
1416
1393
        // should not be treated as a dictionary.
1417
1394
        if (slotBaseObject->structure()->isDictionary())
1425
1402
        if (listIndex == (POLYMORPHIC_LIST_CACHE_SIZE - 1))
1426
1403
            ctiPatchCallByReturnAddress(codeBlock, STUB_RETURN_ADDRESS, FunctionPtr(cti_op_get_by_id_proto_list_full));
1427
1404
    } else if (size_t count = normalizePrototypeChain(callFrame, baseValue, slot.slotBase())) {
 
1405
        ASSERT(!asCell(baseValue)->structure()->isDictionary());
1428
1406
        int listIndex;
1429
1407
        PolymorphicAccessStructureList* prototypeStructureList = getPolymorphicAccessStructureListSlot(stubInfo, listIndex);
1430
1408
 
1893
1871
        } else if (isJSString(globalData, baseValue) && asString(baseValue)->canGetIndex(i)) {
1894
1872
            // All fast byte array accesses are safe from exceptions so return immediately to avoid exception checks.
1895
1873
            ctiPatchCallByReturnAddress(callFrame->codeBlock(), STUB_RETURN_ADDRESS, FunctionPtr(cti_op_get_by_val_string));
1896
 
            result = asString(baseValue)->getIndex(stackFrame.globalData, i);
 
1874
            result = asString(baseValue)->getIndex(callFrame, i);
1897
1875
        } else if (isJSByteArray(globalData, baseValue) && asByteArray(baseValue)->canAccessIndex(i)) {
1898
1876
            // All fast byte array accesses are safe from exceptions so return immediately to avoid exception checks.
1899
1877
            ctiPatchCallByReturnAddress(callFrame->codeBlock(), STUB_RETURN_ADDRESS, FunctionPtr(cti_op_get_by_val_byte_array));
1924
1902
    if (LIKELY(subscript.isUInt32())) {
1925
1903
        uint32_t i = subscript.asUInt32();
1926
1904
        if (isJSString(globalData, baseValue) && asString(baseValue)->canGetIndex(i))
1927
 
            result = asString(baseValue)->getIndex(stackFrame.globalData, i);
 
1905
            result = asString(baseValue)->getIndex(callFrame, i);
1928
1906
        else {
1929
1907
            result = baseValue.get(callFrame, i);
1930
1908
            if (!isJSString(globalData, baseValue))
2089
2067
    return JSValue::encode(result);
2090
2068
}
2091
2069
 
2092
 
DEFINE_STUB_FUNCTION(int, op_loop_if_true)
2093
 
{
2094
 
    STUB_INIT_STACK_FRAME(stackFrame);
2095
 
 
2096
 
    JSValue src1 = stackFrame.args[0].jsValue();
2097
 
 
2098
 
    CallFrame* callFrame = stackFrame.callFrame;
2099
 
 
2100
 
    bool result = src1.toBoolean(callFrame);
2101
 
    CHECK_FOR_EXCEPTION_AT_END();
2102
 
    return result;
2103
 
}
2104
 
    
2105
2070
DEFINE_STUB_FUNCTION(int, op_load_varargs)
2106
2071
{
2107
2072
    STUB_INIT_STACK_FRAME(stackFrame);
2440
2405
 
2441
2406
    if (cell1->isString()) {
2442
2407
        if (src2.isInt32())
2443
 
            return static_cast<JSString*>(cell1)->value().toDouble() == src2.asInt32();
 
2408
            return static_cast<JSString*>(cell1)->value(stackFrame.callFrame).toDouble() == src2.asInt32();
2444
2409
            
2445
2410
        if (src2.isDouble())
2446
 
            return static_cast<JSString*>(cell1)->value().toDouble() == src2.asDouble();
 
2411
            return static_cast<JSString*>(cell1)->value(stackFrame.callFrame).toDouble() == src2.asDouble();
2447
2412
 
2448
2413
        if (src2.isTrue())
2449
 
            return static_cast<JSString*>(cell1)->value().toDouble() == 1.0;
 
2414
            return static_cast<JSString*>(cell1)->value(stackFrame.callFrame).toDouble() == 1.0;
2450
2415
 
2451
2416
        if (src2.isFalse())
2452
 
            return static_cast<JSString*>(cell1)->value().toDouble() == 0.0;
 
2417
            return static_cast<JSString*>(cell1)->value(stackFrame.callFrame).toDouble() == 0.0;
2453
2418
 
2454
2419
        JSCell* cell2 = asCell(src2);
2455
2420
        if (cell2->isString())
2456
 
            return static_cast<JSString*>(cell1)->value() == static_cast<JSString*>(cell2)->value();
 
2421
            return static_cast<JSString*>(cell1)->value(stackFrame.callFrame) == static_cast<JSString*>(cell2)->value(stackFrame.callFrame);
2457
2422
 
2458
2423
        src2 = asObject(cell2)->toPrimitive(stackFrame.callFrame);
2459
2424
        CHECK_FOR_EXCEPTION();
2476
2441
 
2477
2442
    ASSERT(string1->isString());
2478
2443
    ASSERT(string2->isString());
2479
 
    return string1->value() == string2->value();
 
2444
    return string1->value(stackFrame.callFrame) == string2->value(stackFrame.callFrame);
2480
2445
}
2481
2446
 
2482
2447
#else // USE(JSVALUE32_64)
2774
2739
 
2775
2740
    JSObject* base = stackFrame.args[0].jsObject();
2776
2741
    JSString* property = stackFrame.args[1].jsString();
2777
 
    return base->hasProperty(stackFrame.callFrame, Identifier(stackFrame.callFrame, property->value()));
 
2742
    return base->hasProperty(stackFrame.callFrame, Identifier(stackFrame.callFrame, property->value(stackFrame.callFrame)));
2778
2743
}
2779
2744
 
2780
2745
DEFINE_STUB_FUNCTION(JSObject*, op_push_scope)
2851
2816
    JSValue src1 = stackFrame.args[0].jsValue();
2852
2817
    JSValue src2 = stackFrame.args[1].jsValue();
2853
2818
 
2854
 
    return JSValue::encode(jsBoolean(JSValue::strictEqual(src1, src2)));
 
2819
    return JSValue::encode(jsBoolean(JSValue::strictEqual(stackFrame.callFrame, src1, src2)));
2855
2820
}
2856
2821
 
2857
2822
DEFINE_STUB_FUNCTION(EncodedJSValue, op_to_primitive)
2865
2830
{
2866
2831
    STUB_INIT_STACK_FRAME(stackFrame);
2867
2832
 
2868
 
    return JSValue::encode(concatenateStrings(stackFrame.callFrame, &stackFrame.callFrame->registers()[stackFrame.args[0].int32()], stackFrame.args[1].int32()));
 
2833
    JSValue result = jsString(stackFrame.callFrame, &stackFrame.callFrame->registers()[stackFrame.args[0].int32()], stackFrame.args[1].int32());
 
2834
    CHECK_FOR_EXCEPTION_AT_END();
 
2835
    return JSValue::encode(result);
2869
2836
}
2870
2837
 
2871
2838
DEFINE_STUB_FUNCTION(EncodedJSValue, op_nstricteq)
2875
2842
    JSValue src1 = stackFrame.args[0].jsValue();
2876
2843
    JSValue src2 = stackFrame.args[1].jsValue();
2877
2844
 
2878
 
    return JSValue::encode(jsBoolean(!JSValue::strictEqual(src1, src2)));
 
2845
    return JSValue::encode(jsBoolean(!JSValue::strictEqual(stackFrame.callFrame, src1, src2)));
2879
2846
}
2880
2847
 
2881
2848
DEFINE_STUB_FUNCTION(EncodedJSValue, op_to_jsnumber)
2984
2951
    void* result = codeBlock->characterSwitchJumpTable(tableIndex).ctiDefault.executableAddress();
2985
2952
 
2986
2953
    if (scrutinee.isString()) {
2987
 
        UString::Rep* value = asString(scrutinee)->value().rep();
 
2954
        UString::Rep* value = asString(scrutinee)->value(callFrame).rep();
2988
2955
        if (value->size() == 1)
2989
2956
            result = codeBlock->characterSwitchJumpTable(tableIndex).ctiForValue(value->data()[0]).executableAddress();
2990
2957
    }
3004
2971
    void* result = codeBlock->stringSwitchJumpTable(tableIndex).ctiDefault.executableAddress();
3005
2972
 
3006
2973
    if (scrutinee.isString()) {
3007
 
        UString::Rep* value = asString(scrutinee)->value().rep();
 
2974
        UString::Rep* value = asString(scrutinee)->value(callFrame).rep();
3008
2975
        result = codeBlock->stringSwitchJumpTable(tableIndex).ctiForValue(value).executableAddress();
3009
2976
    }
3010
2977