Changeset 91095 in webkit


Ignore:
Timestamp:
Jul 15, 2011 12:51:49 PM (13 years ago)
Author:
barraclough@apple.com
Message:

https://bugs.webkit.org/show_bug.cgi?id=64250
Global strict mode function leaking global object as "this".

Reviewed by Oliver Hunt.

Source/JavaScriptCore:

The root problem here is that we pass the wrong values into
calls, and then try to fix them up in the callee. Correct
behaviour per the spec is to pass in the value undefined,
as this unless either (1) the function call is based on an
explicit property access or (2) the base of the call comes
directly from a 'with'.

This change does away with the need for this conversion of
objects (non strict code should only box primitives), and
does away with all this conversion for strict functions.

This patch may have web compatibility ramifications, and may
require some advocacy.

  • bytecode/CodeBlock.cpp:

(JSC::CodeBlock::dump):

  • Removed op_convert_this_strict, added op_resolve_with_this.
  • bytecode/Opcode.h:
    • Removed op_convert_this_strict, added op_resolve_with_this.
  • bytecompiler/BytecodeGenerator.cpp:

(JSC::BytecodeGenerator::BytecodeGenerator):
(JSC::BytecodeGenerator::emitResolveWithThis):

  • Removed op_convert_this_strict, added op_resolve_with_this.
  • bytecompiler/BytecodeGenerator.h:
    • Removed op_convert_this_strict, added op_resolve_with_this.
  • bytecompiler/NodesCodegen.cpp:

(JSC::EvalFunctionCallNode::emitBytecode):
(JSC::FunctionCallResolveNode::emitBytecode):

  • Removed op_convert_this_strict, added op_resolve_with_this.
  • dfg/DFGSpeculativeJIT.cpp:

(JSC::DFG::SpeculativeJIT::compile):

  • Change NeedsThisConversion check to test for JSString's vptr (objects no longer need conversion).
  • interpreter/Interpreter.cpp:

(JSC::Interpreter::resolveThisAndProperty):

  • Based on resolveBaseAndProperty, but produce correct this value.

(JSC::Interpreter::privateExecute):

  • Removed op_convert_this_strict, added op_resolve_with_this.
  • interpreter/Interpreter.h:
  • jit/JIT.cpp:

(JSC::JIT::privateCompileMainPass):
(JSC::JIT::privateCompileSlowCases):

  • Removed op_convert_this_strict, added op_resolve_with_this.
  • jit/JIT.h:
  • jit/JITOpcodes.cpp:

(JSC::JIT::emit_op_resolve_with_this):

  • Removed op_convert_this_strict, added op_resolve_with_this.

(JSC::JIT::emit_op_convert_this):
(JSC::JIT::emitSlow_op_convert_this):

  • Change NeedsThisConversion check to test for JSString's vptr (objects no longer need conversion).
  • jit/JITOpcodes32_64.cpp:

(JSC::JIT::emit_op_resolve_with_this):

  • Removed op_convert_this_strict, added op_resolve_with_this.

(JSC::JIT::emit_op_convert_this):
(JSC::JIT::emitSlow_op_convert_this):

  • Change NeedsThisConversion check to test for JSString's vptr (objects no longer need conversion).
  • jit/JITStubs.cpp:

(JSC::DEFINE_STUB_FUNCTION):

  • Removed op_convert_this_strict, added op_resolve_with_this.
  • jit/JITStubs.h:
    • Removed op_convert_this_strict, added op_resolve_with_this.
  • runtime/JSActivation.h:
    • removed NeedsThisConversion flag, added IsEnvironmentRecord.
  • runtime/JSStaticScopeObject.h:
    • removed NeedsThisConversion flag, added IsEnvironmentRecord.
  • runtime/JSString.h:

(JSC::RopeBuilder::createStructure):

  • removed NeedsThisConversion.
  • runtime/JSTypeInfo.h:

(JSC::TypeInfo::isEnvironmentRecord):
(JSC::TypeInfo::overridesHasInstance):

  • removed NeedsThisConversion flag, added IsEnvironmentRecord.
  • runtime/JSValue.h:
    • removed NeedsThisConversion.
  • runtime/JSVariableObject.h:
    • Corrected StructureFlags inheritance.
  • runtime/StrictEvalActivation.h:

(JSC::StrictEvalActivation::createStructure):

  • Added IsEnvironmentRecord to StructureFlags, addded createStructure.
  • runtime/Structure.h:
    • removed NeedsThisConversion.
  • tests/mozilla/ecma/String/15.5.4.6-2.js:

(getTestCases):

  • Removed invalid test case.

Source/WebCore:

  • bindings/js/JSMainThreadExecState.h:

(WebCore::JSMainThreadExecState::call):

  • bindings/scripts/CodeGeneratorJS.pm:

(GenerateHeader):

  • Change call to pass DOM Window shell, instead of the global varaible object.

Source/WebKit/mac:

  • Plugins/Hosted/NetscapePluginInstanceProxy.mm:

(WebKit::NetscapePluginInstanceProxy::invoke):
(WebKit::NetscapePluginInstanceProxy::invokeDefault):

  • Change call to pass DOM Window shell, instead of the global varaible object.

Source/WebKit2:

  • WebProcess/Plugins/Netscape/NPJSObject.cpp:

(WebKit::NPJSObject::invoke):

  • Change call to pass DOM Window shell, instead of the global varaible object.

LayoutTests:

Add test case / update test results.

  • fast/js/call-base-resolution-expected.txt: Added.
  • fast/js/call-base-resolution.html: Added.
    • Add test for ES5 correct this value resolution in calls.
  • sputnik/Conformance/15_Native_Objects/15.5_String/15.5.4/15.5.4.10_String.prototype.match/S15.5.4.10_A1_T3-expected.txt:
  • sputnik/Conformance/15_Native_Objects/15.5_String/15.5.4/15.5.4.12_String.prototype.search/S15.5.4.12_A1_T3-expected.txt:
  • sputnik/Conformance/15_Native_Objects/15.5_String/15.5.4/15.5.4.13_String.prototype.slice/S15.5.4.13_A1_T3-expected.txt:
  • sputnik/Conformance/15_Native_Objects/15.5_String/15.5.4/15.5.4.14_String.prototype.split/S15.5.4.14_A1_T3-expected.txt:
  • sputnik/Conformance/15_Native_Objects/15.5_String/15.5.4/15.5.4.15_String.prototype.substring/S15.5.4.15_A1_T3-expected.txt:
  • sputnik/Conformance/15_Native_Objects/15.5_String/15.5.4/15.5.4.4_String.prototype.charAt/S15.5.4.4_A1_T3-expected.txt:
  • sputnik/Conformance/15_Native_Objects/15.5_String/15.5.4/15.5.4.5_String.prototype.charCodeAt/S15.5.4.5_A1_T3-expected.txt:
  • sputnik/Conformance/15_Native_Objects/15.5_String/15.5.4/15.5.4.6_String.prototype.concat/S15.5.4.6_A1_T3-expected.txt:
  • sputnik/Conformance/15_Native_Objects/15.5_String/15.5.4/15.5.4.7_String.prototype.indexOf/S15.5.4.7_A1_T3-expected.txt:
  • sputnik/Conformance/15_Native_Objects/15.5_String/15.5.4/15.5.4.8_String.prototype.lastIndexOf/S15.5.4.8_A1_T3-expected.txt:
Location:
trunk
Files:
2 added
48 edited

Legend:

Unmodified
Added
Removed
  • trunk/LayoutTests/ChangeLog

    r91086 r91095  
     12011-07-14  Gavin Barraclough  <barraclough@apple.com>
     2
     3        https://bugs.webkit.org/show_bug.cgi?id=64250
     4        Global strict mode function leaking global object as "this".
     5
     6        Reviewed by Oliver Hunt.
     7
     8        Add test case / update test results.
     9
     10        * fast/js/call-base-resolution-expected.txt: Added.
     11        * fast/js/call-base-resolution.html: Added.
     12            - Add test for ES5 correct this value resolution in calls.
     13        * sputnik/Conformance/15_Native_Objects/15.5_String/15.5.4/15.5.4.10_String.prototype.match/S15.5.4.10_A1_T3-expected.txt:
     14        * sputnik/Conformance/15_Native_Objects/15.5_String/15.5.4/15.5.4.12_String.prototype.search/S15.5.4.12_A1_T3-expected.txt:
     15        * sputnik/Conformance/15_Native_Objects/15.5_String/15.5.4/15.5.4.13_String.prototype.slice/S15.5.4.13_A1_T3-expected.txt:
     16        * sputnik/Conformance/15_Native_Objects/15.5_String/15.5.4/15.5.4.14_String.prototype.split/S15.5.4.14_A1_T3-expected.txt:
     17        * sputnik/Conformance/15_Native_Objects/15.5_String/15.5.4/15.5.4.15_String.prototype.substring/S15.5.4.15_A1_T3-expected.txt:
     18        * sputnik/Conformance/15_Native_Objects/15.5_String/15.5.4/15.5.4.4_String.prototype.charAt/S15.5.4.4_A1_T3-expected.txt:
     19        * sputnik/Conformance/15_Native_Objects/15.5_String/15.5.4/15.5.4.5_String.prototype.charCodeAt/S15.5.4.5_A1_T3-expected.txt:
     20        * sputnik/Conformance/15_Native_Objects/15.5_String/15.5.4/15.5.4.6_String.prototype.concat/S15.5.4.6_A1_T3-expected.txt:
     21        * sputnik/Conformance/15_Native_Objects/15.5_String/15.5.4/15.5.4.7_String.prototype.indexOf/S15.5.4.7_A1_T3-expected.txt:
     22        * sputnik/Conformance/15_Native_Objects/15.5_String/15.5.4/15.5.4.8_String.prototype.lastIndexOf/S15.5.4.8_A1_T3-expected.txt:
     23            - Check in failing results for these tests - these tests were asserting incorrect behaviour,
     24              and have since been fixed in test-262, see https://bugs.ecmascript.org/show_bug.cgi?id=117
     25
    1262011-07-15  Stephen White  <senorblanco@chromium.org>
    227
  • trunk/LayoutTests/sputnik/Conformance/15_Native_Objects/15.5_String/15.5.4/15.5.4.10_String.prototype.match/S15.5.4.10_A1_T3-expected.txt

    r58534 r91095  
    11S15.5.4.10_A1_T3
    22
    3 PASS
     3FAIL TypeError: Type error
    44
    55TEST COMPLETE
  • trunk/LayoutTests/sputnik/Conformance/15_Native_Objects/15.5_String/15.5.4/15.5.4.12_String.prototype.search/S15.5.4.12_A1_T3-expected.txt

    r58534 r91095  
    11S15.5.4.12_A1_T3
    22
    3 PASS
     3FAIL TypeError: Type error
    44
    55TEST COMPLETE
  • trunk/LayoutTests/sputnik/Conformance/15_Native_Objects/15.5_String/15.5.4/15.5.4.13_String.prototype.slice/S15.5.4.13_A1_T3-expected.txt

    r58534 r91095  
    11S15.5.4.13_A1_T3
    22
    3 PASS
     3FAIL TypeError: Type error
    44
    55TEST COMPLETE
  • trunk/LayoutTests/sputnik/Conformance/15_Native_Objects/15.5_String/15.5.4/15.5.4.14_String.prototype.split/S15.5.4.14_A1_T3-expected.txt

    r58534 r91095  
    11S15.5.4.14_A1_T3
    22
    3 PASS
     3FAIL TypeError: Type error
    44
    55TEST COMPLETE
  • trunk/LayoutTests/sputnik/Conformance/15_Native_Objects/15.5_String/15.5.4/15.5.4.15_String.prototype.substring/S15.5.4.15_A1_T3-expected.txt

    r58534 r91095  
    11S15.5.4.15_A1_T3
    22
    3 PASS
     3FAIL TypeError: Type error
    44
    55TEST COMPLETE
  • trunk/LayoutTests/sputnik/Conformance/15_Native_Objects/15.5_String/15.5.4/15.5.4.4_String.prototype.charAt/S15.5.4.4_A1_T3-expected.txt

    r58534 r91095  
    11S15.5.4.4_A1_T3
    22
    3 PASS
     3FAIL TypeError: Type error
    44
    55TEST COMPLETE
  • trunk/LayoutTests/sputnik/Conformance/15_Native_Objects/15.5_String/15.5.4/15.5.4.5_String.prototype.charCodeAt/S15.5.4.5_A1_T3-expected.txt

    r58534 r91095  
    11S15.5.4.5_A1_T3
    22
    3 PASS
     3FAIL TypeError: Type error
    44
    55TEST COMPLETE
  • trunk/LayoutTests/sputnik/Conformance/15_Native_Objects/15.5_String/15.5.4/15.5.4.6_String.prototype.concat/S15.5.4.6_A1_T3-expected.txt

    r58534 r91095  
    11S15.5.4.6_A1_T3
    22
    3 PASS
     3FAIL TypeError: Type error
    44
    55TEST COMPLETE
  • trunk/LayoutTests/sputnik/Conformance/15_Native_Objects/15.5_String/15.5.4/15.5.4.7_String.prototype.indexOf/S15.5.4.7_A1_T3-expected.txt

    r58534 r91095  
    11S15.5.4.7_A1_T3
    22
    3 PASS
     3FAIL TypeError: Type error
    44
    55TEST COMPLETE
  • trunk/LayoutTests/sputnik/Conformance/15_Native_Objects/15.5_String/15.5.4/15.5.4.8_String.prototype.lastIndexOf/S15.5.4.8_A1_T3-expected.txt

    r58534 r91095  
    11S15.5.4.8_A1_T3
    22
    3 PASS
     3FAIL TypeError: Type error
    44
    55TEST COMPLETE
  • trunk/Source/JavaScriptCore/ChangeLog

    r91094 r91095  
     12011-07-14  Gavin Barraclough  <barraclough@apple.com>
     2
     3        https://bugs.webkit.org/show_bug.cgi?id=64250
     4        Global strict mode function leaking global object as "this".
     5
     6        Reviewed by Oliver Hunt.
     7
     8        The root problem here is that we pass the wrong values into
     9        calls, and then try to fix them up in the callee. Correct
     10        behaviour per the spec is to pass in the value undefined,
     11        as this unless either (1) the function call is based on an
     12        explicit property access or (2) the base of the call comes
     13        directly from a 'with'.
     14
     15        This change does away with the need for this conversion of
     16        objects (non strict code should only box primitives), and
     17        does away with all this conversion for strict functions.
     18
     19        This patch may have web compatibility ramifications, and may
     20        require some advocacy.
     21
     22        * bytecode/CodeBlock.cpp:
     23        (JSC::CodeBlock::dump):
     24            - Removed op_convert_this_strict, added op_resolve_with_this.
     25        * bytecode/Opcode.h:
     26            - Removed op_convert_this_strict, added op_resolve_with_this.
     27        * bytecompiler/BytecodeGenerator.cpp:
     28        (JSC::BytecodeGenerator::BytecodeGenerator):
     29        (JSC::BytecodeGenerator::emitResolveWithThis):
     30            - Removed op_convert_this_strict, added op_resolve_with_this.
     31        * bytecompiler/BytecodeGenerator.h:
     32            - Removed op_convert_this_strict, added op_resolve_with_this.
     33        * bytecompiler/NodesCodegen.cpp:
     34        (JSC::EvalFunctionCallNode::emitBytecode):
     35        (JSC::FunctionCallResolveNode::emitBytecode):
     36            - Removed op_convert_this_strict, added op_resolve_with_this.
     37        * dfg/DFGSpeculativeJIT.cpp:
     38        (JSC::DFG::SpeculativeJIT::compile):
     39            - Change NeedsThisConversion check to test for JSString's vptr
     40              (objects no longer need conversion).
     41        * interpreter/Interpreter.cpp:
     42        (JSC::Interpreter::resolveThisAndProperty):
     43            - Based on resolveBaseAndProperty, but produce correct this value.
     44        (JSC::Interpreter::privateExecute):
     45            - Removed op_convert_this_strict, added op_resolve_with_this.
     46        * interpreter/Interpreter.h:
     47        * jit/JIT.cpp:
     48        (JSC::JIT::privateCompileMainPass):
     49        (JSC::JIT::privateCompileSlowCases):
     50            - Removed op_convert_this_strict, added op_resolve_with_this.
     51        * jit/JIT.h:
     52        * jit/JITOpcodes.cpp:
     53        (JSC::JIT::emit_op_resolve_with_this):
     54            - Removed op_convert_this_strict, added op_resolve_with_this.
     55        (JSC::JIT::emit_op_convert_this):
     56        (JSC::JIT::emitSlow_op_convert_this):
     57            - Change NeedsThisConversion check to test for JSString's vptr
     58              (objects no longer need conversion).
     59        * jit/JITOpcodes32_64.cpp:
     60        (JSC::JIT::emit_op_resolve_with_this):
     61            - Removed op_convert_this_strict, added op_resolve_with_this.
     62        (JSC::JIT::emit_op_convert_this):
     63        (JSC::JIT::emitSlow_op_convert_this):
     64            - Change NeedsThisConversion check to test for JSString's vptr
     65              (objects no longer need conversion).
     66        * jit/JITStubs.cpp:
     67        (JSC::DEFINE_STUB_FUNCTION):
     68            - Removed op_convert_this_strict, added op_resolve_with_this.
     69        * jit/JITStubs.h:
     70            - Removed op_convert_this_strict, added op_resolve_with_this.
     71        * runtime/JSActivation.h:
     72            - removed NeedsThisConversion flag, added IsEnvironmentRecord.
     73        * runtime/JSStaticScopeObject.h:
     74            - removed NeedsThisConversion flag, added IsEnvironmentRecord.
     75        * runtime/JSString.h:
     76        (JSC::RopeBuilder::createStructure):
     77            - removed NeedsThisConversion.
     78        * runtime/JSTypeInfo.h:
     79        (JSC::TypeInfo::isEnvironmentRecord):
     80        (JSC::TypeInfo::overridesHasInstance):
     81            - removed NeedsThisConversion flag, added IsEnvironmentRecord.
     82        * runtime/JSValue.h:
     83            - removed NeedsThisConversion.
     84        * runtime/JSVariableObject.h:
     85            - Corrected StructureFlags inheritance.
     86        * runtime/StrictEvalActivation.h:
     87        (JSC::StrictEvalActivation::createStructure):
     88            - Added IsEnvironmentRecord to StructureFlags, addded createStructure.
     89        * runtime/Structure.h:
     90            - removed NeedsThisConversion.
     91        * tests/mozilla/ecma/String/15.5.4.6-2.js:
     92        (getTestCases):
     93            - Removed invalid test case.
     94
    1952011-07-15  Sheriff Bot  <webkit.review.bot@gmail.com>
    296
  • trunk/Source/JavaScriptCore/bytecode/CodeBlock.cpp

    r90877 r91095  
    523523            break;
    524524        }
    525         case op_convert_this_strict: {
    526             int r0 = (++it)->u.operand;
    527             printf("[%4d] convert_this_strict %s\n", location, registerName(exec, r0).data());
    528             break;
    529         }
    530525        case op_new_object: {
    531526            int r0 = (++it)->u.operand;
     
    802797            int id0 = (++it)->u.operand;
    803798            printf("[%4d] resolve_with_base %s, %s, %s\n", location, registerName(exec, r0).data(), registerName(exec, r1).data(), idName(id0, m_identifiers[id0]).data());
     799            break;
     800        }
     801        case op_resolve_with_this: {
     802            int r0 = (++it)->u.operand;
     803            int r1 = (++it)->u.operand;
     804            int id0 = (++it)->u.operand;
     805            printf("[%4d] resolve_with_this %s, %s, %s\n", location, registerName(exec, r0).data(), registerName(exec, r1).data(), idName(id0, m_identifiers[id0]).data());
    804806            break;
    805807        }
  • trunk/Source/JavaScriptCore/bytecode/Opcode.h

    r90371 r91095  
    4646        macro(op_get_callee, 2) \
    4747        macro(op_convert_this, 2) \
    48         macro(op_convert_this_strict, 2) \
    4948        \
    5049        macro(op_new_object, 2) \
     
    108107        macro(op_ensure_property_exists, 3) \
    109108        macro(op_resolve_with_base, 4) \
     109        macro(op_resolve_with_this, 4) \
    110110        macro(op_get_by_id, 8) \
    111111        macro(op_get_by_id_self, 8) \
  • trunk/Source/JavaScriptCore/bytecompiler/BytecodeGenerator.cpp

    r90423 r91095  
    415415        instructions().append(funcProto->index());
    416416    } else if (functionBody->usesThis() || m_shouldEmitDebugHooks) {
    417         if (codeBlock->isStrictMode())
    418             emitOpcode(op_convert_this_strict);
    419         else
     417        if (!codeBlock->isStrictMode()) {
    420418            emitOpcode(op_convert_this);
    421         instructions().append(m_thisRegister.index());
     419            instructions().append(m_thisRegister.index());
     420        }
    422421    }
    423422}
     
    14161415}
    14171416
     1417RegisterID* BytecodeGenerator::emitResolveWithThis(RegisterID* baseDst, RegisterID* propDst, const Identifier& property)
     1418{
     1419    size_t depth = 0;
     1420    int index = 0;
     1421    JSObject* globalObject = 0;
     1422    bool requiresDynamicChecks = false;
     1423    if (!findScopedProperty(property, index, depth, false, requiresDynamicChecks, globalObject) || !globalObject || requiresDynamicChecks) {
     1424        // We can't optimise at all :-(
     1425        emitOpcode(op_resolve_with_this);
     1426        instructions().append(baseDst->index());
     1427        instructions().append(propDst->index());
     1428        instructions().append(addConstant(property));
     1429        return baseDst;
     1430    }
     1431
     1432    bool forceGlobalResolve = false;
     1433
     1434    // Global object is the base
     1435    emitLoad(baseDst, jsUndefined());
     1436
     1437    if (index != missingSymbolMarker() && !forceGlobalResolve) {
     1438        // Directly index the property lookup across multiple scopes.
     1439        emitGetScopedVar(propDst, depth, index, globalObject);
     1440        return baseDst;
     1441    }
     1442    if (shouldAvoidResolveGlobal()) {
     1443        emitOpcode(op_resolve);
     1444        instructions().append(propDst->index());
     1445        instructions().append(addConstant(property));
     1446        return baseDst;
     1447    }
     1448#if ENABLE(JIT)
     1449    m_codeBlock->addGlobalResolveInfo(instructions().size());
     1450#endif
     1451#if ENABLE(INTERPRETER)
     1452    m_codeBlock->addGlobalResolveInstruction(instructions().size());
     1453#endif
     1454    emitOpcode(requiresDynamicChecks ? op_resolve_global_dynamic : op_resolve_global);
     1455    instructions().append(propDst->index());
     1456    instructions().append(addConstant(property));
     1457    instructions().append(0);
     1458    instructions().append(0);
     1459    if (requiresDynamicChecks)
     1460        instructions().append(depth);
     1461    return baseDst;
     1462}
     1463
    14181464void BytecodeGenerator::emitMethodCheck()
    14191465{
  • trunk/Source/JavaScriptCore/bytecompiler/BytecodeGenerator.h

    r89954 r91095  
    314314        RegisterID* emitResolveBaseForPut(RegisterID* dst, const Identifier& property);
    315315        RegisterID* emitResolveWithBase(RegisterID* baseDst, RegisterID* propDst, const Identifier& property);
     316        RegisterID* emitResolveWithThis(RegisterID* baseDst, RegisterID* propDst, const Identifier& property);
    316317
    317318        void emitMethodCheck();
  • trunk/Source/JavaScriptCore/bytecompiler/NodesCodegen.cpp

    r90371 r91095  
    336336    CallArguments callArguments(generator, m_args);
    337337    generator.emitExpressionInfo(divot() - startOffset() + 4, 4, 0);
    338     generator.emitResolveWithBase(callArguments.thisRegister(), func.get(), generator.propertyNames().eval);
     338    generator.emitResolveWithThis(callArguments.thisRegister(), func.get(), generator.propertyNames().eval);
    339339    return generator.emitCallEval(generator.finalDestination(dst, func.get()), func.get(), callArguments, divot(), startOffset(), endOffset());
    340340}
     
    375375    int identifierStart = divot() - startOffset();
    376376    generator.emitExpressionInfo(identifierStart + m_ident.length(), m_ident.length(), 0);
    377     generator.emitResolveWithBase(callArguments.thisRegister(), func.get(), m_ident);
     377    generator.emitResolveWithThis(callArguments.thisRegister(), func.get(), m_ident);
    378378    return generator.emitCall(generator.finalDestinationOrIgnored(dst, func.get()), func.get(), callArguments, divot(), startOffset(), endOffset());
    379379}
  • trunk/Source/JavaScriptCore/dfg/DFGSpeculativeJIT.cpp

    r91041 r91095  
    976976    case ConvertThis: {
    977977        SpeculateCellOperand thisValue(this, node.child1());
    978         GPRTemporary temp(this);
    979 
    980         m_jit.loadPtr(JITCompiler::Address(thisValue.gpr(), JSCell::structureOffset()), temp.gpr());
    981         speculationCheck(m_jit.branchTest8(JITCompiler::NonZero, JITCompiler::Address(temp.gpr(), Structure::typeInfoFlagsOffset()), JITCompiler::TrustedImm32(NeedsThisConversion)));
     978
     979        speculationCheck(m_jit.branchPtr(JITCompiler::Equal, JITCompiler::Address(thisValue.gpr()), JITCompiler::TrustedImmPtr(m_jit.globalData()->jsStringVPtr)));
    982980
    983981        cellResult(thisValue.gpr(), m_compileIndex);
  • trunk/Source/JavaScriptCore/interpreter/Interpreter.cpp

    r90938 r91095  
    322322}
    323323
     324NEVER_INLINE bool Interpreter::resolveThisAndProperty(CallFrame* callFrame, Instruction* vPC, JSValue& exceptionValue)
     325{
     326    int thisDst = vPC[1].u.operand;
     327    int propDst = vPC[2].u.operand;
     328    int property = vPC[3].u.operand;
     329
     330    ScopeChainNode* scopeChain = callFrame->scopeChain();
     331    ScopeChainIterator iter = scopeChain->begin();
     332    ScopeChainIterator end = scopeChain->end();
     333
     334    // FIXME: add scopeDepthIsZero optimization
     335
     336    ASSERT(iter != end);
     337
     338    CodeBlock* codeBlock = callFrame->codeBlock();
     339    Identifier& ident = codeBlock->identifier(property);
     340    JSObject* base;
     341    do {
     342        base = iter->get();
     343        ++iter;
     344        PropertySlot slot(base);
     345        if (base->getPropertySlot(callFrame, ident, slot)) {
     346            JSValue result = slot.getValue(callFrame, ident);
     347            exceptionValue = callFrame->globalData().exception;
     348            if (exceptionValue)
     349                return false;
     350            callFrame->uncheckedR(propDst) = JSValue(result);
     351            // All entries on the scope chain should be EnvironmentRecords (activations etc),
     352            // other then 'with' object, which are directly referenced from the scope chain,
     353            // and the global object. If we hit either an EnvironmentRecord or a global
     354            // object at the end of the scope chain, this is undefined. If we hit a non-
     355            // EnvironmentRecord within the scope chain, pass the base as the this value.
     356            if (iter == end || base->structure()->typeInfo().isEnvironmentRecord())
     357                callFrame->uncheckedR(thisDst) = jsUndefined();
     358            else
     359                callFrame->uncheckedR(thisDst) = JSValue(base);
     360            return true;
     361        }
     362    } while (iter != end);
     363
     364    exceptionValue = createUndefinedVariableError(callFrame, ident);
     365    return false;
     366}
     367
    324368#endif // ENABLE(INTERPRETER)
    325369
     
    410454        return throwError(callFrame, exceptionValue);
    411455
    412     return callFrame->globalData().interpreter->execute(eval, callFrame, callFrame->uncheckedR(codeBlock->thisRegister()).jsValue().toThisObject(callFrame), callFrame->registers() - registerFile->begin() + registerOffset, scopeChain);
     456    JSValue thisValue = callFrame->uncheckedR(codeBlock->thisRegister()).jsValue();
     457    ASSERT(isValidThisObject(thisValue, callFrame));
     458    return callFrame->globalData().interpreter->execute(eval, callFrame, thisValue, callFrame->registers() - registerFile->begin() + registerOffset, scopeChain);
    413459}
    414460
     
    719765JSValue Interpreter::execute(ProgramExecutable* program, CallFrame* callFrame, ScopeChainNode* scopeChain, JSObject* thisObj)
    720766{
     767    ASSERT(isValidThisObject(thisObj, callFrame));
    721768    ASSERT(!scopeChain->globalData->exception);
    722769    ASSERT(!callFrame->globalData().isCollectorBusy());
     
    844891JSValue Interpreter::executeCall(CallFrame* callFrame, JSObject* function, CallType callType, const CallData& callData, JSValue thisValue, const ArgList& args)
    845892{
     893    ASSERT(isValidThisObject(thisValue, callFrame));
    846894    ASSERT(!callFrame->hadException());
    847895    ASSERT(!callFrame->globalData().isCollectorBusy());
     
    11191167}
    11201168
    1121 JSValue Interpreter::execute(EvalExecutable* eval, CallFrame* callFrame, JSObject* thisObj, ScopeChainNode* scopeChain)
     1169JSValue Interpreter::execute(EvalExecutable* eval, CallFrame* callFrame, JSValue thisValue, ScopeChainNode* scopeChain)
    11221170{
    11231171    JSObject* compileError = eval->compile(callFrame, scopeChain);
    11241172    if (UNLIKELY(!!compileError))
    11251173        return checkedReturn(throwError(callFrame, compileError));
    1126     return execute(eval, callFrame, thisObj, m_registerFile.size() + eval->generatedBytecode().m_numParameters + RegisterFile::CallFrameHeaderSize, scopeChain);
     1174    return execute(eval, callFrame, thisValue, m_registerFile.size() + eval->generatedBytecode().m_numParameters + RegisterFile::CallFrameHeaderSize, scopeChain);
    11271175}
    11281176
    1129 JSValue Interpreter::execute(EvalExecutable* eval, CallFrame* callFrame, JSObject* thisObj, int globalRegisterOffset, ScopeChainNode* scopeChain)
     1177JSValue Interpreter::execute(EvalExecutable* eval, CallFrame* callFrame, JSValue thisValue, int globalRegisterOffset, ScopeChainNode* scopeChain)
    11301178{
     1179    ASSERT(isValidThisObject(thisValue, callFrame));
    11311180    ASSERT(!scopeChain->globalData->exception);
    11321181    ASSERT(!callFrame->globalData().isCollectorBusy());
     
    11921241    ASSERT(codeBlock->m_numParameters == 1); // 1 parameter for 'this'.
    11931242    newCallFrame->init(codeBlock, 0, scopeChain, callFrame->addHostCallFrameFlag(), codeBlock->m_numParameters, 0);
    1194     newCallFrame->uncheckedR(newCallFrame->hostThisRegister()) = JSValue(thisObj);
     1243    newCallFrame->uncheckedR(newCallFrame->hostThisRegister()) = thisValue.toThisObject(newCallFrame);
    11951244
    11961245    Profiler** profiler = Profiler::enabledProfilerReference();
     
    26032652
    26042653        vPC += OPCODE_LENGTH(op_resolve_with_base);
     2654        NEXT_INSTRUCTION();
     2655    }
     2656    DEFINE_OPCODE(op_resolve_with_this) {
     2657        /* resolve_with_this thisDst(r) propDst(r) property(id)
     2658
     2659           Searches the scope chain for an object containing
     2660           identifier property, and if one is found, writes the
     2661           retrieved property value to register propDst, and the
     2662           this object to pass in a call to thisDst.
     2663
     2664           If the property is not found, raises an exception.
     2665        */
     2666        if (UNLIKELY(!resolveThisAndProperty(callFrame, vPC, exceptionValue)))
     2667            goto vm_throw;
     2668
     2669        vPC += OPCODE_LENGTH(op_resolve_with_this);
    26052670        NEXT_INSTRUCTION();
    26062671    }
     
    45574622        int thisRegister = vPC[1].u.operand;
    45584623        JSValue thisVal = callFrame->r(thisRegister).jsValue();
    4559         if (thisVal.needsThisConversion())
     4624        if (!thisVal.isCell() || thisVal.isString())
    45604625            callFrame->uncheckedR(thisRegister) = JSValue(thisVal.toThisObject(callFrame));
    45614626
    45624627        vPC += OPCODE_LENGTH(op_convert_this);
    4563         NEXT_INSTRUCTION();
    4564     }
    4565     DEFINE_OPCODE(op_convert_this_strict) {
    4566         /* convert_this_strict this(r)
    4567          
    4568          Takes the value in the 'this' register, and converts it to
    4569          its "this" form if (and only if) "this" is an object with a
    4570          custom this conversion
    4571          
    4572          This opcode should only be used at the beginning of a code
    4573          block.
    4574          */
    4575        
    4576         int thisRegister = vPC[1].u.operand;
    4577         JSValue thisVal = callFrame->r(thisRegister).jsValue();
    4578         if (thisVal.isObject() && thisVal.needsThisConversion())
    4579             callFrame->uncheckedR(thisRegister) = JSValue(thisVal.toStrictThisObject(callFrame));
    4580        
    4581         vPC += OPCODE_LENGTH(op_convert_this_strict);
    45824628        NEXT_INSTRUCTION();
    45834629    }
  • trunk/Source/JavaScriptCore/interpreter/Interpreter.h

    r89465 r91095  
    9898        JSValue executeCall(CallFrame*, JSObject* function, CallType, const CallData&, JSValue thisValue, const ArgList&);
    9999        JSObject* executeConstruct(CallFrame*, JSObject* function, ConstructType, const ConstructData&, const ArgList&);
    100         JSValue execute(EvalExecutable* evalNode, CallFrame* exec, JSObject* thisObj, ScopeChainNode* scopeChain);
     100        JSValue execute(EvalExecutable* evalNode, CallFrame*, JSValue thisValue, ScopeChainNode*);
    101101
    102102        JSValue retrieveArguments(CallFrame*, JSFunction*) const;
     
    122122        JSValue execute(CallFrameClosure&);
    123123
    124         JSValue execute(EvalExecutable*, CallFrame*, JSObject* thisObject, int globalRegisterOffset, ScopeChainNode*);
     124        JSValue execute(EvalExecutable*, CallFrame*, JSValue thisValue, int globalRegisterOffset, ScopeChainNode*);
    125125
    126126#if ENABLE(INTERPRETER)
     
    131131        NEVER_INLINE void resolveBase(CallFrame*, Instruction* vPC);
    132132        NEVER_INLINE bool resolveBaseAndProperty(CallFrame*, Instruction*, JSValue& exceptionValue);
     133        NEVER_INLINE bool resolveThisAndProperty(CallFrame*, Instruction*, JSValue& exceptionValue);
    133134        NEVER_INLINE ScopeChainNode* createExceptionScope(CallFrame*, const Instruction* vPC);
    134135
     
    165166#endif
    166167    };
    167    
     168
     169    // This value must not be an object that would require this conversion (WebCore's global object).
     170    inline bool isValidThisObject(JSValue thisValue, ExecState* exec)
     171    {
     172        return !thisValue.isObject() || thisValue.toThisObject(exec) == thisValue;
     173    }
     174
    168175} // namespace JSC
    169176
  • trunk/Source/JavaScriptCore/jit/JIT.cpp

    r90423 r91095  
    224224        DEFINE_OP(op_create_this)
    225225        DEFINE_OP(op_convert_this)
    226         DEFINE_OP(op_convert_this_strict)
    227226        DEFINE_OP(op_init_lazy_reg)
    228227        DEFINE_OP(op_create_arguments)
     
    311310        DEFINE_OP(op_resolve_skip)
    312311        DEFINE_OP(op_resolve_with_base)
     312        DEFINE_OP(op_resolve_with_this)
    313313        DEFINE_OP(op_ret)
    314314        DEFINE_OP(op_call_put_result)
     
    402402        DEFINE_SLOWCASE_OP(op_construct)
    403403        DEFINE_SLOWCASE_OP(op_convert_this)
    404         DEFINE_SLOWCASE_OP(op_convert_this_strict)
    405404        DEFINE_SLOWCASE_OP(op_div)
    406405        DEFINE_SLOWCASE_OP(op_eq)
  • trunk/Source/JavaScriptCore/jit/JIT.h

    r90875 r91095  
    737737        void emit_op_create_this(Instruction*);
    738738        void emit_op_convert_this(Instruction*);
    739         void emit_op_convert_this_strict(Instruction*);
    740739        void emit_op_create_arguments(Instruction*);
    741740        void emit_op_debug(Instruction*);
     
    822821        void emit_op_resolve_skip(Instruction*);
    823822        void emit_op_resolve_with_base(Instruction*);
     823        void emit_op_resolve_with_this(Instruction*);
    824824        void emit_op_ret(Instruction*);
    825825        void emit_op_ret_object_or_this(Instruction*);
     
    854854        void emitSlow_op_construct(Instruction*, Vector<SlowCaseEntry>::iterator&);
    855855        void emitSlow_op_convert_this(Instruction*, Vector<SlowCaseEntry>::iterator&);
    856         void emitSlow_op_convert_this_strict(Instruction*, Vector<SlowCaseEntry>::iterator&);
    857856        void emitSlow_op_div(Instruction*, Vector<SlowCaseEntry>::iterator&);
    858857        void emitSlow_op_eq(Instruction*, Vector<SlowCaseEntry>::iterator&);
  • trunk/Source/JavaScriptCore/jit/JITOpcodes.cpp

    r90352 r91095  
    709709}
    710710
     711void JIT::emit_op_resolve_with_this(Instruction* currentInstruction)
     712{
     713    JITStubCall stubCall(this, cti_op_resolve_with_this);
     714    stubCall.addArgument(TrustedImmPtr(&m_codeBlock->identifier(currentInstruction[3].u.operand)));
     715    stubCall.addArgument(Imm32(currentInstruction[1].u.operand));
     716    stubCall.call(currentInstruction[2].u.operand);
     717}
     718
    711719void JIT::emit_op_new_func_exp(Instruction* currentInstruction)
    712720{
     
    11371145
    11381146    emitJumpSlowCaseIfNotJSCell(regT0);
    1139     loadPtr(Address(regT0, JSCell::structureOffset()), regT1);
    1140     addSlowCase(branchTest8(NonZero, Address(regT1, Structure::typeInfoFlagsOffset()), TrustedImm32(NeedsThisConversion)));
    1141 }
    1142 
    1143 void JIT::emit_op_convert_this_strict(Instruction* currentInstruction)
    1144 {
    1145     emitGetVirtualRegister(currentInstruction[1].u.operand, regT0);
    1146     Jump notNull = branchTestPtr(NonZero, regT0);
    1147     move(TrustedImmPtr(JSValue::encode(jsNull())), regT0);
    1148     emitPutVirtualRegister(currentInstruction[1].u.operand, regT0);
    1149     Jump setThis = jump();
    1150     notNull.link(this);
    1151     Jump isImmediate = emitJumpIfNotJSCell(regT0);
    1152     loadPtr(Address(regT0, JSCell::structureOffset()), regT1);
    1153     Jump notAnObject = branch8(NotEqual, Address(regT1, Structure::typeInfoTypeOffset()), TrustedImm32(ObjectType));
    1154     addSlowCase(branchTest8(NonZero, Address(regT1, Structure::typeInfoFlagsOffset()), TrustedImm32(NeedsThisConversion)));
    1155     isImmediate.link(this);
    1156     notAnObject.link(this);
    1157     setThis.link(this);
     1147    addSlowCase(branchPtr(Equal, Address(regT0), TrustedImmPtr(m_globalData->jsStringVPtr)));
    11581148}
    11591149
     
    12001190void JIT::emitSlow_op_convert_this(Instruction* currentInstruction, Vector<SlowCaseEntry>::iterator& iter)
    12011191{
    1202     linkSlowCase(iter);
     1192    void* globalThis = m_codeBlock->globalObject()->globalScopeChain()->globalThis.get();
     1193
     1194    linkSlowCase(iter);
     1195    Jump isNotUndefined = branchPtr(NotEqual, regT0, TrustedImmPtr(JSValue::encode(jsUndefined())));
     1196    move(TrustedImmPtr(globalThis), regT0);
     1197    emitPutVirtualRegister(currentInstruction[1].u.operand, regT0);
     1198    emitJumpSlowToHot(jump(), OPCODE_LENGTH(op_convert_this));
     1199
     1200    isNotUndefined.link(this);
    12031201    linkSlowCase(iter);
    12041202    JITStubCall stubCall(this, cti_op_convert_this);
    1205     stubCall.addArgument(regT0);
    1206     stubCall.call(currentInstruction[1].u.operand);
    1207 }
    1208 
    1209 void JIT::emitSlow_op_convert_this_strict(Instruction* currentInstruction, Vector<SlowCaseEntry>::iterator& iter)
    1210 {
    1211     linkSlowCase(iter);
    1212     JITStubCall stubCall(this, cti_op_convert_this_strict);
    12131203    stubCall.addArgument(regT0);
    12141204    stubCall.call(currentInstruction[1].u.operand);
  • trunk/Source/JavaScriptCore/jit/JITOpcodes32_64.cpp

    r90352 r91095  
    11031103}
    11041104
     1105void JIT::emit_op_resolve_with_this(Instruction* currentInstruction)
     1106{
     1107    JITStubCall stubCall(this, cti_op_resolve_with_this);
     1108    stubCall.addArgument(TrustedImmPtr(&m_codeBlock->identifier(currentInstruction[3].u.operand)));
     1109    stubCall.addArgument(Imm32(currentInstruction[1].u.operand));
     1110    stubCall.call(currentInstruction[2].u.operand);
     1111}
     1112
    11051113void JIT::emit_op_new_func_exp(Instruction* currentInstruction)
    11061114{
     
    14451453
    14461454    addSlowCase(branch32(NotEqual, regT1, TrustedImm32(JSValue::CellTag)));
    1447 
    1448     loadPtr(Address(regT0, JSCell::structureOffset()), regT2);
    1449     addSlowCase(branchTest8(NonZero, Address(regT2, Structure::typeInfoFlagsOffset()), TrustedImm32(NeedsThisConversion)));
     1455    addSlowCase(branchPtr(Equal, Address(regT0), TrustedImmPtr(m_globalData->jsStringVPtr)));
    14501456
    14511457    map(m_bytecodeOffset + OPCODE_LENGTH(op_convert_this), thisRegister, regT1, regT0);
    14521458}
    14531459
    1454 void JIT::emit_op_convert_this_strict(Instruction* currentInstruction)
    1455 {
     1460void JIT::emitSlow_op_convert_this(Instruction* currentInstruction, Vector<SlowCaseEntry>::iterator& iter)
     1461{
     1462    void* globalThis = m_codeBlock->globalObject()->globalScopeChain()->globalThis.get();
    14561463    unsigned thisRegister = currentInstruction[1].u.operand;
    1457    
    1458     emitLoad(thisRegister, regT1, regT0);
    1459    
    1460     Jump notNull = branch32(NotEqual, regT1, TrustedImm32(JSValue::EmptyValueTag));
    1461     emitStore(thisRegister, jsNull());
    1462     Jump setThis = jump();
    1463     notNull.link(this);
    1464     Jump isImmediate = branch32(NotEqual, regT1, TrustedImm32(JSValue::CellTag));
    1465     loadPtr(Address(regT0, JSCell::structureOffset()), regT2);
    1466     Jump notAnObject = branch8(NotEqual, Address(regT2, Structure::typeInfoTypeOffset()), TrustedImm32(ObjectType));
    1467     addSlowCase(branchTest8(NonZero, Address(regT2, Structure::typeInfoFlagsOffset()), TrustedImm32(NeedsThisConversion)));
    1468     isImmediate.link(this);
    1469     notAnObject.link(this);
    1470     setThis.link(this);
    1471     map(m_bytecodeOffset + OPCODE_LENGTH(op_convert_this_strict), thisRegister, regT1, regT0);
    1472 }
    1473 
    1474 void JIT::emitSlow_op_convert_this(Instruction* currentInstruction, Vector<SlowCaseEntry>::iterator& iter)
    1475 {
    1476     unsigned thisRegister = currentInstruction[1].u.operand;
    1477 
    1478     linkSlowCase(iter);
    1479     linkSlowCase(iter);
    1480 
     1464
     1465    linkSlowCase(iter);
     1466    Jump isNotUndefined = branch32(NotEqual, regT1, TrustedImm32(JSValue::UndefinedTag));
     1467    move(TrustedImmPtr(globalThis), regT0);
     1468    move(TrustedImm32(JSValue::CellTag), regT1);
     1469    emitStore(thisRegister, regT1, regT0);
     1470    emitJumpSlowToHot(jump(), OPCODE_LENGTH(op_convert_this));
     1471
     1472    isNotUndefined.link(this);
     1473    linkSlowCase(iter);
    14811474    JITStubCall stubCall(this, cti_op_convert_this);
    1482     stubCall.addArgument(regT1, regT0);
    1483     stubCall.call(thisRegister);
    1484 }
    1485 
    1486 void JIT::emitSlow_op_convert_this_strict(Instruction* currentInstruction, Vector<SlowCaseEntry>::iterator& iter)
    1487 {
    1488     unsigned thisRegister = currentInstruction[1].u.operand;
    1489    
    1490     linkSlowCase(iter);
    1491    
    1492     JITStubCall stubCall(this, cti_op_convert_this_strict);
    14931475    stubCall.addArgument(regT1, regT0);
    14941476    stubCall.call(thisRegister);
  • trunk/Source/JavaScriptCore/jit/JITStubs.cpp

    r90938 r91095  
    12811281    CallFrame* callFrame = stackFrame.callFrame;
    12821282
     1283    ASSERT(!v1.isCell() || v1.isString());
     1284
    12831285    JSObject* result = v1.toThisObject(callFrame);
    1284     CHECK_FOR_EXCEPTION_AT_END();
    1285     return JSValue::encode(result);
    1286 }
    1287 
    1288 DEFINE_STUB_FUNCTION(EncodedJSValue, op_convert_this_strict)
    1289 {
    1290     STUB_INIT_STACK_FRAME(stackFrame);
    1291    
    1292     JSValue v1 = stackFrame.args[0].jsValue();
    1293     CallFrame* callFrame = stackFrame.callFrame;
    1294     ASSERT(v1.asCell()->structure()->typeInfo().needsThisConversion());
    1295     JSValue result = v1.toStrictThisObject(callFrame);
    12961286    CHECK_FOR_EXCEPTION_AT_END();
    12971287    return JSValue::encode(result);
     
    30373027}
    30383028
     3029DEFINE_STUB_FUNCTION(EncodedJSValue, op_resolve_with_this)
     3030{
     3031    STUB_INIT_STACK_FRAME(stackFrame);
     3032
     3033    CallFrame* callFrame = stackFrame.callFrame;
     3034    ScopeChainNode* scopeChain = callFrame->scopeChain();
     3035
     3036    ScopeChainIterator iter = scopeChain->begin();
     3037    ScopeChainIterator end = scopeChain->end();
     3038
     3039    // FIXME: add scopeDepthIsZero optimization
     3040
     3041    ASSERT(iter != end);
     3042
     3043    Identifier& ident = stackFrame.args[0].identifier();
     3044    JSObject* base;
     3045    do {
     3046        base = iter->get();
     3047        ++iter;
     3048        PropertySlot slot(base);
     3049        if (base->getPropertySlot(callFrame, ident, slot)) {
     3050            JSValue result = slot.getValue(callFrame, ident);
     3051            CHECK_FOR_EXCEPTION_AT_END();
     3052
     3053            // All entries on the scope chain should be EnvironmentRecords (activations etc),
     3054            // other then 'with' object, which are directly referenced from the scope chain,
     3055            // and the global object. If we hit either an EnvironmentRecord or a global
     3056            // object at the end of the scope chain, this is undefined. If we hit a non-
     3057            // EnvironmentRecord within the scope chain, pass the base as the this value.
     3058            if (iter == end || base->structure()->typeInfo().isEnvironmentRecord())
     3059                callFrame->registers()[stackFrame.args[1].int32()] = jsUndefined();
     3060            else
     3061                callFrame->registers()[stackFrame.args[1].int32()] = JSValue(base);
     3062            return JSValue::encode(result);
     3063        }
     3064    } while (iter != end);
     3065
     3066    stackFrame.globalData->exception = createUndefinedVariableError(callFrame, ident);
     3067    VM_THROW_EXCEPTION_AT_END();
     3068    return JSValue::encode(JSValue());
     3069}
     3070
    30393071DEFINE_STUB_FUNCTION(JSObject*, op_new_func_exp)
    30403072{
  • trunk/Source/JavaScriptCore/jit/JITStubs.h

    r90371 r91095  
    323323    EncodedJSValue JIT_STUB cti_op_create_this(STUB_ARGS_DECLARATION);
    324324    EncodedJSValue JIT_STUB cti_op_convert_this(STUB_ARGS_DECLARATION);
    325     EncodedJSValue JIT_STUB cti_op_convert_this_strict(STUB_ARGS_DECLARATION);
    326325    EncodedJSValue JIT_STUB cti_op_create_arguments(STUB_ARGS_DECLARATION);
    327326    EncodedJSValue JIT_STUB cti_op_create_arguments_no_params(STUB_ARGS_DECLARATION);
     
    373372    EncodedJSValue JIT_STUB cti_op_resolve_skip(STUB_ARGS_DECLARATION);
    374373    EncodedJSValue JIT_STUB cti_op_resolve_with_base(STUB_ARGS_DECLARATION);
     374    EncodedJSValue JIT_STUB cti_op_resolve_with_this(STUB_ARGS_DECLARATION);
    375375    EncodedJSValue JIT_STUB cti_op_rshift(STUB_ARGS_DECLARATION);
    376376    EncodedJSValue JIT_STUB cti_op_strcat(STUB_ARGS_DECLARATION);
  • trunk/Source/JavaScriptCore/runtime/CallData.cpp

    r70703 r91095  
    3636{
    3737    ASSERT(callType == CallTypeJS || callType == CallTypeHost);
     38    ASSERT(isValidThisObject(thisValue, exec));
    3839    return exec->interpreter()->executeCall(exec, asObject(functionObject), callType, callData, thisValue, args);
    3940}
  • trunk/Source/JavaScriptCore/runtime/Completion.cpp

    r81904 r91095  
    6060    }
    6161
    62     JSObject* thisObj = (!thisValue || thisValue.isUndefinedOrNull()) ? exec->dynamicGlobalObject() : thisValue.toObject(exec);
     62    if (!thisValue || thisValue.isUndefinedOrNull())
     63        thisValue = exec->dynamicGlobalObject();
     64    JSObject* thisObj = thisValue.toThisObject(exec);
    6365
    6466    JSValue result = exec->interpreter()->execute(program, exec, scopeChain, thisObj);
  • trunk/Source/JavaScriptCore/runtime/JSActivation.h

    r84556 r91095  
    7070
    7171    protected:
    72         static const unsigned StructureFlags = OverridesGetOwnPropertySlot | NeedsThisConversion | OverridesVisitChildren | OverridesGetPropertyNames | JSVariableObject::StructureFlags;
     72        static const unsigned StructureFlags = IsEnvironmentRecord | OverridesGetOwnPropertySlot | OverridesVisitChildren | OverridesGetPropertyNames | JSVariableObject::StructureFlags;
    7373
    7474    private:
  • trunk/Source/JavaScriptCore/runtime/JSObject.cpp

    r87826 r91095  
    148148                MarkedArgumentBuffer args;
    149149                args.append(value);
    150                 call(exec, setterFunc, callType, callData, this, args);
     150
     151                // If this is WebCore's global object then we need to substitute the shell.
     152                call(exec, setterFunc, callType, callData, this->toThisObject(exec), args);
    151153                return;
    152154            }
  • trunk/Source/JavaScriptCore/runtime/JSStaticScopeObject.h

    r84556 r91095  
    5151
    5252    protected:
    53         static const unsigned StructureFlags = OverridesGetOwnPropertySlot | NeedsThisConversion | OverridesVisitChildren | OverridesGetPropertyNames | JSVariableObject::StructureFlags;
     53        static const unsigned StructureFlags = IsEnvironmentRecord | OverridesGetOwnPropertySlot | OverridesVisitChildren | OverridesGetPropertyNames | JSVariableObject::StructureFlags;
    5454
    5555    private:
  • trunk/Source/JavaScriptCore/runtime/JSString.h

    r86499 r91095  
    329329        static Structure* createStructure(JSGlobalData& globalData, JSValue proto)
    330330        {
    331             return Structure::create(globalData, proto, TypeInfo(StringType, OverridesGetOwnPropertySlot | NeedsThisConversion), AnonymousSlotCount, &s_info);
     331            return Structure::create(globalData, proto, TypeInfo(StringType, OverridesGetOwnPropertySlot), AnonymousSlotCount, &s_info);
    332332        }
    333333       
  • trunk/Source/JavaScriptCore/runtime/JSTypeInfo.h

    r87586 r91095  
    3939    static const unsigned OverridesHasInstance = 1 << 2;
    4040    static const unsigned ImplementsDefaultHasInstance = 1 << 3;
    41     static const unsigned NeedsThisConversion = 1 << 4;
     41    static const unsigned IsEnvironmentRecord = 1 << 4;
    4242    static const unsigned OverridesGetOwnPropertySlot = 1 << 5;
    4343    static const unsigned OverridesVisitChildren = 1 << 6;
     
    6565        bool masqueradesAsUndefined() const { return m_flags & MasqueradesAsUndefined; }
    6666        bool implementsHasInstance() const { return m_flags & ImplementsHasInstance; }
     67        bool isEnvironmentRecord() const { return m_flags & IsEnvironmentRecord; }
    6768        bool overridesHasInstance() const { return m_flags & OverridesHasInstance; }
    68         bool needsThisConversion() const { return m_flags & NeedsThisConversion; }
    6969        bool overridesGetOwnPropertySlot() const { return m_flags & OverridesGetOwnPropertySlot; }
    7070        bool overridesVisitChildren() const { return m_flags & OverridesVisitChildren; }
  • trunk/Source/JavaScriptCore/runtime/JSValue.h

    r88587 r91095  
    207207        void put(ExecState*, unsigned propertyName, JSValue);
    208208
    209         bool needsThisConversion() const;
    210209        JSObject* toThisObject(ExecState*) const;
    211210        JSValue toStrictThisObject(ExecState*) const;
  • trunk/Source/JavaScriptCore/runtime/JSVariableObject.h

    r90187 r91095  
    6666       
    6767    protected:
    68         static const unsigned StructureFlags = OverridesGetPropertyNames | JSObject::StructureFlags;
     68        static const unsigned StructureFlags = OverridesGetPropertyNames | JSNonFinalObject::StructureFlags;
    6969
    7070        JSVariableObject(JSGlobalData& globalData, Structure* structure, SymbolTable* symbolTable, Register* registers)
  • trunk/Source/JavaScriptCore/runtime/PropertySlot.cpp

    r60392 r91095  
    3535    CallData callData;
    3636    CallType callType = m_data.getterFunc->getCallData(callData);
    37     return call(exec, m_data.getterFunc, callType, callData, thisValue(), exec->emptyList());
     37   
     38    // Only objects can have accessor properties.
     39    // If the base is WebCore's global object then we need to substitute the shell.
     40    ASSERT(m_slotBase.isObject());
     41    return call(exec, m_data.getterFunc, callType, callData, m_thisValue.toThisObject(exec), exec->emptyList());
    3842}
    3943
  • trunk/Source/JavaScriptCore/runtime/PropertySlot.h

    r80179 r91095  
    213213        unsigned index() const { return m_data.index; }
    214214
    215         JSValue thisValue() const { return m_thisValue; }
    216 
    217215        GetValueFunc customGetter() const
    218216        {
  • trunk/Source/JavaScriptCore/runtime/StrictEvalActivation.h

    r78732 r91095  
    3737    virtual JSObject* toThisObject(ExecState*) const;
    3838    virtual JSValue toStrictThisObject(ExecState*) const;
     39
     40    static Structure* createStructure(JSGlobalData& globalData, JSValue prototype)
     41    {
     42        return Structure::create(globalData, prototype, TypeInfo(ObjectType, StructureFlags), AnonymousSlotCount, &s_info);
     43    }
     44   
     45protected:
     46    static const unsigned StructureFlags = IsEnvironmentRecord | JSNonFinalObject::StructureFlags;
    3947};
    4048
  • trunk/Source/JavaScriptCore/runtime/Structure.h

    r90273 r91095  
    290290    }
    291291
    292     inline bool JSValue::needsThisConversion() const
    293     {
    294         if (UNLIKELY(!isCell()))
    295             return true;
    296         return asCell()->structure()->typeInfo().needsThisConversion();
    297     }
    298 
    299292    ALWAYS_INLINE void MarkStack::internalAppend(JSCell* cell)
    300293    {
  • trunk/Source/JavaScriptCore/tests/mozilla/ecma/String/15.5.4.6-2.js

    r11995 r91095  
    185185                                  eval("var obj = new Object(); obj.indexOf = String.prototype.indexOf; obj.indexOf('bject')") );
    186186
    187     array[item++] = new TestCase( SECTION,
    188                                   "var f = new Object( String.prototype.indexOf ); f('"+GLOBAL+"')",
    189                                   0,
    190                                   eval("var f = new Object( String.prototype.indexOf ); f('"+GLOBAL+"')") );
     187// This correctly throws, due to ES5 15.5.4.7 step 1
     188//    array[item++] = new TestCase( SECTION,
     189//                                  "var f = new Object( String.prototype.indexOf ); f('"+GLOBAL+"')",
     190//                                  0,
     191//                                  eval("var f = new Object( String.prototype.indexOf ); f('"+GLOBAL+"')") );
    191192
    192193    array[item++] = new TestCase( SECTION,
  • trunk/Source/WebCore/ChangeLog

    r91093 r91095  
     12011-07-14  Gavin Barraclough  <barraclough@apple.com>
     2
     3        https://bugs.webkit.org/show_bug.cgi?id=64250
     4        Global strict mode function leaking global object as "this".
     5
     6        Reviewed by Oliver Hunt.
     7
     8        * bindings/js/JSMainThreadExecState.h:
     9        (WebCore::JSMainThreadExecState::call):
     10        * bindings/scripts/CodeGeneratorJS.pm:
     11        (GenerateHeader):
     12            - Change call to pass DOM Window shell, instead of the global varaible object.
     13
    1142011-07-15  Brian Salomon  <bsalomon@google.com>
    215
  • trunk/Source/WebCore/WebCore.xcodeproj/project.pbxproj

    r91056 r91095  
    4646
    4747/* Begin PBXBuildFile section */
     48                00022E6913CE1BBA00282D5B /* CharacterReferenceParserInlineMethods.h in Headers */ = {isa = PBXBuildFile; fileRef = 00022E6813CE1BBA00282D5B /* CharacterReferenceParserInlineMethods.h */; };
    4849                0014628A103CD1DE000B20DB /* OriginAccessEntry.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 00146288103CD1DE000B20DB /* OriginAccessEntry.cpp */; };
    4950                0014628B103CD1DE000B20DB /* OriginAccessEntry.h in Headers */ = {isa = PBXBuildFile; fileRef = 00146289103CD1DE000B20DB /* OriginAccessEntry.h */; };
     
    5859                00D0464A13C4D14500326FCC /* XMLCharacterReferenceParser.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 00D0464813C4D14500326FCC /* XMLCharacterReferenceParser.cpp */; };
    5960                00D0464B13C4D14500326FCC /* XMLCharacterReferenceParser.h in Headers */ = {isa = PBXBuildFile; fileRef = 00D0464913C4D14500326FCC /* XMLCharacterReferenceParser.h */; };
    60                 00022E6913CE1BBA00282D5B /* CharacterReferenceParserInlineMethods.h in Headers */ = {isa = PBXBuildFile; fileRef = 00022E6813CE1BBA00282D5B /* CharacterReferenceParserInlineMethods.h */; };
    6161                052BFCE9128ABF1500FD338D /* GeolocationClientMock.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 052BFCE8128ABF1500FD338D /* GeolocationClientMock.cpp */; };
    6262                052BFCEB128ABF2100FD338D /* GeolocationClientMock.h in Headers */ = {isa = PBXBuildFile; fileRef = 052BFCEA128ABF2100FD338D /* GeolocationClientMock.h */; settings = {ATTRIBUTES = (Private, ); }; };
     
    64066406
    64076407/* Begin PBXFileReference section */
     6408                00022E6813CE1BBA00282D5B /* CharacterReferenceParserInlineMethods.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = CharacterReferenceParserInlineMethods.h; sourceTree = "<group>"; };
    64086409                00146288103CD1DE000B20DB /* OriginAccessEntry.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = OriginAccessEntry.cpp; sourceTree = "<group>"; };
    64096410                00146289103CD1DE000B20DB /* OriginAccessEntry.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = OriginAccessEntry.h; sourceTree = "<group>"; };
     
    64186419                00D0464813C4D14500326FCC /* XMLCharacterReferenceParser.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = XMLCharacterReferenceParser.cpp; sourceTree = "<group>"; };
    64196420                00D0464913C4D14500326FCC /* XMLCharacterReferenceParser.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = XMLCharacterReferenceParser.h; sourceTree = "<group>"; };
    6420                 00022E6813CE1BBA00282D5B /* CharacterReferenceParserInlineMethods.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = CharacterReferenceParserInlineMethods.h; sourceTree = "<group>"; };
    64216421                052BFCE8128ABF1500FD338D /* GeolocationClientMock.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = GeolocationClientMock.cpp; path = mock/GeolocationClientMock.cpp; sourceTree = "<group>"; };
    64226422                052BFCEA128ABF2100FD338D /* GeolocationClientMock.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = GeolocationClientMock.h; path = mock/GeolocationClientMock.h; sourceTree = "<group>"; };
  • trunk/Source/WebCore/bindings/js/JSMainThreadExecState.h

    r81230 r91095  
    4646    {
    4747        JSMainThreadExecState currentState(exec);
     48        // Ensure DOM global object is unwrapped to the shell.
     49        if (thisValue.isObject())
     50            thisValue = thisValue.toThisObject(exec);
    4851        return JSC::call(exec, functionObject, callType, callData, thisValue, args);
    4952    };
  • trunk/Source/WebCore/bindings/scripts/CodeGeneratorJS.pm

    r90717 r91095  
    746746    if ($interfaceName eq "DOMWindow") {
    747747        $structureFlags{"JSC::ImplementsHasInstance"} = 1;
    748         $structureFlags{"JSC::NeedsThisConversion"} = 1;
    749748    }
    750749    push(@headerContent,
  • trunk/Source/WebKit/mac/ChangeLog

    r90948 r91095  
     12011-07-14  Gavin Barraclough  <barraclough@apple.com>
     2
     3        https://bugs.webkit.org/show_bug.cgi?id=64250
     4        Global strict mode function leaking global object as "this".
     5
     6        Reviewed by Oliver Hunt.
     7
     8        * Plugins/Hosted/NetscapePluginInstanceProxy.mm:
     9        (WebKit::NetscapePluginInstanceProxy::invoke):
     10        (WebKit::NetscapePluginInstanceProxy::invokeDefault):
     11            - Change call to pass DOM Window shell, instead of the global varaible object.
     12
    1132011-07-13  Joseph Pecoraro  <joepeck@webkit.org>
    214
  • trunk/Source/WebKit/mac/Plugins/Hosted/NetscapePluginInstanceProxy.mm

    r89001 r91095  
    922922    RefPtr<JSGlobalData> globalData = pluginWorld()->globalData();
    923923    globalData->timeoutChecker.start();
    924     JSValue value = call(exec, function, callType, callData, object, argList);
     924    JSValue value = call(exec, function, callType, callData, object->toThisObject(exec), argList);
    925925    globalData->timeoutChecker.stop();
    926926       
     
    957957    RefPtr<JSGlobalData> globalData = pluginWorld()->globalData();
    958958    globalData->timeoutChecker.start();
    959     JSValue value = call(exec, object, callType, callData, object, argList);
     959    JSValue value = call(exec, object, callType, callData, object->toThisObject(exec), argList);
    960960    globalData->timeoutChecker.stop();
    961961   
  • trunk/Source/WebKit2/ChangeLog

    r91085 r91095  
     12011-07-14  Gavin Barraclough  <barraclough@apple.com>
     2
     3        https://bugs.webkit.org/show_bug.cgi?id=64250
     4        Global strict mode function leaking global object as "this".
     5
     6        Reviewed by Oliver Hunt.
     7
     8        * WebProcess/Plugins/Netscape/NPJSObject.cpp:
     9        (WebKit::NPJSObject::invoke):
     10            - Change call to pass DOM Window shell, instead of the global varaible object.
     11
    1122011-07-15  Anders Carlsson  <andersca@apple.com>
    213
  • trunk/Source/WebKit2/WebProcess/Plugins/Netscape/NPJSObject.cpp

    r87685 r91095  
    292292
    293293    exec->globalData().timeoutChecker.start();
    294     JSValue value = JSC::call(exec, function, callType, callData, m_jsObject.get(), argumentList);
     294    JSValue value = JSC::call(exec, function, callType, callData, m_jsObject->toThisObject(exec), argumentList);
    295295    exec->globalData().timeoutChecker.stop();
    296296
Note: See TracChangeset for help on using the changeset viewer.